MVC之验证

有时候我觉得,很多人将一个具体的技术细节写的那么复杂,我觉得没有必要,搞得很多人一头雾水的,你能教会别人用就成了,具体的细节可以去查MSDN什么的,套用爱因斯坦的名言:能在网上查到的就不要去记,用的时候拿过来就是。应用层面的东东,没必要深究,真正的核心已经被那些大胡子老外们搞定了,你要说你非想搞明白某个东东,那你可以把你的时间用在架构和管理上去,亦或是你也搞个编译器(搞swift语言的那家伙就是捯饬的这个)什么的,玩玩金融,甚至把把妹子都比你去研究一门最底层的技术细节强,我们常说面向抽象编程,说白了就是低层要依赖高层,所以还是研究点高端的东东对你以后有帮助!

言归正传,MVC验证走起,不过只此一篇,希望能讲多少是多少吧!

一、基于数据注解特性的验证

SO EASY:

A、你如果想用数据注解特性,那就必须要引入以下命名空间:using System.ComponentModel.DataAnnotations;

可以注意到,这个命名空间不是以System.Web开头的,这也说明了它并不单单是为Web项目准备的,如何其它类型的项目都可以使用。

例如:对于一个注册用的model,在其上面用特性验证

using System.ComponentModel.DataAnnotations;
namespace Ctrip.Models
{
public class Register
{
[Required(ErrorMessage="用户名必须填写")]
[MinLength(6,ErrorMessage="用户名长度过短")]
public String UserName { get; set; }
[DataType(DataType.Password)]
public String Password { get; set; }
[DataType(DataType.Password)]
[Compare("Password",ErrorMessage="密码要一致")]
public String RptPassword { get; set; }
public String Email { get; set; }
public DateTime BirthDate { get; set; }
}
}

注:错误消息还可以用占位符,体会一下好处在哪

[Required(ErrorMessage=”Your {0} is required.”)]

public string Name { get; set; }

B、在view中用HtmlHelper的方法就可以实现客户端验证了(前提是要开启客户端验证)

@Html.ValidationSummary()会输出所有验证错误, 一般放在Form头处
@Html.ValidationMessageFor()是针对单个输入的验证

大概就是下面的格式:

@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary() <fieldset>
<legend>Registration Form</legend>
<ol>
<li>
@Html.LabelFor(m => m.UserName)
@Html.EditorFor(m => m.UserName)
@Html.ValidationMessageFor(m => m.UserName)
</li>
<li>
@Html.LabelFor(m => m.Password)
@Html.EditorFor(m => m.Password)
@Html.ValidationMessageFor(m => m.Password)
</li>
<li>
@Html.LabelFor(m => m.Email)
@Html.TextBoxFor(m => m.Email)
@Html.ValidationMessageFor(m => m.Email)
</li>
<li>
@Html.LabelFor(m => m.BirthDate)
@Html.EditorFor(m => m.BirthDate)
@Html.ValidationMessageFor(m => m.BirthDate)
</li>
</ol>
<input type="submit" value="Register" />
</fieldset>
}

这个时候如果你不处理后端,只要客户端允许JS运行,就可以在客户端验证,而且是AJAX验证哦,不解释~

备注:客户端验证在哪里开启与关闭呢?在web.config里边,true or false,你说了算!

<appSettings>
<add key="ClientValidationEnabled" value="false" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

C、搞定后端验证

有些人说在控制器里边写一个专门的Valid()方法验证,我说这不是作死的节奏啊,有肉还吃豆腐?呵呵,说的就是下面这个东东ModelState.IsValid

[HttpPost]
public ActionResult Create(Register register)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index", "Home");
}
return View(register);
}

D、验证特性特别多,想要看的自己上网查,或者反编译上面的那个命名空间就可以看到!不过有两个特性比较特殊,是在System.Web.Mvc命名空间里边:
     RemoteAttribute和CompareAttribute,CompareAttribute的用法上面的A中已有,下面举个RemoteAttribute的例子,就是我们在网站注册的时候,要求用户名不能重复,可以用这个RemoteAttribute实现,是异步的~

public class Employee
{
public int EmpId { get; set; }
[DisplayName("Employee Name")]
[Remote("IsEmployeeNameAvailable", "Validation")] //使用RemoteAttribute,指定验证的Controller和Action
public String EmployeeName { get; set; } }

然后你再写个Action就行了,由于比较简单这里就不再写了!
警告:这个RemoteAttribute是只进行客户端验证的,服务器端不验证的,所以如果某个用户屏蔽了客户端js那就没用了

注:正则表达式特性也很有用的,例如:

[RegularExpression(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}”,ErrorMessage=”Email doesn’t look like a valid email address.”)]

具体的正则表达式你可以上网搜~

二、自定义数据注解特性验证

先说说什么是双重验证?

其实就是客户端验证加服务器端验证而已~

为什么要双重验证?

