客户端验证逻辑会对用户向表单输入的数据给出一个即时反馈。而之所以需要服务器端验证,是因为来自网络的信息都是不能被信任的。

当在ASP.NET MVC设计模式上下文中谈论验证时,主要关注的是验证模型的值

数据注解特性定义在名称空间System.ComponentModel.DataAnnotations中,它们提供了服务器端验证的功能。当在模型的属性上使用这些属性时,框架也支持客户端验证。在名称空间DataAnnotations中,有4个特性可以用来应对一般的验证场合。

1.1 Required

因为客户的名字是必须的,所以需要在模型类的属性上添加Required特性

 [Required]
public string FirstName{ get; set;}

当属性是null或空时,Required特性将会引发一个验证错误。

1.2 StringLength

校验数据的长度

 [Required]
[StringLength()]
public string FirstName { get; set;}

当数据长度超过160则会提醒。MinimumLength参数是一个可选项,用于设定字符串的最小长度,如下(长度>=3且<=160)

 [Required]
[StringLength(, MinimumLength=)]
public string FirstName { get; set;}

1.3 RegularExpression

用于正则表达式的验证,用于邮箱、电话等属性。

 [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}")]
public string Email {get; set;}

1.4 Range

Range 特性用来指定数值类型值的最小值和最大值。

限定年龄在35~44之间:

 [Range(,)]
public int Age {get; set;}

限定价格在0.00~49.99之间,该重载方法可限定数据类型:

 [Range(typeof(decimal),"0.00", 49.00)]
public decimal Price {get; set;}

 1.5 Compare

Compare特性确保模型对象的两个属性拥有相同的值,一般用于校验客户的重复输入数据

 [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}")]
public string Email {get; set;} [Compare("Email")]
public string EmailConfirm {get; set;}

如果两次输入的e-mail地址不一致,将会提醒。

1.6 Remote

ASP.NET MVC框架还为应用程序在名称空间System.Web.Mvc中额外添加了Remote验证特性。

Remote特性可以利用服务器端的回调函数执行客户端的验证逻辑。例如避免用户注册时在数据库中产生相同用户名的用户,可以使用Remote特性把UserName的值发送到服务器,然后在服务器端的数据库中与相应的表字段值进行比较:

 [Remote("CheckUserName", "Account")]
public string UserName {get ; set;}

在特性中可以设置客户端代码要调用的控制器名称可操作名称。客户端代码会自动把用户输入的UserName属性值发送发到服务器,该特性的一个重载构造方法还允许指定要发送给服务器的其他字段:

 public JsonResult CheckUserName (string username)
{
var result = Membership.FindUserByName(username).Count == ;
return Json(result, JsonRequestBehavior.AllowGet);
}

上面的控制器操作会利用与UserName属性同名的参数进行验证,并返回一个封装在JacaScript Object Notation(JSON)对象中的布尔类型值(true或false)

2.1 自定义错误提示消息及其本地化

每个验证特性都允许传递一个带有自定义错误提示消息的参数。

 [Required( ErrorMessage = "Your last name is required")]
[StringLength(, ErrorMessage="Your last name is too long")]
public string LastName {get ; set ;}

自定义的错误提示消息在字符串中也有一个格式项。内置特性使用友好的属性显示名称格式化错误提示消息字符串

  [Required( ErrorMessage = "Your {0} is required")]
[StringLength(, ErrorMessage="Your last name is too long")]
public string LastName {get ; set ;}

如果应用程序是多语言的,硬编码的方式就不适用了。可以为验证特性都允许为本地化的错误提示消息指定资源类型和资源名称。

 [Required(ErrorMessageResource = typeof(ErrorMessages),
ErrorMessageResourceName="LastNameRequired")]
[StringLength(, ErrorMessageResourceType = typeof(ErrorMessage),
ErrorMessageResourceName = "LastNameTooLong")]
public string LastName { get; set;}

3.自定义验证逻辑

两个核心应用方法:

  • 将验证逻辑封装在自定义的数据注解中
  • 将验证逻辑封装在模型对象中

把验证逻辑封装在自定义数据注解中可以实现多个模型中重用逻辑,这需要在特性内部编写代码以应对不同类型的模型,但一旦实现,新的注解就可以在多处重用。

另一方面,如果将验证逻辑直接放入模型对象中,就意味着验证逻辑可以很容易地编码实现,因为这样只需要关心一种模型对象的验证逻辑,从而方便了对对象的状态和结构做某些假定,但这种方式不利于实现逻辑的重用。

3.1 自定义注解

所有的验证注解(如Required和Range)特性最终都派生自基类ValidationAttribute,它是个抽象类,在名称空间System.ComponentModel.DataAnnotations中定义。所以,程序的验证逻辑也必须派生自ValidationAttribute类

 using System.ComponentModel.DataAnnotations;

 namespace MvcMusicStore.Infrastructure
{
public clsaa MaxWordsAttribute : ValidationAttribute
{
.......
}
}

