Asp.net ModelState.IsValid为true,但POST数据中缺少[Required]属性

Asp.net ModelState.IsValid为true,但POST数据中缺少[Required]属性,asp.net,asp.net-mvc-3,Asp.net,Asp.net Mvc 3,我的视图模型有一个[Required]不可为null的int属性,由DropDownListFor选择。如果要从中选择的列表为空,则ModelState.IsValid为true 我的模型具有必需的int属性: public class MyModel { [Required] public int PickedValue { get; set;} IEnumerable<SelectListItem> Items { get; set; } } 在我的

我的视图模型有一个[Required]不可为null的int属性,由DropDownListFor选择。如果要从中选择的列表为空,则ModelState.IsValid为true

我的模型具有必需的int属性:

public class MyModel
{
    [Required]
    public int PickedValue  { get; set;}

    IEnumerable<SelectListItem> Items { get; set; }
}
在我的控制器中,如果
model.Items
列表为空(没有可供选择的元素),
ModelState.IsValid
为真:

[HttpPost]
public ActionResult Create( MyModel model )
{
    if( ModelState.IsValid )
    {
        // true, and ModelState.Keys doesn't contain PickedValue because it was never POSTed.
    }
    //...
 }
现在,如果:

  • PickedValue
    可为
    null
    int?
    ),或
  • 如果我的
    -
    @Html.DropDownListFor(model=>model.PickedValue,model.Items,“
    )中有一个空项,或者
  • 如果启用了客户端验证(因为从未触发该操作)

  • 是否有办法强制
    ModelState.IsValid
    false
    ,如果
    MyModel
    的某些属性是
    [必需的]
    ,但POST数据中缺少?这不应该是默认行为吗?

    在您的情况下,我认为最好将PickedValue设置为可为null的int。如果DropDownList可能没有项目,则null应该是PickedValue的一个可能值

    回复评论


    这是有道理的,但并没有回答我原来的问题。。。有没有 如果MyModel的某些 属性是[必需的],但POST数据中缺少属性? 这不应该是默认行为吗

    当涉及int、double、bools和其他不能有空值的原语时,当DefaultModelBinder在HTTP请求中没有收到它们的数据时,它仍然必须构造一个模型实例。因此,构建模型并将属性初始化为其默认值。如果是int,这意味着它将被初始化为零。由于HTTP请求中未接收任何内容,这意味着从未设置int,因此它将始终为零。您是否尝试过为int指定[Range]验证器而不是[Required]验证器?这应该验证它不是零:

    [Range(1, int.MaxValue)]
    public int PickedValue  { get; set; }
    
    我希望避免更改模型,因为它已经是一种常见的模式 我的代码中的模式。。。加上使模型中的属性可为null 强制它不为空似乎违反直觉

    仅仅因为它是代码中的常见模式并不意味着它是正确的。我必须重申我最初的回答:如果您的下拉列表可能没有任何项目,那么您的模型应该允许其所选值为
    null


    这就是为什么最好使用单独的实体和视图模型层的原因之一。在域实体中,可能需要关系。但是,当用户第一次看到一个表单来选择该关系时,您必须为他们提供一个默认的或空的所选下拉项。在这种情况下,实体中的外键可能是int,但viewmodel中的表示形式应该是
    可为null的
    。仅出于这个原因,我不认为仅仅为了确保某个东西不为null而将其设置为null是违反直觉的。您可以在viewmodel中将其设置为空,这样您就可以给用户一个带有空值的表单,并要求他们填写。

    这是有道理的,但没有回答我最初的问题(我希望避免更改模型,因为它已经是我代码中的常见模式)。另外,将模型中的属性设置为null以强制其不为null似乎是违反直觉的。对于外键关系来说,Range属性是一个巧妙的技巧——它可以工作,尽管它很难看:)对于具有单独的实体和视图模型层,这本质上意味着将类增加一倍,重构和维护的成本增加一倍。这远远超出了我为这个项目提供的资源。你找到答案了吗?@gawkface我想这就是DefaultModelBinder的工作原理。“我想如果你需要不同的行为,你应该实现你自己的。谢谢你抽出时间来引导我找到答案,”亚历克斯说
    [Range(1, int.MaxValue)]
    public int PickedValue  { get; set; }