DataAnnotations 在 MVC 中到底如何工作?

发布于 2024-10-19 20:47:49 字数 418 浏览 3 评论 0原文

这更多的是一个理论问题。

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

不知何故,某些东西会检查这些属性,并生成用于验证的 javascript(或 html5 属性,如果使用非侵入模式),并且它可以工作。

我的问题是,什么生成客户端 JavaScript 以及如何访问和修改它?例如,我想以稍微不同的方式处理给定的数据注释属性,或者处理自定义属性(我发现我可以从 ValidationAttribute 派生它们,但也许出于某种原因我不想要)。

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

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

This is more of a theoretical question.

I'm currently examining the MVC 3 validation by using ComponentModel.DataAnnotations, and everything works automagically, especially on client side.

Somehow something checks for those attributes, and generates javascript for the validation (or html5 attributes, if using unobtrusive mode), and it works.

My question is that what generates the client side javascript and how can I access and modify it? For example I want to handle the given dataannotation attributes a little differently, or handle custom attributes (I have found that I can derive them from ValidationAttribute, but maybe for some reason I don't want).

Can someone explain it to me what really happens?
(Or links to good explanations would also be good, as I have only found tutorials for actually using dataannotations)

EDIT: Also with deriving from ValidationAttribute, the client-side validation is not working automatically. Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

记忆之渊 2024-10-26 20:47:49

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

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

您需要做的就是提供您自己的自定义验证属性”时,您有 2 个选项:

  • 创建一个继承的自定义验证属性 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;        
    }    
}

如果使用 strong> 模型,那么代码就只是

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 为 true)

创建一个新的 js 文件并附加到您的 例如

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

MVC3 has a new jQuery Validation mechanism that link jQuery Validation and Validation Attributes Metadata, this is the jquery.validate.unobtrusive file that takes all data- attributes and work with them, just like before when you set the

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

All you need to do is come up with your own Custom Validation Attributes, for that you have 2 options:

  • Create a Custom Validation Attribute that inherits the ValidationAttribute interface and
    override the IsValid

or

  • Create a Self Validate Model use the model IValidatebleObject that all you need is to return the Validate method

in MVC3 you now have a method that you can override that has a ValidationContext object, where you can simply get all references, properties and values of any other object in the form

Create your own, and that unobtrusive file will handle the mapping of what your custom validator needs and will work out together with the jQuery Validation plugin.

YOU DO NOT Change the javascript... that's sooo 90's and not MVC way!

for example if you want to validate, let's say 2 dates that the last can not be less than the first (period of time for example)

public class TimeCard
{
    public DateTime StartDate { get; set; }

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

creating a Custom Validation

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

if using the Self Validating model then the code would be just

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

Keep in mind that the Custom Validation is Generic, that's why much code, and Self Validating Model only works on the model applied.

Hope it helps


added

I didn't explain the Custom Client Validation part, fell free to ask if you need examples, but basically:

It's easier in MVC3 (if of course, you understand jQuery.Validate) all you need to do is:

  • Implement IClientValidateble
  • Implement a jQuery validation method
  • Implement an unobtrusive adapter

To create this 3 things, let's take this GreaterThanDateAttribute into account and create the Custom Client Side Validation. For that we need to code this:

append to the 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;
}

Then you need to write the new jQuery Validator and the metadata adapter that will link the jQuery.Validation with your code providing the correct data- attributes for that field (if of course, UnobtrusiveJavaScriptEnabled is true)

create a new js file and attach to your <head> for example as

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

and append the new validation

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

and then we write the adapter

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;
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文