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格式,有利于前端处理,从而提高了工作 ...
随机推荐
- SSH实战 · 唯唯乐购项目(上)
前台需求分析 一:用户模块 注册 前台JS校验 使用AJAX完成对用户名(邮箱)的异步校验 后台Struts2校验 验证码 发送激活邮件 将用户信息存入到数据库 激活 点击激活邮件中的链接完成激活 根 ...
- java EE设计模式简介
1.何为设计模式 设计模式提供了对常见应用设计问题的解决方案.在面向对象的编程中,设计模式通常在解决与对象创建和交互相关的问题,而非整体软件架构所面对的大规模问题,它们以样板代码的形式提供了通用的解决 ...
- Content Security Policy 入门教程
阮一峰文章:Content Security Policy 入门教程
- InnoDB关键特性学习笔记
插入缓存 Insert Buffer Insert Buffer是InnoDB存储引擎关键特性中最令人激动与兴奋的一个功能.不过这个名字可能会让人认为插入缓冲是缓冲池中的一个组成部分.其实不然,Inn ...
- gulp初学
原文地址:gulp初学 至于gulp与grunt的区别,用过的人都略知一二,总的来说就是2点: 1.gulp的gulpfile.js 配置简单而且更容易阅读和维护.之所以如此,是因为它们的工作方式不 ...
- 基于Composer Player 模型加载和相关属性设置
主要是基于达索软件Composer Player.的基础上做些二次开发. public class ComposerToolBarSetting { public bool AntiAliasingO ...
- WebStorm 2016 最新版激活(activation code方式)
WebStorm 2016 最新版激活(activation code方式) WebStorm activation code WebStorm 最新版本激活方式: 今天下载最新版本的WebStorm ...
- linux的top命令参数详解
简介 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按 ...
- 开始mono开发
使用mono框架开发android程序,第一步当然是构建开发环境,严格意义上说是使用 mono for android开发android程序. 参考Mono for Android安装配置破解 mo ...
- 扑面而来的碎片--图片3D炸裂效果初体验
之前逛园子的时候看到 ChokCoco 的爆炸效果作品:[BOOM]一款有趣的Javascript动画效果 (大神英文有没有拼错呀←.←),觉得蛮有意思的,效果如下: 不过觉得这个爆炸效果还是偏软了一 ...