【问题标题】:ModelState.IsValid ignoring [Required] attributeModelState.IsValid 忽略 [必需] 属性
【发布时间】:2015-03-26 12:07:22
【问题描述】:

出于某种原因,我的控制器中的ModelState.IsValid 检查返回 true,即使我的实体和视图模型属性在字段上具有 [Required] 属性为 0。

这是实体:

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

    [Required]
    public int FareId { get; set; }
    public virtual Fare Fare { get; set; }
}

以及我的视图使用的视图模型:

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>

当我在未选择票价的情况下提交表单时,我的控制器会引发 DbUpdateException,它告诉我 INSERT 语句与 FOREIGN KEY 约束冲突,基本上是 ID 为 0 的 Fare 不存在:

{"INSERT 语句与 FOREIGN KEY 约束冲突 “FK_dbo.Tickets_dbo.Fares_FareId”。数据库发生冲突 “已编辑”,表“dbo.Fares”,列 'Id'。\r\n语句已终止。"}

据我了解,如果 viewmodel/ticket 实体上的 FareId 属性为 0,那么由于该属性上的 [Required] 注释,ModelState.IsValid 应该为 false?

【问题讨论】:

  • 粘贴控制器的代码。
  • 0 是一个有效的整数。由于int 不能为空,您将始终通过Required 测试。你想要一个int?,或者一个可以为空的int。
  • 那么 0 仍然是一个值。当它说Required时意味着它不能为Null。

标签: c# asp.net-mvc entity-framework validation asp.net-mvc-5


【解决方案1】:

Integers 将默认为 0,因为它们是值类型。因此,它满足了Required 属性的要求,尽管对于您的方案来说相当差。

Required Attribute 文档指出:

RequiredAttribute 属性指定当表单上的字段 已验证,该字段必须包含一个值。验证异常 如果属性为 null、包含空字符串 ("") 或 仅包含空白字符。

由于您的 int 不可为空,而且它显然不能是空字符串,因此它通过了验证。

如果您想确保您的 Id 不是默认值,您可以使用 Range 属性,但如果您的 Id 确实为 0,这会给您带来问题。

[Range(1, int.MaxValue,
   ErrorMessage = "Value for {0} must be between {1} and {2}.")]

最后,正如 Chris Peterson 所指出的,如果FareId 可以为空,它将能够正确利用Required 属性,因为如果未发布值,它将默认为空,从而触发验证。

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

【讨论】:

  • 为了这篇文章的目的,我修剪了我的实体/视图模型,我还有另一个名为 TimetableId 的属性,其定义方式与 FareId 相同,只是它由下拉列表表示风景。 also 在您没有选择任何内容时发送值0,但ModelState.IsValid 然后按我的预期工作(当TimetableId == 0 时返回false)。有什么区别?
  • @ChrisWhite TimetableId 肯定会发生另一种情况,但是由于您尚未发布任何有关 TimetableId 的代码,因此无法告诉您有什么区别。
  • 另一种选择是使用具有所需属性的可为空的 int。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2019-05-27
相关资源
最近更新 更多