c# - DataAnnotations 在 MVC 中是如何工作的?

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

这更像是一个理论问题。

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

有些东西会检查这些属性,并生成用于验证的 javascript(或 html5 属性,如果使用非侵入式模式),并且它有效。

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

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

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

最佳答案

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

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

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

  • 创建继承 ValidationAttribute自定义验证属性接口(interface)和 覆盖 IsValid

  • 创建 self 验证模型使用模型 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文件并附加到您的 <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;
});

关于c# - DataAnnotations 在 MVC 中是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5154231/

相关文章:

c# - 如何使 DateTime 模型属性成为必需的?

c# - 如何控制使用 AutoDual 生成的 COM 接口(interface)的生成接口(interface) GUID

ASP.NET MVC - 如何将子站点 (ASP.NET) 添加到我的应用程序?

asp.net-mvc-3 - 使用 ninject 注入(inject)对模型类或非 Controller 类的依赖

asp.net-mvc-3 - System.ComponentModel.DataAnnotations 自动 Controller 单元测试中的 MethodAccessException,MVC

asp.net-mvc - ASP.Net MVC3-强制使用大写字母的自定义数据注释

c# - VS 2017 的任务窗口中的 "Status" "Scheduled"是什么意思?

c# - Intellisense 不会自动工作 VSCode

c# - WebMethod 异步结果显示对象

javascript - 为什么是 "Microsoft JScript runtime error: Object expected"?