第十节:数据批注(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基础——3特性
特性 切片 L=[0,1,2,3,4,5,6,7,8,9,10] L[:3]=[0,1,2] L[-2:]=[9,10] L[1:3]=[1,2] L[::3]=[0,3,6,9] L[:5:2]=[ ...
- python之sqlalchemy的使用
准备数据 from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column from sqla ...
- github使用个人总结
1.获取github上面的源码时候,不能获取最新的,因为你的开发工作不一定是最新的要下载历史版本. 2.要使用里面的文件的时候,可以在目录后面url后面添加downloads 这样可以找到封装好的版本 ...
- ideal中把项目打成war包,并放在tomcat运行,遇见的问题。。。
先说下我遇见的问题吧:最近做项目要把项目放在tomcat上运行,用的springboot框架, 在建项目时选择的是 jar包,项目写完要部署打包是,在pom中虽然把包改成了war ,可是每次放入to ...
- 使用Jasypt对SpringBoot配置文件加密(转)
文章转自 https://www.jianshu.com/p/323ec96c46d2 引入jasypt <dependency> <groupId>com.github. ...
- leetcode 263. Ugly Number 、264. Ugly Number II 、313. Super Ugly Number 、204. Count Primes
263. Ugly Number 注意:1.小于等于0都不属于丑数 2.while循环的判断不是num >= 0, 而是能被2 .3.5整除,即能被整除才去除这些数 class Solution ...
- android 图片上传图片 报Socket: Broken pipe
上传图片的时候报如下错误: 上传失败的原因是服务器限制了文件上传的大小.让服务端改一下配置文件就好了
- 关于wxpython多线程研究包括(import Publisher等错误研究)
作为一个自动化测试人员,开发基本的应用桌面程序是必须的!最近在研究wxpython相关知识,目前看到多线程一块,发现官方文档介绍说:"在线程中不能修改修改窗口属性!",但是实际情况 ...
- THUWC2019:Reach out
竟然还有机会去THUWC!!! 不过没有上WC线感觉有点可惜-- Day -INF~Day -2 考完NOIP两周滚回来被神仙们吊打 先是做专题,为什么会选到构造啊(ノ`Д)ノ 我构造专题有7道题留作 ...
- 【原创】架构师必备,带你弄清混乱的JAVA日志体系!
引言 还在为弄不清commons-logging-xx.jar.log4j-xx.jar.sl4j-api-xx.jar等日志框架之间复杂的关系而感到烦恼吗? 还在为如何统一系统的日志输出而感到不知所 ...