实现IClientValidatable- GetClientValidationRules的麻烦永远不会触发

时间:2013-09-20 21:47:49

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

我正在为我的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使用标准MyRequiredAttribute修饰的自定义OtherValueRequiredAttribute进行了装饰。

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

我必须在这里遗漏一些简单的东西......它是什么?

2 个答案:

答案 0 :(得分:3)

原来这是用户错误,但无论如何我都会发布解决方案,希望能帮助其他人解决类似问题。

原始问题中的代码与使用它的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和我的“Common”项目(实现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"/>

解决了这个问题。

答案 1 :(得分:0)

将此添加到您的Global.asax:

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

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