C# ModelState.IsValid忽略[Required]属性

C# ModelState.IsValid忽略[Required]属性,c#,asp.net-mvc,entity-framework,validation,asp.net-mvc-5,C#,Asp.net Mvc,Entity Framework,Validation,Asp.net Mvc 5,出于某种原因,签入我的控制器的ModelState.IsValid将返回true,即使我的entity和viewmodel属性在字段上的[Required]属性为0 这是实体: public class Ticket { public int Id { get; set; } [Required] public int FareId { get; set; } public virtual Fare Fare { get; set; } } 以及我的视图使用的

出于某种原因,签入我的控制器的
ModelState.IsValid
将返回true,即使我的entity和viewmodel属性在字段上的[Required]属性为0

这是实体:

public class Ticket
{
    public int Id { get; set; }

    [Required]
    public int FareId { get; set; }
    public virtual Fare Fare { get; set; }
}
以及我的视图使用的viewmodel:

public class BaseTicketViewModel
{
    [Required, Display(Name = "Fare")]
    public int FareId { get; set; }
    public Fare Fare { get; set; }
}
在我看来,我使用了许多单选按钮而不是下拉列表,这可能是问题的原因,我只是不知道如何:

<div class="form-group">
    @Html.LabelFor(model => model.FareId, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @foreach (FareGroup fareGroup in Model.FareList)
        {
            <h5><strong>@fareGroup.Name</strong></h5>

            foreach (Fare fare in fareGroup.Fares)
            {
                <label class="checkbox-inline">
                    @Html.RadioButtonFor(model => model.FareId, fare.Id)
                    @fare.Name
                </label>
            }
        }
        @Html.ValidationMessageFor(model => model.FareId, "", new { @class = "text-danger" })
    </div>
</div>

@LabelFor(model=>model.FareId,htmlAttributes:new{@class=“controllabel col-md-2”})
@foreach(模型中的FareGroup FareList)
{
@fareGroup.Name
foreach(票价组中的票价。票价)
{
@Html.radioButton(model=>model.FareId,fare.Id)
@车费.姓名
}
}
@Html.ValidationMessageFor(model=>model.FareId,“,new{@class=“text danger”})
当我提交表单而不选择票价时,我的控制器会引发一个
DbUpdateException
,它告诉我INSERT语句与外键约束冲突,基本上ID为0的
票价不存在:

{“INSERT语句与外键约束冲突 “FK_dbo.Tickets_dbo.Fares_FareId”。数据库中发生冲突 “修订”,表“dbo.票价”,第列 “Id”。\r\n语句已终止。“}

根据我的理解,如果viewmodel/ticket实体上的
FareId
属性为0,则
ModelState.IsValid
应为false,因为该属性上的
[必需]
注释将默认为0,因为它们是值类型。因此,它满足了Required属性的要求,尽管对于您的场景来说相当糟糕

文件规定:

RequiredAttribute属性指定窗体上的字段 验证后,该字段必须包含一个值。验证异常 如果属性为null、包含空字符串(“”),或 仅包含空白字符

由于int不可为null,并且显然不能为空字符串,因此它通过了验证

[Required]
public int? FareId { get; set; }
如果要确保Id不是默认值,可以使用Range属性,但如果Id为0,则会导致问题

[Range(1, int.MaxValue,
   ErrorMessage = "Value for {0} must be between {1} and {2}.")]
最后,正如Chris Peterson指出的那样,如果FareId可为null,它将能够正确地利用所需的属性,因为如果没有发布值,它将默认为null,从而触发验证

[Required]
public int? FareId { get; set; }

粘贴控制器的代码。
0
是有效的int。由于
int
不能为空,您将始终通过
必需的测试。您需要一个
int?
,或者一个可为空的int。0仍然是一个值。当它说Required is时,意味着它不能为Null。为了这篇文章的目的,我缩减了我的实体/视图模型,并且我还有另一个名为
TimetableId
的属性,它的定义方式与
FareId
相同,只是它在视图中由下拉列表表示。当您没有选择任何内容时,它也会发送值
0
,但是
ModelState.IsValid
会像我预期的那样工作(当
TimetableId==0
时返回false)。有什么区别?@ChrisWhite必须有另一种情况发生在TimetableId上,但由于您没有发布任何有关TimetableId的代码,因此无法告诉您区别是什么。另一种选择是使用具有所需属性的可为null的int。