【问题标题】:Troubles with implementing IClientValidatable- GetClientValidationRules never fires实施 IClientValidatable 的问题 - GetClientValidationRules 永远不会触发
【发布时间】:2013-09-26 09:50:58
【问题描述】:

我正在为我的 MVC4 应用程序构建一个自定义验证器。为了简单起见并专注于这个问题的目的,假设我正在重新实现 RequiredAttribute 类的服务器和客户端验证:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class MyRequiredAttribute: ValidationAttribute, IClientValidatable
{
    public MyRequiredAttribute() : base("The {0} field is required.")
    {
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null)
        {
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }
        return null;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRequiredRule(ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()));
    }
}

为了测试这个,我有一个非常简单的控制器:

public class TestController : Controller
{
    public ActionResult Index()
    {
        return View(new MyThing {Value = "whatever"});
    }
    [HttpPost]
    public ActionResult Index(MyThing thing)
    {
        if (ModelState.IsValid)
        {
            return Content("Good choice!");
        }
        return View(thing);
    }
}

还有一个非常简单的模型:

public class MyThing
{
    [MyRequired]
    public string Value { get; set; }
    [Required]
    public string OtherValue { get; set; }
}

最后是索引视图:

@model MyThing

@{
    Layout = "~/Views/Shared/_LayoutWithAllTheAppropriateValidationScripts.cshtml";
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        @using(Html.BeginForm()){
        @Html.ValidationSummary(true)
        @Html.EditorForModel()
        <input type="submit" value="submit"/>
        }
    </div>
</body>
</html>

你会注意到我有Value,它用自定义MyRequiredAttributeOtherValue 装饰,它用标准RequiredAttribute 装饰。

这两个都在服务器端工作得很好,并在回发时返回适当的验证消息,但只有标准的RequiredAttribute 在客户端工作。由于我使用的是 ModelClientValidationRequiredRule 而不是 ModelClientValidationRule 和自定义 ValidationType 属性,因此我假设不需要定义自定义客户端验证规则,但我不确定,因为我没有没能走到那一步。调试器永远不会在GetClientValidationRules 方法内部中断,并且为我的模型上的Value 属性生成的输入html 元素没有data-val-requireddata-val 属性,就像OtherValue 字段一样,我是假设是 GetClientValidationRules 方法负责做的事情。

我一定是遗漏了一些简单的东西......它是什么?

【问题讨论】:

    标签: c# jquery validation asp.net-mvc-4


    【解决方案1】:

    结果证明这是用户错误,但无论如何我都会发布解决方案,希望它可以帮助其他遇到类似问题的人。

    原始问题中的代码与使用它的 MVC 项目位于单独的程序集中。 MVC 项目最近已从 MVC3 升级到 MVC4。我有followed the instructions provided by Microsoft on upgrading,或者我是这么认为的。我错过了 web.config 中的一个部分:

    <runtime>
       <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <dependentAssembly>
           <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
           <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0"/>
         </dependentAssembly>
       </assemblyBinding>
    </runtime>
    

    这告诉 MVC 项目如何很好地处理它所依赖的程序集,这些程序集是通过引用 System.Web.Mvc 程序集的早期版本进行编译的。升级我的 MVC 项目后,它引用了 System.Web.Mvc v4 和我的“通用”项目(扩展 ValidatorAttribute 实现 IClientValidatable 的地方)引用了 v3。上面的配置应该随着升级而更新,但它被遗漏了。除了原始问题中概述的客户端验证问题外,该问题没有以任何其他方式表现出来。

    这里的违规行是

           <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0"/>
    

    应该是的

           <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
    

    解决了问题。

    【讨论】:

      【解决方案2】:

      将此添加到您的 Global.asax:

      DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(MyRequiredAttribute), typeof(RequiredAttributeAdapter));
      

      这应该可以解决您的客户端验证问题。

      【讨论】:

      • 这实际上结合了两种不同的方法来创建自定义验证属性,如herehere 所述。我在提供的代码中使用了 IClientValidatable 方法。仅添加您提供的代码行是不够的。
      猜你喜欢
      • 1970-01-01
      • 2014-05-15
      • 1970-01-01
      • 2014-08-14
      • 1970-01-01
      • 2021-05-22
      • 2015-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多