为了实现验证逻辑,至少需要重写基类中提供的IsValid方法的其中一个版本。重写IsValid方法时利用的ValidationContext参数,提供了很多可在IsValid方法内部使用的信息,如模型类型、模型对象实例、用来验证属性的人性化显示名称以及其他有用的信息。

此处验证单词输入数量,并设置默认错误提示信息:

  using System.ComponentModel.DataAnnotations;

  namespace MvcMusicStore.Infrastructure
{
public clsaa MaxWordsAttribute : ValidationAttribute
{
public MaxWordsAttribute(int maxWords) : base("{0} has too many words.")
{
_maxWords = maxWords;
} protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
var valueAsString = value.ToString();
if( valueAsString.Split(' ').Length > _maxWords)
{
var errorMessage = FormatErrorMessage(validationContext.DisplayName);
return new ValidationResult(errorMessage);
}
return ValidationResult.Success;
}
private readonly int _maxWords;
}
}

FormatErrorMessage可以使用合适的错误提示消息字符串(即使这个字符串是存储在一个本地资源文件中)。这条代码语句需要传递name属性的值,这个值可以通过validationContext参数的DisplayName属性获得。构造完验证逻辑后,就可以将其应用到任何模型属性上:

 [Required]
[StringLength()]
[MaxWords()]
public string LastName {get ; set ;}

甚至可以赋予特性自定义的错误提示消息:

  [Required]
[StringLength()]
[MaxWords(, ErrorMessage = "There are too many words in {0}")]
public string LastName {get ; set ;}

IValidatableObject

自验证(self-validating)模型是指一个知道如何验证自身的模型对象。一个模型对象可以通过实现IValidatableObject接口来实现对自身的验证。下面在Order模型中直接实现对LastName字段中单次个数的检查:

 public class Order : IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext ValidationContext)
{
if(LastName != null && LastName.Split(' ').Length > )
{
yield return new ValidationResult("The last name has too many words!",
new []{"LastName"});
}
//....
}
}

这种方式与特性版本有几个明显的不同点:

  • MVC运行时为执行验证而调用的方法名称是Validate而不是IsValid,但更重要的是,它们返回类型和参数不同
  • Validate的返回类型是IEnumerable<ValidationResult>,而不是单独的ValidationResult对象。因为从表面上看,内部的验证逻辑验证的是整个模型,因此可能返回多个验证错误。
  • 这里没有value参数传递给Validate方法,因为在此Validate是一个模型实例方法,在其内部可以直接访问当前模型对象的属性值。

4.显示和编辑注解

4.1 Display

Display特性可为模型属性设置友好的“显示名称”

  [Required]
[StringLength()]
[Display(Name="Last Name", Order=)]
public string FirstName { get; set;}

4.2 ScaffoldColumn

ScaffoldColumn特性可以隐藏HTML辅助方法(如EditorForModel和DisplayForModel)渲染的一些属性:

 [ScaffoldColumn(false)]
public string Username {get; set;}

添加了这个特性之后,EditorForModel辅助方法将不再为Username字段显示输入元素和Label标签。然而需要注意的是,如果模型绑定器在请求中看到匹配的值,那么他仍然会试图为Username属性赋值。

4.3 DisplayFormat

通过命名参数,DisplayFormat特性可用来处理属性的各种格式化选项。当属性包含空值时,可以提供可选的显示文本,也可以为包含标记的属性关闭HTML编码,还可以为运行时指定一个应用于属性值的格式化字符串。

下面的代码可将模型的Total属性值格式化为货币值形式:

 [DisplayFormat ( ApplyFormatInEditMode = true, DataFormatString "{0:c}")]
public decimal Total {get; set;}

4.4 ReadOnly

如果需要确保默认的模型绑定器不使用请求中的新值来更新属性,可在属性上添加ReadOnly特性:

 [ReadOnly(true)]
public decimal Total {get; set;}

4.5 DataType

DataType特性可为运行时提供关于属性的特定用途信息。例如,String类型的属性可应用与e-mail地址、URL或是密码。DataType特性可满足所有这些需求:

 [Required]
[DataType(DataType.Password)]
[Display(name="Password")]
public string Password {get; set;}

其他的数据类型还有Currency、Date、Time和MultilineText。

5其他特性

UIHint:

给ASP.NET MVC运行时提供了一个模版名称,以备调用模版辅助方法(如DisplayFor和EditorFor)渲染输出时使用。也可以定义自己的模版辅助方法来重写ASP.NET MVC的默认行为。找不到UIHint指定的模版时,MVC会寻找一个合适的替代模版使用。

HiddenInput:

渲染一个type特性值为“hidden”的输入元素。

