为什么验证不适用于 Html.TextBoxFor 但在使用 Html.EditorFor 时有效?

Why validation is not working with Html.TextBoxFor but is when using Html.EditorFor?

我正在尝试 MVC 的数据类型属性,并且刚刚创建了一个如下所示的简单场景:

视图:

@model MVC4.Models.Model

@{
    ViewBag.Title = "DataTypeAttribute";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

<h2>DataTypeAttribute</h2>


@using (Html.BeginForm("SubmitData", "Home"))
{
    <div>
        @Html.ValidationSummary()
    </div>

    @Html.EditorFor(m => m.Email)
    <br />
    <br />
    @Html.EditorFor(m => m.PostalCode)

    <br />
    <br />
    @Html.EditorFor(m => m.TextOnly)
    <br />
    <br />

    <button type="submit">Submit</button>
}

型号:

public class Model
{
    [DataType(DataType.EmailAddress)]

    [Required]
    //[EmailAddress]
    public string Email { get; set; }

    [DataType(DataType.PostalCode)]
    public string PostalCode { get; set; }


    public string TextOnly { get; set; }
}

"SubmitData" 只是一个控制器,returns View(..., model) if ModelState.IsValid is false.

虽然像 this 这样的帖子在解决 Html.TextBoxFor 和 Html.EditorFor 之间的差异方面做得很好,但我找不到关于为什么要验证 datatype EmailAddress 在使用 TextBoxFor 时将不起作用。我确实发现有人提到 TextBoxFor 不考虑元数据,而 EditorFor 考虑。

但这有意义吗?所以 TextBoxFor 不提供对客户端验证的支持?!

请问是什么原因造成两者的差异?

TextBoxFor() 确实适用于验证。

[DataType(DataType.EmailAddress)] 不是验证属性。它是一个属性,通过在呈现的 html 中设置 type 属性来确定要显示的输入类型。例如 <input type="text" ..><input type="date" ..><input type="email" ..> 以呈现 HTML4 日期选择器、电子邮件输入等的浏览器实现。它仅适用于 EditorFor(),因为TextBoxFor() 顾名思义生成并输入 type="text"

如果您想要验证电子邮件地址,那么您可以在 属性.

上使用 [EmailAddress] 属性
[Required]
[EmailAddress]
public string Email { get; set; }

编辑(进一步评论)

HTML5 的一个特点是能够在不依赖脚本的情况下验证用户数据。一种这样的浏览器验证形式是使用 type 属性。在使用 @Html.EditorFor() 呈现的 属性 上使用 [DataType(DataType.EmailAddress)] 会将 type="email" 添加到 input 元素。来自 MDN documentation

email: The element represents one email address. Line breaks are automatically stripped from the input value. An invalid email address can be set, but the input field will only satisfy its constraints if the email address satisfies the ABNF production 1*( atext / "." ) "@" ldh-str 1*( "." ldh-str ) where atext is defined in RFC 5322 section 3.2.3, and ldh-str is defined in RFC 1034 section 3.5.

如果您当前看到与 属性 关联的验证错误消息,并且您尚未添加 [EmailAddress] 属性,则意味着 jquery.validate.js 未加载,您正在查看与 type="email".

关联的浏览器错误消息

jquery.validate.js 加载(正确)时,novalidate="novalidate" 属性被添加到 form 元素,它指定不验证表单(使用 HTML5 验证)提交时。来自 jquery.validate.js 的相关代码是(大约第 35 行)

// Add novalidate tag if HTML5.
this.attr('novalidate', 'novalidate');

添加此内容是为了防止浏览器验证显示的错误消息与 jquery 不显眼的验证之间可能出现的混淆。

至于为什么 DataTypeAttribute 属性在实际上不进行验证时继承 ValidationAttribute,来自 Brad Wilson 本人 this answer

The reason it derives from ValidationAttribute is so that you could create a new custom data type class, which was both a DataType and a Validation, all wrapped up into one. It's an unfortunate side-effect of .NET not allowing multiple inheritance.