首先,客户端验证能够直接响应客户,减少了服务器压力的同时还提高了用户体验,但是你永远不能信任来自客户端的信息(用户可以关闭浏览器的脚本功能,让你的js验证彻底不起作用),所以服务器端验证也是必须的~

常规验证可以通过上面列出的这些系统预定义ValidationAttribute特性来完成,但是在很多情况下我们需要通过创建自定义的ValidationAttribute特性来解决一些特殊的验证,而且这些自定义的特性在很多地方可以重用的!

你需要做的就是重写ValidationAttribute里边的方法IsValid()而已

举个栗子:

using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions; namespace MvcValidation.Extension
{
public class EmailAttribute : ValidationAttribute
{
public const string reg = @"^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]+$"; public EmailAttribute()
{
} //重写基类方法
public override bool IsValid(object value)
{
if (value == null)
return true; if (value is string)
{
Regex regEx = new Regex(reg);
return regEx.IsMatch(value.ToString());
}
return false;
}
}
}

用的话,就是下面的样子:

[Email]
public string Email { get; set; }

注意:
此时的自定义的验证特性只支持后端验证,如果想支持前端jquery验证,还需要实现 IClientValidatable接口

所以改写一下:

using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using System.Web.Mvc; namespace MvcValidation.Extension
{
public sealed class EmailAttribute : ValidationAttribute, IClientValidatable
{
public const string reg = @"^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]+$"; public EmailAttribute()
{
} //重写基类方法
public override bool IsValid(object value)
{
if (value == null)
return true; if (value is string)
{
Regex regEx = new Regex(reg);
return regEx.IsMatch(value.ToString());
}
return false;
} public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
ModelClientValidationRule rule = new ModelClientValidationRule
{
ValidationType = "email",
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
};
yield return rule;
}
}
}

注意:
ValidationType属性的值一定要小写,否则报错。

其实还没有结束呢,还要扩展JQuery函数(jQuery.validator.email.js文件)

//扩展方法
$.validator.addMethod("email", function (value, element) {
if (value == false) {
return true;
}
this.optional(element) || /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]+$/i.test(value);
}); //扩展方法注册
$.validator.unobtrusive.adapters.addBool("email");

其实实现IClientValidatable之后,就是为前端的Email输入input标签添加了一个data-val-email属性而已,属性中的“email”就是ValidationType = "email"中的名字。

三、带自我验证的模型

适用场景:不需要重用验证逻辑,只是针对某一个特定的模型进行验证。

这些带自我验证的模型实现了接口IValidatableObject,该接口定义在“System.ComponentModel.DataAnnotations”命名空间下。

public interface IValidatableObject
{
IEnumerable<ValidationResult> Validate( ValidationContext validationContext);
}

举个栗子:

public class Person: IValidatableObject
{
[DisplayName("姓名")]
public string Name { get; set; }
[DisplayName("性别")]
public string Gender { get; set; }
[DisplayName("年龄")]
public int? Age { get; set; }
public IEnumerable<ValidationResult> Validate( ValidationContext validationContext)
{
Person person = validationContext.ObjectInstance as Person;
if (null == person)
{
yield break;
}
if(string.IsNullOrEmpty(person.Name))
{
yield return new ValidationResult("'Name'是必需字段", new string[]{"Name"});
}
if (string.IsNullOrEmpty(person.Gender))
{
yield return new ValidationResult("'Gender'是必需字段", new string[] { "Gender" });
}
else if (!new string[]{"M","F"}.Any( g=>string.Compare(person.Gender,g, true) == 0))
{
yield return new ValidationResult("有效'Gender'必须是'M','F'之一", new string[] { "Gender" });
}
if (null == person.Age)
{
yield return new ValidationResult("'Age'是必需字段", new string[] { "Age" });
}
else if (person.Age > 25 || person.Age < 18)
{
yield return new ValidationResult("'Age'必须在18到25周岁之间", new string[] { "Age" });
}
}
}

四、自定义验证的错误消息

通过在自定义验证特性中重写FormatErrorMessage方法来实现:

using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using System.Web.Mvc; namespace MvcValidation.Extension
{
public sealed class EmailAttribute : ValidationAttribute, IClientValidatable
{
public const string reg = @"^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]+$"; public EmailAttribute()
{
} //重写基类方法
public override bool IsValid(object value)
{
if (value == null)
return true; if (value is string)
{
Regex regEx = new Regex(reg);
return regEx.IsMatch(value.ToString());
}
return false;
} public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
ModelClientValidationRule rule = new ModelClientValidationRule
{
ValidationType = "email",
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
};
yield return rule;
}
/// <summary>
/// 格式化错误信息
/// </summary>
/// <param name="name">属性名</param>
/// <returns></returns>
public override string FormatErrorMessage(string name)
{ return this.ErrorMessage ?? string.Format("{0}属性没有输入正确的Email", name);
}
}
}

