在项目的实际使用中,MVC默认提供的Validation Attribute往往不够用,难以应付现实中复杂多变的验证需求。比如, 在注册用户的过程中,往往需要用户勾选”免责声明”,这个checkbox往往是必填项,但是MVC中并没有提供对于checkbox必选的验证。这篇文章通过解决checkbox必选验证的问题,看看如何在MVC中定义自己的自定义验证属性。

阅读目录:

一. CheckBox必选验证的困局

二. 对于服务端ValidationAttribute的实现分析

三. 自定义EnforceTrueAttribute实现服务器端验证

四. 添加客户端验证

五. 总结

一, CheckBox必选验证的困局

先来引入问题,下面是我们定义的RegisterModel, 为了简化问题,只是定义了2个属性

public class RegisterModel { [DisplayName("User Name")] [Required(ErrorMessage = "User Name is required")] public String UserName { get; set; }[Required] public bool IsAgreeTerm { get; set; }}

我们尝试在IsAgreeTerm添加上[Required], 希望能够帮我们实现必选验证。

注册View页面的代码如下:

@using (Html.BeginForm()) { @Html.AntiForgeryToken() @Html.ValidationSummary()<fieldset> <legend>Registration Form</legend> <ol> <li> @Html.LabelFor(m => m.EmployeeName) @Html.EditorFor(m => m.EmployeeName) <br/> @Html.ValidationMessageFor(m => m.EmployeeName) </li> <li> @Html.LabelFor(m => m.IsAgreeTerm) @Html.EditorFor(m => m.IsAgreeTerm) <br/> @Html.ValidationMessageFor(m => m.IsAgreeTerm) </li> </ol> <input type="submit" value="Register" /> </fieldset>
}

接下来看看实际的运行效果:

验证中只是提示了User Name必填,而没有提示IsAgreeTerm。 这是因为checkbox不选的话,提交到后台的值是false, 也就是说无论如何checkbox都是有值的,[Required]验证Attribute并不能按照预想的那样为我们解决验证问题。

下面我们就着手实现自己的ValidationAttribute来实现该验证。

二, 对于服务端ValidationAttribute的实现分析

在实现自己的ValidationAttribute之前,我们来分析一下MVC中提供的RequiredAttribute

上面能够看出, RequiredAttribute继承于ValidationAttribute抽象类, 覆盖了IsValid方法.

也就是说, RequiredAttribute提供了方法,用来判断添加RequiredAttribute验证规则的属性是否valid的标准。

实际上MVC的服务端验证流程是这样的:

客户端请求—>Route解析—> model绑定—> 数据验证.

现在思路应该比较清晰,就是同样继承ValidationAttribute, 实现我们的CheckboxRequiredAttribute.

三, 自定义EnforceTrueAttribute实现服务器端验证

这里我们定义个EnforceTrueAttribute继承ValidationAttribute

public class EnforceTrueAttribute : ValidationAttribute { public override bool IsValid(object value) { if (value == null) return false; if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties."); return (bool)value; }public override string FormatErrorMessage(string name) { return "The " + name + " field must be checked in order to continue."; }}

这里覆盖了父类的2个方法IsValid和FormatErrorMessage。

在IsValid方法中,如果提交的checkbox的值不是true, 验证就会不通过。 
FormatErrorMessage方法,是根据字段的名称显示错误信息.

在IsAgreeTerm上应用上EnforceTrueAttribute.

[DisplayName("Term")]
[EnforceTrue]
public bool IsAgreeTerm { get; set; }

编译运行,提交表单之后的效果是这样的:

 

四, 添加客户端验证

我们不仅仅希望服务端验证,也同时想加上客户端验证。

4.1 在EnforceTrueAttribute上实现IClientValidatable

要实现客户端验证,首先需要在服务端的EnforceTrueAttribute上实现IClientValidatable

public class EnforceTrueAttribute : ValidationAttribute, IClientValidatable
{ public override bool IsValid(object value) { if (value == null) return false; if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties."); return (bool)value; }public override string FormatErrorMessage(string name) { return "The " + name + " field must be checked in order to continue."; }public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { yield return new ModelClientValidationRule { ErrorMessage = String.IsNullOrEmpty(ErrorMessage) ? FormatErrorMessage(metadata.DisplayName) : ErrorMessage, ValidationType = "enforcetrue" }; }
}

上面代码中,我们实现了IClientValidatable接口的方法GetClientValidationRules, 该方法返回了ModelClientValidationRule,包含了的信息ValidationType 和ErrorMessage.

对比一下,在EnforceTrueAttribute在实现IClientValidatable接口前后,生成前段的html差别,就能知道改方法的作用了.

4.2 扩展客户端验证方法

通过实现IClientValidatable接口,我们只是做到了给应用了该标签的input, 在生成html代码时候,添加上了额外的验证规则,但是这些规则在客户端上,还没有方法来验证。下面就是扩展客户端验证框架unobtrusive来实现完整的客户端验证流程。

<script type="text/javascript"> jQuery.validator.addMethod("enforcetrue", function(value, element, param) { return element.checked; }); jQuery.validator.unobtrusive.adapters.addBool("enforcetrue"); </script>

五, 总结

到这里,对于完成添加一个自定义验证需要完成的流程应该是比较清楚了。

1. 服务端创建ValidationAttribute继承ValidationAttribute, 实现服务端的验证
2. ValidationAttribute继承IClientValidatable接口为生成的input标记客户端验证规则,同时客户端扩展验证方法

在实际开发中,扩展验证规则来达到数据验证的目的,能够达到代码复用的效果,同时也使得数据验证变得更加简单和方便。

相关系列文章: 

Asp.net MVC验证那些事(1)-- 介绍和验证规则使用 
Asp.net MVC验证哪些事(2)-- 验证规则总结以及使用 
Asp.net MVC验证哪些事(3)-- Remote验证及其改进(附源码)

本文转自JustRun博客园博客,原文链接:http://www.cnblogs.com/JustRun1983/p/3591036.html,如需转载请自行联系原作者

Asp.net MVC验证那些事(4)-- 自定义验证特性相关推荐

