【问题标题】:How does DataAnnotations really work in MVC?DataAnnotations 如何在 MVC 中真正发挥作用?
【发布时间】:2011-07-06 11:16:26
【问题描述】:

这更像是一个理论问题。

我目前正在使用 ComponentModel.DataAnnotations 检查 MVC 3 验证,一切都自动运行,尤其是在客户端。

以某种方式检查这些属性,并生成用于验证的 javascript(或 html5 属性,如果使用不显眼的模式),并且它可以工作。

我的问题是生成客户端 javascript 的内容以及如何访问和修改它?例如,我想稍微不同地处理给定的 dataannotation 属性,或者处理自定义属性(我发现我可以从 ValidationAttribute 派生它们,但可能出于某种原因我不想要)。

有人可以向我解释一下到底发生了什么吗? (或者指向好的解释的链接也很好,因为我只找到了实际使用数据注释的教程)

编辑:同样从 ValidationAttribute 派生,客户端验证不会自动工作。为什么?

【问题讨论】:

    标签: c# asp.net-mvc-3 data-annotations


    【解决方案1】:

    MVC3 有一个新的 jQuery 验证机制,它链接 jQuery 验证和验证属性元数据,这是 jquery.validate.unobtrusive 文件,它获取所有 data- 属性并使用它们,就像之前设置时一样

    <add key="UnobtrusiveJavaScriptEnabled" value="false" />
    

    您需要做的就是想出自己的自定义验证属性,为此您有两个选择:

    • 创建一个继承ValidationAttribute接口的自定义验证属性和 覆盖IsValid

    • 创建一个自我验证模型使用模型IValidatebleObject,您所需要的只是返回Validate方法

    MVC3 中,您现在拥有一个可以覆盖的方法,该方法具有 ValidationContext 对象,您可以在其中简单地获取表单中任何其他对象的所有引用、属性和值

    创建您自己的,该不显眼的文件将处理您的自定义验证器所需的映射,并将与 jQuery 验证插件一起工作。

    你不要更改 javascript...这是 90 年代的风格,而不是 MVC 方式!

    例如,如果您想验证,假设 2 个日期,最后一个日期不能小于第一个日期(例如时间段)

    public class TimeCard
    {
        public DateTime StartDate { get; set; }
    
        [GreaterThanDateAttribute("StartDate")]
        public DateTime EndDate { get; set; }
    }
    

    创建自定义验证

    public class GreaterThanDateAttribute : ValidationAttribute
    {
        public string GreaterThanDateAttribute(string otherPropertyName)
            :base("{0} must be greater than {1}")
        {
            OtherPropertyName = otherPropertyName;
        }
    
        public override string FormatErrorMessage(string name)
        {
            return String.Format(ErrorMessageString, name, OtherPropertyName);
        }
    
        public override ValidateionResult IsValid(object value, ValidationContext validationContext)
        {
            var otherPropertyInfo = validationContext.ObjectTYpe.GetProperty(OtherPropertyName);
            var otherDate = (DateTime)otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
            var thisDate = (DateTime)value;
    
            if( thisDate <= otherDate )
            {
                var message = FormatErrorMessage(validationContext.DisplayName);
                return new ValidationResult(message);
            }
    
            return null;        
        }    
    }
    

    如果使用自我验证模型,那么代码就是

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if( EndDate <= StartDate )
            yield return new ValidationResult("EndDate must be grater than StartDate");
    }
    

    请记住,自定义验证是通用的,这就是为什么有很多代码,而自我验证模型仅适用于应用的模型。

    希望对你有帮助


    添加

    我没有解释自定义客户端验证部分,随意询问您是否需要示例,但基本上:

    在 MVC3 中更容易(当然,如果你了解 jQuery.Validate)你需要做的就是:

    • 实施IClientValidateble
    • 实现一个 jQuery 验证方法
    • 实现一个不显眼的适配器

    要创建这 3 件事,让我们将 GreaterThanDateAttribute 考虑在内并创建自定义客户端验证。为此,我们需要编写以下代码:

    附加到GreaterThanDateAttribute

    public IEnumerable<ModelCLientValidation> GetCLientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelCLientValidationRule();
        rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
        rule.ValidationType = "greater"; // This is what the jQuery.Validation expects
        rule.ValidationParameters.Add("other", OtherPropertyName); // This is the 2nd parameter
    
        yield return rule;
    }
    

    然后您需要编写新的 jQuery Validator元数据适配器,将 jQuery.Validation 与您的代码链接起来,为该字段提供正确的 data- 属性(如果当然,UnobtrusiveJavaScriptEnabled 是真的)

    创建一个新的js 文件并附加到您的&lt;head&gt;,例如

    <script src="@Url.Content("~/Scripts/customValidation.js")" type="text/javascript"></script>
    

    并附加新的验证

    jQuery.validator.addMethod("greater", function(value, element, param) {
        // we need to take value and compare with the value in 2nd parameter that is hold in param
        return Date.parse(value) > Date.parse($(param).val());
    });
    

    然后我们编写适配器

    jQuery.validator.unobtrusive.adapters.add("greater", ["other"], function(options) {
        // pass the 'other' property value to the jQuery Validator
        options.rules["greater"] = "#" + options.param.other;
        // when this rule fails, show message that comes from ErrorMessage
        options.messages["greater"] = options.message;
    });
    

    【讨论】:

    • 感谢您的回答。自我验证模型对我来说是一种新方法。但是你误解了这个问题。我对实际创建自定义验证属性不感兴趣,但对从验证属性生成 javascript(或 html5 属性,如果选择了不显眼的模式)的方式感兴趣。抱歉,我强行举了一个幼稚的例子来说明这些知识将如何有用,但这真的不是我这篇文章的重点。除了这个,你的回答真的很好。
    • 对不起,我没有关注。您想知道data- 是如何生成的吗?这是助手Html.TextBoxFor() 方法的工作,因为它已经知道该字段需要的所有数据注释,如果 Unobstrive 设置为真,它将生成他需要的所有data-,然后适配器将其链接到 jQuery.Validate插入。随意询问示例,对于上面的GreaterThanDateAttribute 示例,我可以很好地完成所有这些,也许它可以帮助您更好地理解它?
    • 添加了自定义客户端验证示例,创建并使用它,这样您就可以看到Custom Client Validation 做了什么。它将向&lt;input&gt; 添加属性data-valdata-val-greater 以及执行客户端验证所需的所有属性。 是否最后一个例子回答了你的问题?
    • 感谢您的回答,我已经为此提出了一个后续问题,如果您也可以帮助我,我会很高兴:D stackoverflow.com/questions/5155816/…
    • 在除法线之后,您可以在此处找到该答案的所有代码。你还需要什么?两个部分的客户端验证是相同的,自我验证是服务器端验证。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多