webapi - 模型验证
本次要和大家分享的是webapi的模型验证,讲解的内容可能不单单是做验证,但都是围绕模型来说明的;首先来吐槽下,今天下午老板为自己买了套新办公家具,看起来挺好说明老板有钱,不好的是我们干技术的又成了搬运工(谁叫技术部男的多呢哈哈),话说让我们搬点儿什么小座椅板凳就够了吧,为什么4大箱的家具都让我们动手,每箱东西拆分出来每件几乎需要至少4个人才能挪到的东西,而且不少呢,这是让我们搬完后不用上班的节奏吧;我很想问的是买这么贵的东西,难道不给包送和组装?行政部门就不能请点搬运工,非要节约这点钱(技术可不是兼职的搬运工啊)?东西少那是锻炼身体没关系,东西多了那就是折磨人,这里说的想必也是大众技术朋友们的心声吧呵呵;好了不多说了,本章内容希望大家喜欢,也希望各位多多扫码支持和点赞谢谢:
» 增加模型验证
» 自定义过滤器,输出模型验证信息
» FromUri和FromBody用途
下面一步一个脚印的来分享:
» 增加模型验证
首先,我们测试用例使用上一篇的 MoStudent 学生类,模型验证需要在对应提交类中的需要验证格式的属性增加一些注解标记,常用的标记有:
. Required:必须满足不为空
. RegularExpression:正则表达式验证
. StringLength:指定字符允许的范围
. DataType:数据类型,常用于密码类型,如: DataType.Password
. Range:指定数字允许的范围
这里我们实例的 MoStudent 类用到的注解,如下代码:
public class MoStudent
{ public int Id { get; set; } [Required(ErrorMessage = "名称必须填写")]
[RegularExpression(@"\w{2,15}", ErrorMessage = "名称应为2-15长度的字母组合")]
public string Name { get; set; } public bool Sex { get; set; }
public DateTime Birthday { get; set; }
}
然后,我们把保存学生的方法内容定义成这样,iis访问地址为 http://localhost:1001/s/add ,代码对应:
[Route("add")]
[HttpPost]
public HttpResponseMessage AddStudent(MoStudent moStudent)
{ if (ModelState.IsValid)
{ return Request.CreateResponse(HttpStatusCode.OK, moStudent);
}
return Request.CreateResponse(HttpStatusCode.BadRequest, ModelState);
}
这里的关键代码是 ModelState.IsValid ,通过这个来判断用户录入的信息是否满足我们定义在实体类中的注解规则,不满足我这里直接输出访问状态为 HttpStatusCode.BadRequest ,再来咋们用ajax提交添加学生表单到这个接口,但不录入任何学生信息,会得到console输出的返回的信息:
这里能看到404,明显从上面的代码来看走到了 Request.CreateResponse(HttpStatusCode.BadRequest, ModelState); 这段代码,也就是说 ModelState.IsValid 的结果是false,验证没有通过,因为我们在录入学生信息页面的文本框内,没有输入任何信息就直接提交的表单,所以这里验证没有通过;但是作为一个webapi接口而言,这种如果提交格式不正确,就直接返回400错误,这样明显不友好,那么我们需要做一下变动,首先需要定义一个公共接口返回类 MoResult ,该类主要用来作为webapi接口的统一返回数据格式标准(这也是通常接口需要的一种响应数据规则格式),我们定义如下格式代码:
/// <summary>
/// 结果输出类
/// </summary>
public class MoResult
{ /// <summary>
/// 0:失败,1:成功 其他
/// </summary>
public EnResultStatus Status { get; set; } /// <summary>
/// 错误信息
/// </summary>
public object Msg { get; set; } /// <summary>
/// 对象信息
/// </summary>
public object Data { get; set; }
} /// <summary>
/// 枚举类型
/// </summary>
public enum EnResultStatus
{
失败 = ,
成功 =
}
然后,调整下apiController对应保存学生信息的Action方法代码如:
[Route("add")]
[HttpPost]
public HttpResponseMessage AddStudent(MoStudent moStudent)
{ var moResult = new MoResult() { Msg = EnResultStatus.失败 };
try
{
if (ModelState.IsValid)
{
var isfalse = db.Save(moStudent);
moResult.Status = isfalse ? EnResultStatus.成功 : EnResultStatus.失败;
moResult.Data = moStudent;
}
else
{
//如果验证是吧,只取第一个错误信息返回
var item = ModelState.Values.Take().SingleOrDefault();
moResult.Msg = item.Errors.Where(b => !string.IsNullOrWhiteSpace(b.ErrorMessage)).Take().SingleOrDefault().ErrorMessage;
}
}
catch (Exception ex)
{
moResult.Msg = ex.Message;
}
return Request.CreateResponse(HttpStatusCode.OK, moResult);
}
需要注意的几点是:
1. 这里我们通过 MoResult 的Data属性来返回我们添加成功Student输入信息;
2. 如果 ModelState.IsValid 验证失败,取第一个验证错误信息返回给调用方,其目的让调用方能够提醒用户哪些信息录入的不全或者格式不对
好了咋们来一起看下这个时候ajax提交的空表单数据后,获取到webapi接口返回的数据信息如:
很明显这个错误信息就是咋们在实体 MoStudent 中对Name属性做的一个验证错误信息,再这里一个前端调用webapi接口验证的流程基本就完事了,当然一般这种空验证也是需要前端自己验证的,好了咋们也来看下,如果录入完成学生信息的表单提交过后会有什么样子的数据返回呢:
» 自定义过滤器,输出模型验证信息
首先,我们需要明确的是,任意webapi接口基本都是需要有请求参数的格式验证的,如果按照上一节直接在实体类中增加注解验证,那么我们就没必要在每一个api接口对应的action中再写代码 ModelState.IsValid 去判断是否验证成功,或者是获取验证后的错误信息了,因为webapi提供一个 ActionFilterAttribute Action过滤器,这个作用主要是请求到api的Action方法时候用来执行一些东西,本实例通过继承她,来自定义一个验证过滤器 ValidateModelAttribute ,主要用来统一获取验证错误信息,并且输出响应给调用方,下面先来看下代码:
/// <summary>
/// 模型格式验证
/// </summary>
public class ValidateModelAttribute : ActionFilterAttribute
{ public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{ if (!actionContext.ModelState.IsValid)
{ var moResult = new MoResult() { Msg = "请求数据异常", Status = EnResultStatus.失败 };
//自定义错误信息
var item = actionContext.ModelState.Values.Take().SingleOrDefault();
moResult.Msg = item.Errors.Where(b => !string.IsNullOrWhiteSpace(b.ErrorMessage)).Take().SingleOrDefault().ErrorMessage;
actionContext.Response = actionContext.Request.CreateResponse(System.Net.HttpStatusCode.OK, moResult);
}
}
}
同第一小节的代码差不多,主要用来判断是否通过实体类的注解验证,如果不通过获取第一个错误信息返回给调用方;这里要注意的是我们重写了 ActionFilterAttribute 过滤器中的 OnActionExecuting 方法;好了下面我们还需要把自定义的 ValidateModelAttribute 在 App_Start/WebApiConfig.cs 加入一下 config.Filters.Add(new ValidateModelAttribute()); 这个代码,意思吧自定义的过滤器假如到webapi中;再来咋们直接就可以在我们添加学生的Action上方使用 [ValidateModel] 标记来验证调用方传递给webapi的参数了,我们把学生添加Action AddStudent 代码改为如下所示:
[Route("add")]
[HttpPost]
[ValidateModel] //这里是自定义过滤
public HttpResponseMessage AddStudent(MoStudent moStudent)
{ var moResult = new MoResult();
try
{
var isfalse = db.Save(moStudent);
moResult.Status = isfalse ? EnResultStatus.成功 : EnResultStatus.失败;
moResult.Data = moStudent;
}
catch (Exception ex)
{
moResult.Msg = ex.Message;
}
return Request.CreateResponse(HttpStatusCode.OK, moResult);
}
然后,再用ajax提交一下空表单数据,会得到如图所示的信息:
能看出自定义验证过滤器效果和我们之前直接写在代码中验证的提示信息一样,总体来说自定义的验证使得api中的Action代码精简了很多,很提倡使用;
» FromUri和FromBody用途
首先,我们来看一段代码:
[Route("all01_2/{id:int?}")]
[AcceptVerbs("POST", "GET")]
public HttpResponseMessage GetAllStudents01_2(int id = )
{
var students = db.GetAll(); if (id > )
{
students = students.Where(b => b.Id == id).ToList();
} return Request.CreateResponse(HttpStatusCode.OK, students);
}
这里的action传递进来了一个名称id的参数,然后下面做了 id > 的判断来获取不同的数据,这种场景我们经常会遇到,并且查询条件的参数不止一个,这样来看我们会不断的在action里面增加传递的参数,格式可能会如此: public HttpResponseMessage GetAllStudents01_2(int id = ,参数2,参数3,参数...) ,这样如果需要用到的参数有10个以上,通常看起来不是很方便,这个时候FromUri和FromBody的用途就来了;先来看FromUri,首先需要我们把上面的那个Action方法的入参格式改成这样:
[Route(@"all01_3/{id:int=0}/{name?}")]
[AcceptVerbs("POST", "GET")]
public HttpResponseMessage GetAllStudents01_3([FromUri]MoSearch moSearch)
{
var students = db.GetAll().AsEnumerable(); if (moSearch.Id > )
{
students = students.Where(b => b.Id == moSearch.Id);
} if (!string.IsNullOrWhiteSpace(moSearch.Name))
{
students = students.Where(b => b.Name.Contains(moSearch.Name));
} return Request.CreateResponse(HttpStatusCode.OK, students);
}
通过实体类 MoSearch 来获取调用端传递的参数,实体类MoSearch定义的属性字段如:
public class MoSearch
{ public int Id { get; set; } public string Name { get; set; }
}
然后我们改造下查询学生列表的ajax请求方法如:
$("#btnSearch").on("click", function () { var tabObj = $("#tab tbody");
tabObj.html('tr><td colspan="4">加载中...</td></tr>'); var url = "http://localhost:1001/s/all01_3/1";
var txtName = $("input[name='txtName']").val();
if (txtName.length > ) {
url = url + "/" + txtName;
} $.get(url, function (data) { console.log(data); var tabHtml = [];
$.each(data, function (i, item) { tabHtml.push('<tr>');
tabHtml.push("<td>" + item.Id + "</td>");
tabHtml.push("<td>" + item.Name + "</td>");
tabHtml.push("<td>" + (item.Sex ? "男" : "女") + "</td>");
tabHtml.push("<td>" + item.Birthday + "</td>");
tabHtml.push('</tr>');
});
if (tabHtml.length <= ) { tabHtml.push('tr><td colspan="4">暂无数据</td></tr>'); } tabObj.html(tabHtml.join(''));
});
});
这里Id=1是固定了,直接查询id=1的学生信息,并且有一个可传递的参数学生名称txtName的值,如果用户没有输入学生名称,那么就不会加入到这个get请求中,下面来看下首先不输入学生姓名查询条件的效果:
这里能看出来只有学生编号为1的学生被查出来了,下面我们再录入姓名查询条件,能看到结果如:
能看到此时查不到名称为“小2”的学生信息,咋们再改成“小1”试试,
这个时候小1的学生能被查出来,这说明咋们的api的all01_3能够通过 FromUri]MoSearch moSearch 获取到我们输入的参数;下面我们使用FromBody来演示她的效果,首先需要修改js请求webapi格式如:
然后把webapi的all01_3修改为如下代码:
[Route(@"all01_3/{name?}")]
[AcceptVerbs("POST", "GET")]
public HttpResponseMessage GetAllStudents01_3([FromBody]MoSearch moSearch)
{
var students = db.GetAll().AsEnumerable(); if (moSearch.Id > )
{
students = students.Where(b => b.Id == moSearch.Id);
} if (!string.IsNullOrWhiteSpace(moSearch.Name))
{
students = students.Where(b => b.Name.Contains(moSearch.Name));
} return Request.CreateResponse(HttpStatusCode.OK, students);
}
主要区别吧FromUri换成了FromBody,最后咋们来一起看下没有录入学生名称查询条件的测试效果图:
录入学生查询条件后的效果图:
由上看出能正常查询出来数据,这说明 [FromBody]MoSearch moSearch 获取到了调用客户端的请求参数;好了FromBody和FromUri测试的例子就这些,这两者的区别这里总结下:
FromBody:主要用来获取post方式请求的参数
FromUri:主要获取url地址的请求参数(可以看成get方式)
这两者的效果对比我就不做了,有兴趣的朋友可以自己验证下;本次分享的内容就到这里吧,主要讲解了关于数据模型的一些知识,希望各位喜欢,多多点赞。
webapi - 模型验证的更多相关文章
- ASP.NET Core - 实现自定义WebApi模型验证
Framework时代 在Framework时代,我们一般进行参数验证的时候,以下代码是非常常见的 [HttpPost] public async Task<JsonResult> Sav ...
- 一、WebApi模型验证实践项目使用
一.启语 前面我们说到,模型验证的原理(包含1.项目创建,2.模型创建,3.走通测试模型验证,4.在过滤器中处理返回json格式(非控制器内))-完全是新手理解使用的,新番理解 通常情况下,对于那些经 ...
- 一、WebApi模型验证
一.新建项目 选择空的项目webapi 查看启动端口 创建控制器 添加方法 public class VerifController : ApiController { public IHttpAct ...
- .Net Core WebApi 模型验证无效时报400
问题 模型验证无效时,没有进入到接口里,而是直接报400 Bad Request,非常不友好. 环境 SDK:.Net Core 2.2.401 开发工具:VS2017 step 1 创建接口 /// ...
- 在asp.net WebAPI 中 使用Forms认证和ModelValidata(模型验证)
一.Forms认证 1.在webapi项目中启用Forms认证 Why:为什么要在WebAPI中使用Forms认证?因为其它项目使用的是Forms认证. What:什么是Forms认证?它在WebAP ...
- .Net高级进阶,WebApi和MVC进行模型验证的时候,教你如何自由控制需要进行验证的字段?
现在,你有一个MVC架构的web项目,你要完成一个注册功能. 前台传了3个值到你的控制器,分别是账号.密码.邮箱. 如图:现在你要在控制器里面判断,账号名称.密码.邮箱不能为空,并且名称和密码不超过1 ...
- webapi Model Validation 模型验证
通常情况下,对于那些经常为别人提供数据接口的开发人员来说,对于调用方传递过来的参数都会有验证处理.例如: if (string.IsNullOrEmpty(entity.Name)) { //当姓名为 ...
- WebAPI ModelValidata(模型验证)——DataAnnotations 解析
爱做一个新的项目,在该项目中的 WebAPI 中对数据的验证用到了 ModelValidata, 以前也没有用到过,也不是很熟悉,在查看了一些资料和代码后稍有了解,这里记录下来. 这里主要介绍的是 S ...
- ASP.NET Core 2.2 WebApi 系列【八】统一返回格式(返回值、模型验证、异常)
现阶段,基本上都是前后端分离项目,这样一来,就需要前后端配合,没有统一返回格式,那么对接起来会很麻烦,浪费时间.我们需要把所有接口及异常错误信息都返回一定的Json格式,有利于前端处理,从而提高了工作 ...
随机推荐
- ABP入门系列(2)——通过模板创建MAP版本项目
一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打 ...
- nodejs进阶(1)—输出hello world
下面将带领大家一步步学习nodejs,知道怎么使用nodejs搭建服务器,响应get/post请求,连接数据库等. 搭建服务器页面输出hello world var http = require ...
- Vue-Router 页面正在加载特效
Vue-Router 页面正在加载特效 如果你在使用 Vue.js 和 Vue-Router 开发单页面应用.因为每个页面都是一个 Vue 组件,你需要从服务器端请求数据,然后再让 Vue 引擎来渲染 ...
- Android数据存储之Android 6.0运行时权限下文件存储的思考
前言: 在我们做App开发的过程中基本上都会用到文件存储,所以文件存储对于我们来说是相当熟悉了,不过自从Android 6.0发布之后,基于运行时权限机制访问外置sdcard是需要动态申请权限,所以以 ...
- javascript中的操作符详解1
好久没有写点什么了,根据博主的技术,仍然写一点javascript新手入门文章,接下来我们一起来探讨javascript的操作符. 一.前言 javascript中有许多操作符,但是许多初学者并不理解 ...
- 编写高质量代码:改善Java程序的151个建议(第6章:枚举和注解___建议88~92)
建议88:用枚举实现工厂方法模式更简洁 工厂方法模式(Factory Method Pattern)是" 创建对象的接口,让子类决定实例化哪一个类,并使一个类的实例化延迟到其它子类" ...
- 体验报告:微信小程序在安卓机和苹果机上的区别
很多人可能会问:微信小程序和在微信里面浏览一个网页有什么区别? 首先,小程序的运行是全屏的,界面跟进入了一个APP很像,更为沉浸跟在微信里面访问h5不一样:其次,它的浏览体验更为稳定. 不过,这还不够 ...
- Atitit.cto 与技术总监的区别
Atitit.cto 与技术总监的区别 1. 核心区别1 2. Cto主要职责1 3. 如何提升到cto1 4. CTO五种基本的必备素质:2 5. 2 1. 核心区别 技术总监(Chief Tech ...
- PowerShell 数组以及XML操作
PowerShell基础 PowerShell数组操作 将字符串拆分成数据的操作 cls #原始字符串 $str = "abc,def,ghi,mon" #数据定义 #$StrAr ...
- 高级渲染技巧和代码示例 GPU Pro 7
下载代码示例 移动设备正呈现着像素越来越高,屏幕尺寸越来越小的发展趋势. 由于像素着色的能耗非常大,因此 DPI 的增加以及移动设备固有的功耗受限环境为降低像素着色成本带来了巨大的压力. MSAA 有 ...