  1. asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证

    asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证 原文:asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型 ...

  2. ASP.NET MVC使用Oauth2.0实现身份验证

    随着软件的不断发展,出现了更多的身份验证使用场景,除了典型的服务器与客户端之间的身份验证外还有,如服务与服务之间的(如微服务架构).服务器与多种客户端的(如PC.移动.Web等),甚至还有需要以服务的 ...

  3. 【转】ASP.NET验证控件详解(非空验证,比较验证,范围验证,正则表达式,自定义验证)...

    [转]ASP.NET验证控件详解(非空验证,比较验证,范围验证,正则表达式,自定义验证) ASP.NET验证控件详解 现在ASP.NET,你不但可以轻松的实现对用户输入的验证,而且,还可以选择验证在服 ...

  4. [ASP.NET MVC 小牛之路]16 - Model 验证

    上一篇博文 [ASP.NET MVC 小牛之路]15 - Model Binding 中讲了MVC在Model Binding过程中如何根据用户提交HTTP请求数据创建Model对象.在实际的项目中, ...

  5. ASP.NET MVC中的统一化自定义异常处理

    使用系统默认的错误处理方式,可以减少一次重定向访问,并且正常提示了错误信息,并发送了错误码500,但应注意以下问题: 一.需要修改web.config <customErrors mode=&q ...

  6. Asp.Net MVC及Web API添加身份验证及错误处理的过滤器

    先说身份验证的问题.无论是mvc还是api都有一个安全性的问题,未通过身份验证的人能不能访问的问题.我们新一个空项目时,默认是没有身份验证的,除非你在控制器类或者方法上面加上Authorize属性才会 ...

  7. 如何提高码农产量,基于ASP.NET MVC的敏捷开发框架之自定义表单开发随笔四

    "厂长,上一次我们讲过了工作流的整体规划,今天我要动手做啦!我想先把工作流的自定义表单做出来." "好的,以前我做这方面的东西,我给你设计了一份表结构,你先拿去看看.&q ...

  8. ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)

    ASP.NET MVC通过Model验证帮助我们很容易的实现对数据的验证,在默认的情况下,基于ValidationAttribute的声明是验证被使用,我们只需要将相应的ValidationAttri ...

  9. 在ASP.NET MVC中使用Knockout实践07,自定义验证信息的位置与内容

    在前两篇中,体验了Knockout的基本验证和自定义验证.本篇自定义验证信息的显示位置与内容. 自定义验证信息的显示位置 通常,Knockout的验证信息紧跟在input后面,通过validation ...

最新文章

  1. Optional 是个好东西,你真的会用么?
  2. 水下机器人线上赛战火升级,目标检测、通信赛项等你来战
  3. 删除linux系统中的ifcfg-eth0.bak
  4. ahjesus Ubuntu配置svn服务器
  5. gcc选项 和 gdb 使用
  6. 尚硅谷_JS DOM编程_学习笔记
  7. 解决MySQL Server Logs不能正常查看的问题
  8. java class和this_转:java 类名 this 的使用
  9. 03-body标签中相关标签
  10. 中国PLC市场增长分析
  11. [转]ie6下CSS存在的BUG
  12. Java面试题-泛型篇十四
  13. 信号公式汇总之Z变换
  14. 软件项目的规模、工作量和成本是如何进行估算或评估的?
  15. python背离点的判断
  16. 京东vs淘宝的商业模式,你了解吗?
  17. 黑镜成真!3分钟看懂马斯克直播脑机接口,芯片植入猪脑,活猪演示
  18. matlab摩托车刹车问题,安全骑行篇,摩托车刹车的基本知识与技巧!
  19. 网络爬虫学习第二弹:requests库的使用
  20. 谷歌cloud_参加Google Cloud专业机器学习工程师考试的20天Beta

热门文章

  1. Codis集群扩容方法
  2. Training的第六天
  3. 通过组策略禁用U盘执行病毒文件
  4. Android设计模式系列(3)--SDK源码之单例模式
  5. 家用机器人风口来临,但巨头围猎背后的前景不容乐观
  6. 在maven项目中使用Junit进行单元测试(一)
  7. 俄研发新无线传电系统 隔20cm保持80%传输效率
  8. 【Java 基础篇】【第一课】HelloWorld
  9. Java面向对象知识点精华
  10. [.net 面向对象编程基础] (18) 泛型