最后,有一些验证还可以用JQuery实现,基本上属于js的东东,这里不再陈述~

本人对MVC验证也只是略懂一二,所以就写这么多吧~

MVC之验证的更多相关文章

  1. ASP.NET MVC Model验证(五)

    ASP.NET MVC Model验证(五) 前言 上篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现, 然而在MVC框架中还给我们提供了其它 ...

  2. ASP.NET MVC Model验证(四)

    ASP.NET MVC Model验证(四) 前言 本篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现,前者是Model验证提供程序,而Mod ...

  3. ASP.NET MVC Model验证(三)

    ASP.NET MVC Model验证(三) 前言 上篇中说到在MVC框架中默认的Model验证是在哪里验证的,还讲到DefaultModelBinder类型的内部执行的示意图,让大家可以看到默认的M ...

  4. ASP.NET MVC Model验证(二)

    ASP.NET MVC Model验证(二) 前言 上篇内容演示了一个简单的Model验证示例,然后在文中提及到Model验证在MVC框架中默认所处的位置在哪?本篇就是来解决这个问题的,并且会描述一下 ...

  5. ASP.NET MVC Model验证(一)

    ASP.NET MVC Model验证(一) 前言 前面对于Model绑定部分作了大概的介绍,从这章开始就进入Model验证部分了,这个实际上是一个系列的Model的绑定往往都是伴随着验证的.也会在后 ...

  6. MVC 数据验证

    MVC 数据验证 前一篇说了MVC数据验证的例子,这次来详细说说各种各样的验证注解.System.ComponentModel.DataAnnotations 一.基础特性 一.Required 必填 ...

  7. ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view)

    在本节中,您将验证电影控制器生成的编辑方法(Edit action methods)和视图.但是首先将修改点代码,使得发布日期属性(ReleaseDate)看上去更好.打开Models \ Movie ...

  8. 【MVC】ASP.NET MVC Forms验证机制

    http://www.cnblogs.com/bomo/p/3309766.html 随笔 - 121  文章 - 0  评论 - 92 [MVC]ASP.NET MVC Forms验证机制 ASP. ...

  9. MVC数据验证原理及自定义ModelValidatorProvider实现无编译修改验证规则和错误信息

    Asp.net MVC中的提供非常简单易用的数据验证解决方案. 通过System.ComponentModel.DataAnnotations提供的很多的验证规则(Required, StringLe ...

  10. MVC 数据验证[转]

    前一篇说了MVC数据验证的例子,这次来详细说说各种各样的验证注解. 一.基础特性 一.Required 必填选项,当提交的表单缺少该值就引发验证错误. 二.StringLength 指定允许的长度 指 ...

随机推荐

  1. JavaScript-2.2 document.write 输出到页面的内容

    <html> <head> <meta http-equiv="content-type" content="text/html;chars ...

  2. React组件开发入门

    React 组件开发入门 Introduction 本文组成: Ryan Clark文章Getting started with React的翻译. 博主的实践心得. React由Facebook的程 ...

  3. ZOJ-3652-Maze(BFS)

    Celica is a brave person and believer of a God in the bright side. He always fights against the mons ...

  4. Java存储区域——JVM札记&lt;一个&gt;

    Java当虚拟机数据区域 执行数据区主要包括:方法区.堆.VM栈.本地方法栈.程序计数器. 当中方法区和栈是线程共享的区域,另外三块区域是每一个线程私有的区域.各个数据区的功能简单说明例如以下: 程序 ...

  5. 标签(Tag)的各种设计方案

    标签(Tag)的各种设计方案 首先,标签(Tag)是什么? 我的理解:用来具体区分某一类内容的标识,和标签类似的一个概念是分类(Category),有一个示例可以很好的区分它们两个,比如人类分为:白种 ...

  6. thinkphp学习笔记5—模块化设计

    原文:thinkphp学习笔记5-模块化设计 1.模块结构 完整的ThinkPHP用用围绕模块/控制器/操作设计,并支持多个入口文件盒多级控制.ThinkPHP默认PATHINFO模式,如下: htt ...

  7. maven 编

    Eclipse   对    run  as   [Run Configurations] main标签. Goals:输入命令:clean install -Dmaven.test.skip=tru ...

  8. Android Intent机制与常见的用法

    Activity Android于.Activity所有的程序都是必不可少,程都执行在Activity之中.Activity具有自己的生命周期(见http://www.cnblogs.com/feis ...

  9. ASP.NET上传文件的几种方法

      //上传文件实例 if (fileDealer.HasFile)//判断文件是否存在        {            string filepath = "";     ...

  10. 关于启动调试时,总是启动多个web端口的问题

    在一个解决方案中,经常包含多个web项目,当设置某一个web项目为起始项目后,启动调试,会发现其他的web项目的端口也会一起打开,显示在电脑的右下方,其实开启其他端口有时是没必要的,只是多占用了系统内 ...