Asp.net MVC验证那些事(4)-- 自定义验证特性
在项目的实际使用中,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验证及其改进(附源码)
Asp.net MVC验证那些事(4)-- 自定义验证特性的更多相关文章
- asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证
原文:asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证 在前面的文章中我们曾经涉及到ControllerActionInvoker类GetPara ...
- ASP.NET没有魔法——ASP.NET MVC使用Oauth2.0实现身份验证
随着软件的不断发展,出现了更多的身份验证使用场景,除了典型的服务器与客户端之间的身份验证外还有,如服务与服务之间的(如微服务架构).服务器与多种客户端的(如PC.移动.Web等),甚至还有需要以服务的 ...
- ASP.NET MVC使用Oauth2.0实现身份验证
随着软件的不断发展,出现了更多的身份验证使用场景,除了典型的服务器与客户端之间的身份验证外还有,如服务与服务之间的(如微服务架构).服务器与多种客户端的(如PC.移动.Web等),甚至还有需要以服务的 ...
- ASP.NET MVC 5 学习教程:添加验证
原文 ASP.NET MVC 5 学习教程:添加验证 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 通过控 ...
- 【译】ASP.NET MVC 5 教程 - 10:添加验证
原文:[译]ASP.NET MVC 5 教程 - 10:添加验证 在本节中,我们将为Movie模型添加验证逻辑,并确认验证规则在用户试图使用程序创建和编辑电影时有效. DRY 原则 ASP.NET M ...
- [ASP.NET MVC]如何定制Numeric属性/字段验证消息
原文:[ASP.NET MVC]如何定制Numeric属性/字段验证消息 对于一个Numeric属性/字段,ASP.NET MVC会自动进行数据类型的验证(客户端验证),以确保输入的是一个有效的数字, ...
- [转][ASP.NET MVC]如何定制Numeric属性/字段验证消息
本文转自:http://www.cnblogs.com/artech/archive/2012/02/13/NumericPropertyValidation.html 对于一个Numeric属性/字 ...
- ASP.NET MVC中对Model进行分步验证的解决方法
原文:ASP.NET MVC中对Model进行分步验证的解决方法 在我之前的文章:ASP.NET MVC2.0结合WF4.0实现用户多步注册流程中将一个用户的注册分成了四步,而这四个步骤都是在完善一个 ...
- [ASP.NET MVC 小牛之路]16 - Model 验证
上一篇博文 [ASP.NET MVC 小牛之路]15 - Model Binding 中讲了MVC在Model Binding过程中如何根据用户提交HTTP请求数据创建Model对象.在实际的项目中, ...
- ASP.NET MVC 4.0中选择Windows 验证默认出错拒绝访问的原因和解决方案
在VS 2012或者2013 中,根据模板创建一个ASP.NET MVC 4.0的应用程序,选择下面的模板 然后选择Intranet Application 不对源代码做任何修改,直接按下F5调试,会 ...
随机推荐
- JavaScript中JSON的处理心得
一门语言用到深处,就避免不了要对数据的类型进行准确判断,并针对其类型做正确处理. 抛开在Web前端环境不谈,从一门独立编程语言的角度来看js,你就会感受到对js中数据类型的理解有多么重要. 禁止直接多 ...
- API 开发实践
整个2015年,如果要给自己打上一个标签的话,那应该就是 API. 在各个不同的系统中定制各种 API 框架. 在做商城对接各种电商 ERP 的 API 开发中,我采用的是兼容SHOPEX 的 API ...
- 第 23 章 CSS3 边框图片效果
学习要点: 1.属性初探 2.属性解释 3.简写和版本 主讲教师:李炎恢 本章主要探讨 HTML5 中 CSS3 中边框图片背景的效果,通过这个新属性让边框更加的丰富多彩. 一.属性解释 CSS3 提 ...
- 操作系统笔记系列 一 Linux
学习资料: 1.http://www.icoolxue.com/ 马士兵 1.Linux 服务器端,目前98%的服务器都是Linux. 2.
- Verilog学习笔记简单功能实现(七)...............接口设计(并行输入串行输出)
利用状态机实现比较复杂的接口设计: 这是一个将并行数据转换为串行输出的变换器,利用双向总线输出.这是由EEPROM读写器的缩减得到的,首先对I2C总线特征介绍: I2C总线(inter integra ...
- CentOS 6.5 搭建 LAMP 环境
目录 第一步: 安装和配置Apache服务器 第二步: 设置.绑定站点目录文件 第三步: 安装MYSQL数据库 第四步: 安装PHP环境 总结 >>Begin: 第一步: 安装和配置Apa ...
- android 查找某个特定文件后缀名
private void queryFiles(){ String[] projection = new String[] { MediaStore.Files.FileColumns._ID, Me ...
- .Net中的并行编程-4.实现高性能异步队列
上文<.Net中的并行编程-3.ConcurrentQueue实现与分析>分析了ConcurrentQueue的实现,本章就基于ConcurrentQueue实现一个高性能的异步队列,该队 ...
- IoC和DI的理解
1 概述 当我们想闭上眼睛想如何让我们的软件更加可用可维护时,我们总能想到一个词:松耦合.在这篇文章中,主要讲述了模块间存在的依赖关系,但这种依赖关系违背了依赖倒置原则.在这之后,我们将讨论一种解除软 ...
- 向 Web 开发人员推荐35款 JavaScript 图形图表库
图表是数据图形化的表示,通过形象的图表来展示数据,比如条形图,折线图,饼图等等.可视化图表可以帮助开发者更容易理解复杂的数据,提高生产的效率和 Web 应用和项目的可靠性. 在这篇文章中,我们收集了3 ...