假设我有一个自定义验证属性ValidateFooIsCompatibleWith
模型,如下所示:
public class FooPart
{
public string Foo { get; set; }
public string Eey { get; set; }
}
public class FooableViewModel
{
public FooPart Foo1 { get; set; }
[ValidateFooIsCompatibleWith("Foo1")]
public FooPart Foo2 { get; set; }
}
假设我也为FooPart
定义了自定义的EditorTemplates:
@Html.TextBoxFor(m => m.Foo)
@Html.TextBoxFor(m => m.Eey)
因此我的观点基本上是:
@Html.EditorFor(m => m.Foo1)
@Html.EditorFor(m => m.Foo2)
服务器端,验证工作正常。但是,无论我尝试什么,我都无法获得渲染的html来添加规则。
如果我实施IClientValidatable
,事实证明GetClientValidationRules()
永远不会被调用。 (我之前已成功使用IClientValidatable
和“简单”字段。
我还尝试通过继承DataAnnotationsModelValidator<TAttribute>
注册我自己的自定义适配器,然后在global.asax
中使用DataAnnotationsModelValidatorProvider.RegisterAdapter(...)
进行注册。该方法也无法调用GetClientValidationRules()
。
**更新**
如果添加自定义ModelMetadataProvider
和自定义ModelValidatorProvider
以便我可以设置断点,我会注意到一些有趣的行为:
ModelMetadataProvider
请求ContainerType
FooableViewModel
和ModelType
FooPart
的元数据。但是,没有对ModelValidatorProvider
提出相应的请求,因此我无法在那里插入自定义客户端验证规则。ModelValidatorProvider
和{{ContainerType
FooPart
ModelType
string
Foo
Eey
个FooPart
1}}属性。但在此级别,我不知道应用于{{1}}属性的属性。如何让MVC框架为复杂类型注册我的自定义客户端验证规则?
答案 0 :(得分:1)
我找到了解决方案:
首先,创建一个自定义模型元数据提供程序(请参阅https://stackoverflow.com/a/20983571/24954),该提供程序检查复杂类型的属性,并将客户端可验证的规则工厂存储在AdditionalValues
集合中,例如在CreateMetadataProtoype
CachedDataAnnotationsModelMetadataProvider
覆盖中
var ruleFactories = new List<Func<ModelMetadata, ControllerContext, IEnumerable<ModelClientValidationRules>>>();
...
var clientValidatable = (IClientValidatable)attribute;
ruleFactories.Add(clientValidatable.GetClientValidationRules);
...
result.AdditionalValues.Add("mycachekey", ruleFactories);
接下来,将其注册为global.asax
中的默认元数据提供程序protected void Application_Start()
{
ModelMetadataProviders.Current = new MyCustomModelMetadataProvider();
....
}
然后我创建了一个html助手,它将处理modelmetata并创建/合并每个AdditionalValues
集合中的“data-val *”html属性。
public static IDictionary<string, Object> MergeHtmlAttributes<TModel>(this HtmlHelper<TModel>, object htmlAttributes = null)
{
var attributesDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
//ensure data dictionary has unobtrusive validation enabled for the element
attributesDictionary.Add("data-val", "true");
//loop through all the rule factories, and execute each factory to get all the rules
var rules = ruleFactory(helper.Html.ViewData.ModelMetadata, helper.Html.ViewContext);
//loop through and execute all rules in the ruleFactory collection in the AdditionalValues
//and add the data-val attributes for those.
attributesDictionary.add("data-val-" + rule.ValidationType, ruleErrorMessage);
//similarly for anything in the rule.ValidationParameters
attributesDictionary.Add("data-val-" + rule.ValidationType + "-" + parameterName, parameterValue);
}
最后,在我的编辑器模板中,为每个复杂类型属性调用html帮助器(其模型类型为“FooPart1”),例如
@Html.TextBoxFor(m => m.Foo, Html.MergeHtmlAttributes(new { @class="Bar"}))
@Html.TextBoxFor(m => m.Eey, Html.MergeHtmlAttributes())
我实际上最终创建了第二个接口(与IClientValidatable
具有相同的签名),这允许我为复杂类型的各个字段自定义规则(主要用于错误消息)。我还扩展了帮助程序以获取可以使用我的自定义规则格式化的字符串参数。
答案 1 :(得分:0)
jQuery.validator.setDefaults({
success: "valid"
});
$( "#foo" ).validate({
rules:
{
rule1: {required: true, min: 3},
parent:
{
required: function(element) {return $("#age").val() < 13;}
}
}
});
复杂类型似乎没有任何理由让我烦恼所以试试Jquery验证器。根据您尝试验证的内容,可能会完成工作。