asp.net mvc源码分析-ModelValidatorProviders 客户端的验证
2016-04-02 11:22
411 查看
几年写过asp.net mvc源码分析-ModelValidatorProviders 当时主要是考虑mvc的流程对,客户端的验证也只是简单的提及了一下,现在我们来仔细看一下客户端的验证。
View Code
这里的AttributeFactories可以通过
public static void RegisterAdapter(Type attributeType, Type adapterType)
public static void RegisterAdapterFactory(Type attributeType, DataAnnotationsModelValidationFactory factory)
这2个方法添加新的成员。而ValidatableFactories默认是没有成员的,可以通过以下方法添加成员
public static void RegisterValidatableObjectAdapter(Type modelType, Type adapterType)
public static void RegisterValidatableObjectAdapterFactory(Type modelType, DataAnnotationsValidatableObjectAdapterFactory factory)
注意以下我们一般自定义的验证类都是继承ValidationAttribute的,所以这里用的就是DefaultAttributeFactory,也就是DataAnnotationsModelValidator,那么就是要调用DataAnnotationsModelValidator的GetClientValidationRules方法。
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() {
IEnumerable<ModelClientValidationRule> results = base.GetClientValidationRules();
IClientValidatable clientValidatable = Attribute as IClientValidatable;
if (clientValidatable != null) {
results = results.Concat(clientValidatable.GetClientValidationRules(Metadata, ControllerContext));
}
return results;
}
这个方法首先调用基类的GetClientValidationRules方法,返回没有元素的一个集合,然后调用我们自定义类的GetClientValidationRules方法,这里也就解释了为什么 我们需要实现IClientValidatable 这个接口了。注意以下DataAnnotationsModelValidator类还有一个 public override IEnumerable<ModelValidationResult> Validate(object container)这个方法,就是我们服务器端的验证,比如会调用我们子类的 public override bool IsValid(object value)方法。
在实际开发中我一般喜欢用ValidationAttribute和IClientValidatable这种方式,当然还可以用Attribute-》ModelValidator-》AssociatedValidatorProvider 比如MVC中的扩展点(九)验证 最后在调用ModelValidatorProviders.Providers.Add(new ConfirmValidatorProvider());来添加ValidatorProvider。
ModelValidatorProviders主要关心2个地方,1是获取ModelMetadata;
2是如何调用GetClientValidationRules方法。
ModelMetadata是一个很复杂的东西,所以本文没有提及,大家可以参考:
ASP.NET MVC Model元数据(一)
ASP.NET MVC Model元数据(二)
ASP.NET MVC Model元数据(三)
ASP.NET MVC Model元数据(四)
ASP.NET MVC Model元数据(五)
客户端的验证就相对简单了很多,我们先说这一段code:
jQuery.validator.unobtrusive.adapters.add('mulregular', ['regexs', 'minmatchno'], function (options) {
options.rules["mulregular"] = {
regexs: options.params.regexs,
minmatchno: options.params.minmatchno
};
if (options.message) {
options.messages['mulregular'] = options.message;
}
});
其中的Add的实现如下:
adapters.add = function (adapterName, params, fn) {
if (!fn) { // Called with no params, just a function
fn = params;
params = [];
}
this.push({ name: adapterName, params: params, adapt: fn });
return this;
};
而我们定义的这个方法在parseElement方法中调用:
$.each(this.adapters, function () {
var prefix = "data-val-" + this.name, //获取验证前缀 如data-val-mulregular
message = $element.attr(prefix),// 获取error message
paramValues = {};
if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy)
prefix += "-";
$.each(this.params, function () { //params就是传递的['regexs', 'minmatchno']
paramValues[this] = $element.attr(prefix + this);// 获取参数值 如data-val-mulregular-minmatchno 这里的this就是minmatchno
});
this.adapt({ //调用我们在jQuery.validator.unobtrusive.adapters.add定义的方法
element: element,
form: form,
message: message,
params: paramValues,
rules: rules,
messages: messages
});
}
再来看客户端验证的实现code:
jQuery.validator.addMethod('mulregular', function (value, element, param) {
if (this.optional(element)) {
return true;
}
var regs = param["regexs"].split(",");
var minmatchno = param["minmatchno"] - 0;
for (var i = 0; i < regs.length; i++) {
var match = new RegExp(regs[i]).exec(value);
if (match && (match.index === 0) && (match[0].length === value.length)) {
minmatchno -= 1;
}
}
return minmatchno <= 0;
});
其中addMethod的实现很简单
addMethod: function( name, method, message ) {
$.validator.methods[name] = method;
$.validator.messages[name] = message !== undefined ? message : $.validator.messages[name];
if ( method.length < 3 ) {
$.validator.addClassRules(name, $.validator.normalizeRule(name));
}
}
这里定义的方法在check里面调用:
大家看到的这里的parameter的数据和我们在unobtrusive.adapters中返回的参数一致,但是怎么获取的我也不是很明白。里面涉及到的内容很多很多。
网上关于这一方面的还很多
ASP.NET MVC Unobtrusive JavaScript 实现 onfocusout 验证, onfocusin 清除错误
ASP.NET MVC的客户端验证:jQuery验证在Model验证中的实现
改写jquery.validate.unobtrusive.js实现气泡提示mvc错误
Query validate 根据 asp.net MVC的验证提取简单快捷的验证方式(jquery.validate.unobtrusive.js)
ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)
public class RangeAttributeAdapter : DataAnnotationsModelValidator<RangeAttribute> { public RangeAttributeAdapter(ModelMetadata metadata, ControllerContext context, RangeAttribute attribute) : base(metadata, context, attribute) { } public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() { string errorMessage = ErrorMessage; // Per Dev10 Bug #923283, need to make sure ErrorMessage is called before Minimum/Maximum return new[] { new ModelClientValidationRangeRule(errorMessage, Attribute.Minimum, Attribute.Maximum) }; } } public class ModelClientValidationRangeRule : ModelClientValidationRule { public ModelClientValidationRangeRule(string errorMessage, object minValue, object maxValue) { ErrorMessage = errorMessage; ValidationType = "range"; ValidationParameters["min"] = minValue; ValidationParameters["max"] = maxValue; } }
View Code
这里的AttributeFactories可以通过
public static void RegisterAdapter(Type attributeType, Type adapterType)
public static void RegisterAdapterFactory(Type attributeType, DataAnnotationsModelValidationFactory factory)
这2个方法添加新的成员。而ValidatableFactories默认是没有成员的,可以通过以下方法添加成员
public static void RegisterValidatableObjectAdapter(Type modelType, Type adapterType)
public static void RegisterValidatableObjectAdapterFactory(Type modelType, DataAnnotationsValidatableObjectAdapterFactory factory)
注意以下我们一般自定义的验证类都是继承ValidationAttribute的,所以这里用的就是DefaultAttributeFactory,也就是DataAnnotationsModelValidator,那么就是要调用DataAnnotationsModelValidator的GetClientValidationRules方法。
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() {
IEnumerable<ModelClientValidationRule> results = base.GetClientValidationRules();
IClientValidatable clientValidatable = Attribute as IClientValidatable;
if (clientValidatable != null) {
results = results.Concat(clientValidatable.GetClientValidationRules(Metadata, ControllerContext));
}
return results;
}
这个方法首先调用基类的GetClientValidationRules方法,返回没有元素的一个集合,然后调用我们自定义类的GetClientValidationRules方法,这里也就解释了为什么 我们需要实现IClientValidatable 这个接口了。注意以下DataAnnotationsModelValidator类还有一个 public override IEnumerable<ModelValidationResult> Validate(object container)这个方法,就是我们服务器端的验证,比如会调用我们子类的 public override bool IsValid(object value)方法。
在实际开发中我一般喜欢用ValidationAttribute和IClientValidatable这种方式,当然还可以用Attribute-》ModelValidator-》AssociatedValidatorProvider 比如MVC中的扩展点(九)验证 最后在调用ModelValidatorProviders.Providers.Add(new ConfirmValidatorProvider());来添加ValidatorProvider。
ModelValidatorProviders主要关心2个地方,1是获取ModelMetadata;
var metadataProvider = new DataAnnotationsModelMetadataProvider(); var metadata = metadataProvider.GetMetadataForType(null, section.SectionDataType); foreach (ModelMetadata meta in metadata.Properties) { var validatorList = meta.GetValidators(this.ControllerContext).ToList(); if (validatorList.Count > 0) { foreach (var validator in validatorList) { var rules = validator.GetClientValidationRules(); foreach (var rule in rules) { object value; switch (rule.ValidationType) { case "required": XXXXXXX break; } } } } }
2是如何调用GetClientValidationRules方法。
ModelMetadata是一个很复杂的东西,所以本文没有提及,大家可以参考:
ASP.NET MVC Model元数据(一)
ASP.NET MVC Model元数据(二)
ASP.NET MVC Model元数据(三)
ASP.NET MVC Model元数据(四)
ASP.NET MVC Model元数据(五)
客户端的验证就相对简单了很多,我们先说这一段code:
jQuery.validator.unobtrusive.adapters.add('mulregular', ['regexs', 'minmatchno'], function (options) {
options.rules["mulregular"] = {
regexs: options.params.regexs,
minmatchno: options.params.minmatchno
};
if (options.message) {
options.messages['mulregular'] = options.message;
}
});
其中的Add的实现如下:
adapters.add = function (adapterName, params, fn) {
if (!fn) { // Called with no params, just a function
fn = params;
params = [];
}
this.push({ name: adapterName, params: params, adapt: fn });
return this;
};
而我们定义的这个方法在parseElement方法中调用:
$.each(this.adapters, function () {
var prefix = "data-val-" + this.name, //获取验证前缀 如data-val-mulregular
message = $element.attr(prefix),// 获取error message
paramValues = {};
if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy)
prefix += "-";
$.each(this.params, function () { //params就是传递的['regexs', 'minmatchno']
paramValues[this] = $element.attr(prefix + this);// 获取参数值 如data-val-mulregular-minmatchno 这里的this就是minmatchno
});
this.adapt({ //调用我们在jQuery.validator.unobtrusive.adapters.add定义的方法
element: element,
form: form,
message: message,
params: paramValues,
rules: rules,
messages: messages
});
}
再来看客户端验证的实现code:
jQuery.validator.addMethod('mulregular', function (value, element, param) {
if (this.optional(element)) {
return true;
}
var regs = param["regexs"].split(",");
var minmatchno = param["minmatchno"] - 0;
for (var i = 0; i < regs.length; i++) {
var match = new RegExp(regs[i]).exec(value);
if (match && (match.index === 0) && (match[0].length === value.length)) {
minmatchno -= 1;
}
}
return minmatchno <= 0;
});
其中addMethod的实现很简单
addMethod: function( name, method, message ) {
$.validator.methods[name] = method;
$.validator.messages[name] = message !== undefined ? message : $.validator.messages[name];
if ( method.length < 3 ) {
$.validator.addClassRules(name, $.validator.normalizeRule(name));
}
}
这里定义的方法在check里面调用:
大家看到的这里的parameter的数据和我们在unobtrusive.adapters中返回的参数一致,但是怎么获取的我也不是很明白。里面涉及到的内容很多很多。
网上关于这一方面的还很多
ASP.NET MVC Unobtrusive JavaScript 实现 onfocusout 验证, onfocusin 清除错误
ASP.NET MVC的客户端验证:jQuery验证在Model验证中的实现
改写jquery.validate.unobtrusive.js实现气泡提示mvc错误
Query validate 根据 asp.net MVC的验证提取简单快捷的验证方式(jquery.validate.unobtrusive.js)
ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)
相关文章推荐
- HTML与Aspx的区别
- asp.net 母版页使用详解
- 修改asp.net的Ajax变更为post请求的历程
- 详细讲解Asp_net MVC上传文件与下载文件的方法
- 【dotnet跨平台】Asp.net 正在经历的变革
- Simple way to implement caching in ASP.NET Web API
- Migrating Configuration From ASP.NET MVC 5 to MVC
- Manual JSON serialization from DataReader in ASP.NET Web API
- ASP.NET的OnClientClick与OnClick事件
- 关于在asp.net后台输出提示字符串的时候显示的字符提示出错的问题
- 【Raspberry Pi】 小问题汇总
- ASP.NET-DropDownListFor绑定model数据
- OWASP-ZAP
- 在ASP.NET MVC3 中利用JSONP跨域登录WEB系统
- AOP之基于@Aspect 注解与Schema(xml)区别
- 如何创建自定义ASP.NET MVC5脚手架模板?
- metasploit命令大全。
- ASP.NET MVC 让@Html.DropDownList显示默认值
- asp网页跳转
- ASP.NET的三层架构(DAL,BLL,UI)