第十节:数据批注(DataAnnotationModel)和自定义验证(包括Model级别的验证)
一. 简介
写完上一个章节MVC中的常用特性,迫不及待将该系列补全,该章节主要介绍数据批注(也叫:注解)。
一听【数据批注】,好高大上的名字,但仔细一看,它们其实是【System.ComponentModel.DataAnnotations】程序集下的一些特性类,O(∩_∩)O哈哈~,既然是特性,就符合特性的所有特征,只不过这些特性是作用于“属性”上的。
再一看【System.ComponentModel.DataAnnotations】这个命名空间,有点眼熟,与之前EF中的一篇文章【EF的CodeFirst模式通过DataAnnotations修改默认协定】中的一类操作来源于同一个命名空间下。
所以综上所述:该命名空间下的特性,在EF中可以用来映射生成数据库中的表字段,在日常开发中也可以用于做类中属性的限制和验证。
原理:均继承了ValidationAttribute特性,通过覆写IsValide方法进行校验。
适用场景:很多项目需要客户端和服务器端进行双重格式验证,使之更加安全,这时服务器端就可以使用数据批注了来进行校验了。
以Required特性为例,查看一下源码:

二. 常用的数据批注
这里总结一下【System.ComponentModel.DataAnnotations】命名空间下常用的数据批注,即特性。
① Key :声明主键
② Required:非空声明
③ MinLength和MaxLength:设置string类型的最大长度和最小长度,数据库的对应nvarchar
④ StringLength:设置string类型的长度,数据库对应nvarchar
⑤ Compare:新老密码对比
⑥ RegularExpression:正则的匹配
⑦ Phone:验证手机号码
⑧ Range:验证范围
⑨ Timestamp:将byte[]类型设置为timestamp类型
⑩ ConcurrencyCheck:并发检查,执行update操作时,会检查并发性(乐观锁) (在后面并发章节着重介绍Timestamp和ConcurrencyCheck)
另外还有一些不是很常用的,如:
① DisplayName:声明属性的名称
② Remote:远程验证,需要JQuery插件的支持 (这里不做测试等待补充 参考: https://www.cnblogs.com/JustRun1983/p/3505151.html)
下面补充一下该命名空间反射源码,可以自行查找需要的批注:


代码测试:
(1). 实体类,在其属性上添加数据标注
/// <summary>
/// 用户信息类 ,用于测试框架本身提供的数据批注
/// </summary>
public class UserInfor
{
[Required]
public string id { get; set; } [StringLength()]
public string userName { get; set; } [MaxLength()]
public string userMsg { get; set; } [Range(, )]
public int userAge { get; set; } [RegularExpression("[a-d]")] //a-d中的一个
public string userMsg3 { get; set; } [Phone]
public string userPhone { get; set; } public string userOldPwd { get; set; } [Compare("userOldPwd")] //比较和userOldPwd的值是否相等
public string userNewPwd { get; set; } }
(2). 前端代码
//1. 测试数据批注
$("#btn1").click(function () {
$.ajax({
type: "Post",
url: "TestDataAnnotationModel",
data: {
"id":"123",
"userName": "mr12",
"userMsg": "ypf1234",
"userAge": 6,
"userMsg3": "a",
"userPhone": "15764222366",
"userOldPwd": "123456",
"userNewPwd":"123456" },
success: function (data) {
if (data == "ok") {
alert("测试通过");
}
if (data == "error") {
alert("测试未通过");
}
}
});
});
(3). 服务器端代码
public ActionResult TestDataAnnotationModel(UserInfor user)
{
//通过该方法进行验证
var isValidate = ModelState.IsValid; if (isValidate)
{
return Content("ok");
}
return Content("error");
}
三. 自定义数据批注
思路:通过上面的批注源码可知,均为自定义类继承:ValidationAttribute,覆写IsValid方法
需求:这里我们自定义一个批注,要求不为空,且长度区间为6-12位
使用方法同样为:action中通过实体接收,通过ModelState.IsValid的值为true或false来判断验证是否通过
代码测试:
(1). 实体类和自定义批注
/// <summary>
/// 角色类,用于测试自定义业务的数据批注
/// </summary>
public class RoleInfor
{ public string id { get; set; } [myOwnCheck]
public string roleName { get; set; }
} /// <summary>
/// 自定义数据批注,要求非空且长度为6-12位
/// </summary>
public class myOwnCheckAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
if (value != null && value.ToString().Length > && value.ToString().Length < )
{
return true;
}
return false;
}
}
(2). 前端代码
//2. 测试自定义业务逻辑的验证
$("#btn2").click(function () {
$.ajax({
type: "Post",
url: "TestMyOwnCheck",
data: {
"id": "",
"roleName": "mr12345"
},
success: function (data) {
if (data == "ok") {
alert("测试通过");
}
if (data == "error") {
alert("测试未通过");
}
}
});
});
(3). 服务器端代码
public ActionResult TestDataAnnotationModel(UserInfor user)
{
//通过该方法进行验证
var isValidate = ModelState.IsValid; if (isValidate)
{
return Content("ok");
}
return Content("error");
}
四. Model级别的验证扩展
实现IValidaableObjec接口,实现Validate方法。(了解即可)
public class CarInfor: IValidatableObject
{
public string id { get; set; } public string carName { get; set; } public int carAge { get; set; } IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
{
if (carAge % == )
{
var result = new ValidationResult("车龄验证不通过", new string[] { "carAge" }); yield return result;
}
}
}

