ASP.NET 不可空类型 (Int32) 的 MVC 5 模型验证

ASP.NET MVC 5 model validation for non-nullable types (Int32)

我正在开发一个 ASP.NET MVC 5 应用程序,项目所有者担心 "under-posting" 由验证不可空类型引起的问题(如 http://bradwilson.typepad.com/blog/2010/01/input-validation-vs-model-validation-in-aspnet-mvc.html and http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api 中所述)。

我创建了一个测试用例来在 ASP.NET MVC 5 中复制这个问题,但没有成功。

型号:

public class ContactModel
{
    [Required]
    public Int32 data1 { get; set; }

    public Int32 data2 { get; set; }
}

查看:

<div class="form-group">
    @Html.LabelFor(model => model.data1)
    <div>
        @Html.EditorFor(model => model.data1)
    </div>
</div>  
<div>
    @Html.LabelFor(model => model.data2)
    <div>
        @Html.EditorFor(model => model.data2)
    </div>
</div>

控制器:

public ActionResult Index(Models.ContactModel contact)
{
    if (ModelState.IsValid)
    {
        Response.Write("modelstate is valid<br>");

        return View();
    }
    else
    {
        Response.Write("modelstate is invalid<br>");

        return View();
    }
}

似乎当 data1data2 在 post 中为 null 时,它们在模型 (contact) 中的值将为 0。但是,ModelState.IsValid 也将是 false(而不是两篇文章中显示的 true)。

我有:

第二篇文章显示的内容:

我找不到任何关于 ASP.NET MVC 中模型验证工作方式变化的信息,所以我猜我的测试用例有问题。任何想法和建议都将受到赞赏。

您的 ModelState 为假的原因是因为 post 提供了模型中每个 属性 的表单值。本质上,模型绑定系统正在检查 data1 和 data2 字段的有效性,因为您有 @Html.EditorFor helpers explicitly 为视图中的两个属性编写(因此没有 underposting 实际上正在进行中)。

我确实成功地复制了文章中的不足 posting 问题。只需删除您视图中的一个 EditorFor 助手,这样您实际上就处于 posting 之下。有两个助手在场,就没有 underposting 的事情发生了。所以视图现在看起来像这样(注意我为两个属性添加了验证助手以在视图中获得关于正在发生的事情的反馈):

查看:

<div class="form-group">
    @Html.LabelFor(model => model.data1)
    <div>
        @Html.EditorFor(model => model.data1)
        @Html.ValidationMessageFor(model => model.data1)
        @Html.ValidationMessageFor(model => model.data2)
    </div>
</div>

确保完全关闭 data2 属性 的 @Html.EditorFor 助手。现在在表单字段中填写零(当然现在您只会在视图中看到一个表单字段),然后 post 进行操作。

在这种情况下,ModelState 将返回为 true,即使只有一个表单字段被 posted。如果有人做不到 post,那可不是什么好结果!所以这里是(稍微修改过的)原始模型class,如果表单字段不在您的表单中,则会出现 underposting 问题(请注意 Required 属性在此方面没有任何区别两个属性都是值类型的情况):

//You could add the Required attribute or not, doesn't matter at this point.
//The concern here is that the Modelstate will still come back as Valid
//in the case of a form field being left off of your form (or someone underposts).
//So to replicate underposting issues, make sure to comment or delete
//at least one Html.EditorFor helper in the view.

//[Required] Underposting will occur regardless if this is marked required or not,
//so be careful if someone does underpost your form.
public Int32 data1 { get; set; }

//[Required]
public Int32 data2 { get; set; }

现在,如果您想解决 posting 不足的问题,请使用以下解决方案: 只需将这两个属性标记为必需,并按照您提供的文章中所述使它们可为空,如下所示:

[Required]
public Int32? data1 { get; set; }

[Required]
public Int32? data2 { get; set; }

现在,当视图 posted 时缺少 @Html.EditorFor 助手或缺少表单字段,ModelState Validation 将返回为 false,并且您将受到保护,免受 underposting 问题。