博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自定义Remote验证(对博客园文章“Asp.net MVC验证哪些事(3)-- Remote验证及其改进(附源码)”自定义验证的改进)...
阅读量:6413 次
发布时间:2019-06-23

本文共 10166 字,大约阅读时间需要 33 分钟。

最近拜读了博客园我一直很敬仰的大神几年前关于asp.net mvc中自定义Remote验证的文章:

获益匪浅。但是文中给出的解决方案,个人觉得里面动态执行验证方法的那段代码有可以完善的地方(并没有半点对大神的诋毁,代码为下面标色部分):

public class CustomModelBinder : DefaultModelBinder    {        protected override void BindProperty(ControllerContext controllerContext,        ModelBindingContext bindingContext,        PropertyDescriptor propertyDescriptor)        {            if (propertyDescriptor.PropertyType == typeof(string))            {                //检查Model绑定的属性中,是否应用了CustomRemoteAttribute                var remoteAttribute =                  propertyDescriptor.Attributes.OfType
() .FirstOrDefault(); if (remoteAttribute != null) { //如果使用了CustomRemoteAttribute, 就开始找到CustomAttribute中指定的Controller var allControllers = GetControllerNames(); var controllerType = allControllers.FirstOrDefault(x => x.Name == remoteAttribute.Controller + "Controller"); if (controllerType != null) { //查找Controller中的Action方法 var methodInfo = controllerType.GetMethod(remoteAttribute.Action); if (methodInfo != null) { //调用方法,得到验证的返回结果 bool isValidate = callRemoteValidationFunction( controllerContext, bindingContext, propertyDescriptor, controllerType, methodInfo, remoteAttribute.AdditionalFields); //如果验证失败,添加ModelError if (!isValidate) { bindingContext.ModelState.AddModelError(propertyDescriptor.Name, remoteAttribute.ErrorMessage); } } } } } base.BindProperty(controllerContext, bindingContext, propertyDescriptor); } /// This function calls the indicated method on a new instance of the supplied /// controller type and return the error string. (NULL if not) private bool callRemoteValidationFunction( ControllerContext controllerContext, ModelBindingContext bindingContext, MemberDescriptor propertyDescriptor, Type controllerType, MethodInfo methodInfo, string additionalFields) { var propertyValue = controllerContext.RequestContext.HttpContext.Request.Form[ bindingContext.ModelName + propertyDescriptor.Name]; var controller = (Controller)Activator.CreateInstance(controllerType); object result = null; var parameters = methodInfo.GetParameters(); if (parameters.Length == 0) { result = methodInfo.Invoke(controller, null); } else { var parametersArray = new List
(); if (!string.IsNullOrEmpty(additionalFields)) { int i = 0; foreach (var field in additionalFields.Split(',')) { //可以根据参数名字对应,这里根据参数顺序对应 string value = controllerContext.RequestContext.HttpContext .Request.Form[bindingContext.ModelName + field]; parametersArray.Add(Convert.ChangeType(value, parameters[i].ParameterType)); i++; } if (parametersArray.Count == parameters.Length) { result = methodInfo.Invoke(controller, parametersArray.ToArray()); } } } if (result != null) { return Convert.ToBoolean(((JsonResult)result).Data); } return false; ; } /// Returns a list of all Controller types private static IEnumerable
GetControllerNames() { var controllerNames = new List
(); GetSubClasses
().ForEach(controllerNames.Add); return controllerNames; } private static List
GetSubClasses
() { return Assembly.GetCallingAssembly().GetTypes().Where( type => type.IsSubclassOf(typeof(T))).ToList(); } }

 

当然这段代码是没有任何问题的,也考虑到了验证方法包含多个参数的问题,但是有个问题就是:Remote验证方法的参数都被指定成了string类型,但是实际中,我们不能保证我们的验证方法的参数都是string类型。这里给出自己改进的代码部分

var parametersArray = new List();if (!string.IsNullOrEmpty(additionalFields)){    int i = 0;    foreach (var field in additionalFields.Split(','))    {        //可以根据参数名字对应,这里根据参数顺序对应        string value = controllerContext.RequestContext.HttpContext                    .Request.Form[bindingContext.ModelName + field];        parametersArray.Add(Convert.ChangeType(value, parameters[i].ParameterType));        i++;    }    if (parametersArray.Count == parameters.Length)    {        result = methodInfo.Invoke(controller, parametersArray.ToArray());    }}

 上面是根据验证参数顺序来对应的,当然,你也可以根据参数名称来对应了。下面是调用方法:

[Required][CustomRemote("CheckMMSRecord", "MMSRecord", AdditionalFields = "CustPhone,Type,VCode", ErrorMessage = "请输入正确的手机验证码")]public string VCode { get; set; }

验证方法定义为:

public JsonResult CheckMMSRecord2(string Mobile, int Type, string VCode)

CustomModelBinder完整如下:

public class CustomModelBinder : DefaultModelBinder    {        protected override void BindProperty(ControllerContext controllerContext,        ModelBindingContext bindingContext,        PropertyDescriptor propertyDescriptor)        {            if (propertyDescriptor.PropertyType == typeof(string))            {                //检查Model绑定的属性中,是否应用了CustomRemoteAttribute                var remoteAttribute =                  propertyDescriptor.Attributes.OfType
() .FirstOrDefault(); if (remoteAttribute != null) { //如果使用了CustomRemoteAttribute, 就开始找到CustomAttribute中指定的Controller var allControllers = GetControllerNames(); var controllerType = allControllers.FirstOrDefault(x => x.Name == remoteAttribute.Controller + "Controller"); if (controllerType != null) { //查找Controller中的Action方法 var methodInfo = controllerType.GetMethod(remoteAttribute.Action); if (methodInfo != null) { //调用方法,得到验证的返回结果 bool isValidate = callRemoteValidationFunction( controllerContext, bindingContext, propertyDescriptor, controllerType, methodInfo, remoteAttribute.AdditionalFields); //如果验证失败,添加ModelError if (!isValidate) { bindingContext.ModelState.AddModelError(propertyDescriptor.Name, remoteAttribute.ErrorMessage); } } } } } base.BindProperty(controllerContext, bindingContext, propertyDescriptor); } /// This function calls the indicated method on a new instance of the supplied /// controller type and return the error string. (NULL if not) private bool callRemoteValidationFunction( ControllerContext controllerContext, ModelBindingContext bindingContext, MemberDescriptor propertyDescriptor, Type controllerType, MethodInfo methodInfo, string additionalFields) { var propertyValue = controllerContext.RequestContext.HttpContext.Request.Form[ bindingContext.ModelName + propertyDescriptor.Name]; var controller = (Controller)Activator.CreateInstance(controllerType); object result = null; var parameters = methodInfo.GetParameters(); if (parameters.Length == 0) { result = methodInfo.Invoke(controller, null); } else { var parametersArray = new List
(); if (!string.IsNullOrEmpty(additionalFields)) { int i = 0; foreach (var field in additionalFields.Split(',')) { //可以根据参数名字对应,这里根据参数顺序对应 string value = controllerContext.RequestContext.HttpContext .Request.Form[bindingContext.ModelName + field]; parametersArray.Add(Convert.ChangeType(value, parameters[i].ParameterType)); i++; } if (parametersArray.Count == parameters.Length) { result = methodInfo.Invoke(controller, parametersArray.ToArray()); } } } if (result != null) { return Convert.ToBoolean(((JsonResult)result).Data); } return false; ; } /// Returns a list of all Controller types private static IEnumerable
GetControllerNames() { var controllerNames = new List
(); GetSubClasses
().ForEach(controllerNames.Add); return controllerNames; } private static List
GetSubClasses
() { return Assembly.GetCallingAssembly().GetTypes().Where( type => type.IsSubclassOf(typeof(T))).ToList(); } }

以上仅为个人遇见,有不对之处,还望斧正。

转载于:https://www.cnblogs.com/coce/p/6840156.html

你可能感兴趣的文章
java后台框架 springmvc mybatis(sqlsever oracle 和 mysql数据库) HTML5 bootstrap 全新高大尚...
查看>>
ReportNG 支持中文处理技巧
查看>>
Java 面向对象 之 多态实例2
查看>>
Linux 的发展基本知识及哲学思想
查看>>
PHP 随机用户名账号的生成
查看>>
地址解析协议ARP
查看>>
RC 和 Beta认识
查看>>
输入一串随机数字,然后按千分位输出。
查看>>
流程控制案例
查看>>
进程与线程
查看>>
linux部署时间服务器出现错误no server suitable for synchronization found
查看>>
日志备份和按时间删除日志脚本实现
查看>>
cd in bash
查看>>
rspamd 动态 add_header
查看>>
降低Redis内存占用
查看>>
Docker仓库Harbor配置LDAP并开启TLS认证
查看>>
NTLDR is missing
查看>>
通用权限管理系统组件 (GPM - General Permissions Manager) 中实现岗位的维护
查看>>
python内置函数与使用
查看>>
Linux route指定静态路由配置
查看>>