第十节:数据批注(DataAnnotationModel)和自定义验证(包括Model级别的验证)的更多相关文章
- ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪
ASP.NET MVC深入浅出(被替换) 一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...
- centos shell编程6一些工作中实践脚本 nagios监控脚本 自定义zabbix脚本 mysql备份脚本 zabbix错误日志 直接送给bc做计算 gzip innobackupex/Xtrabackup 第四十节课
centos shell编程6一些工作中实践脚本 nagios监控脚本 自定义zabbix脚本 mysql备份脚本 zabbix错误日志 直接送给bc做计算 gzip innobacku ...
- 第三百一十四节,Django框架,自定义分页
第三百一十四节,Django框架,自定义分页 自定义分页模块 #!/usr/bin/env python #coding:utf-8 from django.utils.safestring impo ...
- CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第十节
原文链接 第十节:CUDPP, 强大的数据平行CUDA库Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在多 ...
- 第三百八十节,Django+Xadmin打造上线标准的在线教育平台—将所有app下的models数据库表注册到xadmin后台管理
第三百八十节,Django+Xadmin打造上线标准的在线教育平台—将所有app下的models数据库表注册到xadmin后台管理 将一个app下的models数据库表注册到xadmin后台管理 重点 ...
- 第三百七十节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索结果分页
第三百七十节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索结果分页 逻辑处理函数 计算搜索耗时 在开始搜索前:start_time ...
- 第三百一十节,Django框架,模板语言
第三百一十节,Django框架,模板语言 模板语言就是可以将动态数据在html模板渲染的语言 一.接收值渲染 locals()函数,写在请求响应render()函数里,可以将逻辑处理函数里的变量传到h ...
- centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 访问控制 apache rewrite 配置开机启动apache tcpdump 第二十节课
centos LAMP第二部分apache配置 下载discuz!配置第一个虚拟主机 安装Discuz! 用户认证 配置域名跳转 配置apache的访问日志 配置静态文件缓存 配置防盗链 ...
- 第十节:详细讲解一下Java多线程,随机文件
前言 大家好,给大家带来第十节:详细讲解一下Java多线程,随机文件的概述,希望你们喜欢 多线程的概念 线程的生命周期 多线程程序的设计 多线程的概念 多线程的概念:程序是静态的,进程是动态的.多进程 ...
随机推荐
- (转载)Python之道1-环境搭建与pycharm的配置django安装及MySQL数据库配置
近期做那个python的开发,今天就来简单的写一下开发路线的安装及配置, 开发路线 Python3.6.1+Pycharm5.0.6+Django1.11+MySQL5.7.18 1-安装Python ...
- cesium加载纽约市3dtiles模型
const tileset = new Cesium.Cesium3DTileset({ url: '../../assets/data/NewYork/tileset.json' }); viewe ...
- 在Linux系统中同步更新我们的Github博客
原理介绍 类似于版本管理,我们把我们的hexo博客文件系统在Github上建立一个分支,通过管理分支提交最新的博客文件系统,保证我们博客框架的更新.然后我们基于最新的博客框架,撰写文章,进行Githu ...
- Json多层对象访问
背景说明 本文主要记录演示,利用Gson工具,对多层的 Json 数据进行转换读取的示例.原始 Json 字符串格式化效果如下: 示例代码 import java.util.Iterator; imp ...
- 点击button自动刷新页面的奇葩错误
以前在写练习的时候遇到过这样一个问题,自己在html中写了一个button <button>test1</button> 在没有给其附上onclick事件时是点击是不会有任何反 ...
- Binary Search(Java)(非递归)
public static int rank(int[] array, int k) { int front = 0, rear = array.length - 1; while(front < ...
- 封装的通过微信JS-SDK实现自定义分享到朋友圈或者朋友的ES6类!
引言: 我们经常在做微信H5的过程中需要自定义分享网页,这个如何实现呢?请看如下的封装的ES6类及使用说明! /** * @jssdk js对象,包括appId,timestamp,nonceStr, ...
- springboot 学习进度
1 hello world --------------ok 主启动程序必须在层次结构的最上面. 2 配置 3.日志 4.Web开发 1)SpringBoot集成JSP的方法 配置applicatio ...
- PS调出韩式米黄色室内婚纱照片
原图: Camera Raw打开原图. 光线调整,压暗白色,保留高光细节,少量对比黑色压暗. 降低整体饱和. 曲线调整,压暗高光明度. 减红加青(融合色彩). 中间调,靠近暗部区域加蓝,靠近亮部区域加 ...
- Django rest framework(6)----序列化(2)
为什么要序列化 django 查询数据库返回的类型是 queryset 类型 而我们和前端通信使用的大多数是json类型,这个时候我们需要把 queryset的数据类型转换成python的数据类型然 ...