DataAnnotations如何在MVC中真正起作用?

时间:2011-03-01 12:01:36

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

这更像是一个理论问题。

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

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

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

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

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

1 个答案:

答案 0 :(得分:15)

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

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

您需要做的只是提出自己的自定义验证属性,因为您有2个选项:

  • 创建一个继承ValidationAttribute界面的自定义验证属性 覆盖IsValid

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

MVC3 中,您现在有一个可以覆盖的方法,它有一个ValidationContext对象,您可以在其中获取表单中任何其他对象的所有引用,属性和值< / p>

创建您自己的文件,这个不显眼的文件将处理您的自定义验证器需要的映射,并将与jQuery Validation插件一起使用。

你不要改变javascript ......那是sooo 90's而不是MVC方式!

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

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验证方法
  • 实施不显眼的适配器

要创建这三件事,让我们考虑这个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文件并附加到<head>,例如

<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;
});