ASP.NET MVC5高级编程 之 数据注解和验证的更多相关文章

  1. ASP.NET MVC5 高级编程 第5章 表单和HTML辅助方法

    参考资料<ASP.NET MVC5 高级编程>第5版 第5章 表单和HTML辅助方法 5.1 表单的使用 5.1.1 action 和 method 特性 默认情况下,表单发送的是 HTT ...

  2. ASP.NET MVC5 高级编程 第3章 视图

    参考资料<ASP.NET MVC5 高级编程>第5版 第3章 视图 3.1 视图的作用 视图的职责是向用户提供界面. 不像基于文件的框架,ASP.NET Web Forms 和PHP ,视 ...

  3. ASP.NET MVC5 高级编程 第2章 控制器

    参考资料<ASP.NET MVC5 高级编程>第5版 第2章 控制器 控制器:响应用户的HTTP 请求,并将处理的信息返回给浏览器. 2.1 ASP.NET MVC 简介 MVC 模式中的 ...

  4. ASP.NET MVC5高级编程 之 Ajax

    jQuery不仅支持所有现代浏览器,包括IE.Firefox.Safari.Opera和Chrome等,还可以在编写代码和浏览器API冲突时隐藏不一致性(和错误). 1. jQuery jQuery擅 ...

  5. ASP.NET MVC5 高级编程-学习日记-第一章 入门

    1.1 ASP.NET MVC 简介 ASP.NET是一种构建Web应用程序的框架,它将一般的MVC(Model-View-Controller)模式应用于ASP.NET框架. 1.1.1 MVC模式 ...

  6. ASP.NET MVC5高级编程 之 模型

    1. 为MVC Music Store建模 Models文件夹(右击) --> 添加 --> 类 为类添加对应的属性: public class Album { public virtua ...

  7. ASP.NET MVC5高级编程 之 HTML辅助方法

    Html属性调用HTML辅助方法,Url属性调用URL辅助方法,Ajax属性调用Ajax辅助方法. HTML辅助方法 1.Html.BeginForm @using (Html.BeginForm(& ...

  8. 学习《ASP.NET MVC5高级编程》——基架

    基架--代码生成的模板.我姑且这么去定义它,在我学习微软向编程之前从未听说过,比如php代码,大部分情况下是我用vim去手写而成,重复使用的代码需要复制粘贴,即使后来我在使用eclipse这样的IDE ...

  9. ASP.NET MVC5高级编程 之 视图

    1.1理解视图约定 当创建一个项目模版时,可以注意到,项目以一种非常具体的方式包含了一个结构化的Views目录.在每一个控制器的View文件夹中,每一个操作方法都有一个同名的视图文件与其对应.这就提供 ...

随机推荐

  1. mongoTemplate简单用法(增删改查)

    分页时查找数量: public long countSample(String id) { Query query = new Query(); if (StringUtil.hasText(id)) ...

  2. spring容器加载完毕做一件事情(利用ContextRefreshedEvent事件)转

    关键字:spring容器加载完毕做一件事情(利用ContextRefreshedEvent事件) 应用场景:很多时候我们想要在某个类加载完毕时干某件事情,但是使用了spring管理对象,我们这个类引用 ...

  3. C#与数据库访问技术总结(十四)之DataAdapter对象

    DataAdapter对象 DataAdapter对象主要用来承接Connection和DataSet对象. DataSet对象只关心访问操作数据,而不关心自身包含的数据信息来自哪个Connectio ...

  4. 鸟哥的linux私房菜之vim

    vim是vi的进阶版本

  5. 队列(Queue)--环形队列、优先队列和双向队列

    1. 队列概述 队列和堆栈都是有序列表,属于抽象型数据类型(ADT),所有加入和删除的动作都发生在不同的两端,并符合First In, First Out(先进先出)的特性. 特性: ·FIFO ·拥 ...

  6. 如何用docker安装laravel开发环境

    如何用docker安装laravel开发环境 看laravel框架的官方文档安装部分时,发现需要安装特别多软件,估计还有许多复杂的配置,官方推荐使用Laravel Homestead虚拟机进行安装,但 ...

  7. opencv学习之路(30)、分水岭算法及图像修补

    一.简介 二.分水岭算法 #include "opencv2/opencv.hpp" using namespace cv; void main() { Mat srcImg = ...

  8. python21期day01笔记总结

    2019.3.27 S21 day01笔记总结 一.计算机基础知识 1.计算机组成 用户 应用软件程序开发——用到了两个方面: 1语法 : 2解释器.编译器.虚拟机: 操作系统的开发 硬件组成 2.操 ...

  9. ss客户端的使用

    这里假设读者已经搭建了ss服务.教程 客户端安装 客户端可以通过GitHub上搜索,这里就不写太详细了,避免文章被禁掉. 比如对于mac的用户,可以选择这个 客户端配置 点击程序图标以展开菜单栏 服务 ...

  10. BZOJ.1901.Dynamic Rankings(树状数组套主席树(动态主席树))

    题目链接 BZOJ 洛谷 区间第k小,我们可以想到主席树.然而这是静态的,怎么支持修改? 静态的主席树是利用前缀和+差分来求解的,那么对于每个位置上的每棵树看做一个点,拿树状数组更新. 还是树状数组的 ...