本次要和大家分享的是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 - 模型验证的更多相关文章

  1. ASP.NET Core - 实现自定义WebApi模型验证

    Framework时代 在Framework时代,我们一般进行参数验证的时候,以下代码是非常常见的 [HttpPost] public async Task<JsonResult> Sav ...

  2. 一、WebApi模型验证实践项目使用

    一.启语 前面我们说到,模型验证的原理(包含1.项目创建,2.模型创建,3.走通测试模型验证,4.在过滤器中处理返回json格式(非控制器内))-完全是新手理解使用的,新番理解 通常情况下,对于那些经 ...

  3. 一、WebApi模型验证

    一.新建项目 选择空的项目webapi 查看启动端口 创建控制器 添加方法 public class VerifController : ApiController { public IHttpAct ...

  4. .Net Core WebApi 模型验证无效时报400

    问题 模型验证无效时,没有进入到接口里,而是直接报400 Bad Request,非常不友好. 环境 SDK:.Net Core 2.2.401 开发工具:VS2017 step 1 创建接口 /// ...

  5. 在asp.net WebAPI 中 使用Forms认证和ModelValidata(模型验证)

    一.Forms认证 1.在webapi项目中启用Forms认证 Why:为什么要在WebAPI中使用Forms认证?因为其它项目使用的是Forms认证. What:什么是Forms认证?它在WebAP ...

  6. .Net高级进阶,WebApi和MVC进行模型验证的时候,教你如何自由控制需要进行验证的字段?

    现在,你有一个MVC架构的web项目,你要完成一个注册功能. 前台传了3个值到你的控制器,分别是账号.密码.邮箱. 如图:现在你要在控制器里面判断,账号名称.密码.邮箱不能为空,并且名称和密码不超过1 ...

  7. webapi Model Validation 模型验证

    通常情况下,对于那些经常为别人提供数据接口的开发人员来说,对于调用方传递过来的参数都会有验证处理.例如: if (string.IsNullOrEmpty(entity.Name)) { //当姓名为 ...

  8. WebAPI ModelValidata(模型验证)——DataAnnotations 解析

    爱做一个新的项目,在该项目中的 WebAPI 中对数据的验证用到了 ModelValidata, 以前也没有用到过,也不是很熟悉,在查看了一些资料和代码后稍有了解,这里记录下来. 这里主要介绍的是 S ...

  9. ASP.NET Core 2.2 WebApi 系列【八】统一返回格式(返回值、模型验证、异常)

    现阶段,基本上都是前后端分离项目,这样一来,就需要前后端配合,没有统一返回格式,那么对接起来会很麻烦,浪费时间.我们需要把所有接口及异常错误信息都返回一定的Json格式,有利于前端处理,从而提高了工作 ...

随机推荐

  1. 快速构建H5单页面切换骨架

    在Web App和Hybrid App横行的时代,为了拥有更好的用户体验,单页面应用顺势而生,单页面应用简称`SPA`,即Single Page Application,就是只有一个HTML页面的应用 ...

  2. bootstrap-datetimepicker 进一步跟进~~~开始时间和结束时间的样式显示

    上次简单介绍了一下:05.LoT.UI 前后台通用框架分解系列之——漂亮的时间选择器(http://www.cnblogs.com/dunitian/p/5524019.html) 这次深入再介绍一下 ...

  3. C++ 拷贝构造函数和赋值运算符

    本文主要介绍了拷贝构造函数和赋值运算符的区别,以及在什么时候调用拷贝构造函数.什么情况下调用赋值运算符.最后,简单的分析了下深拷贝和浅拷贝的问题. 拷贝构造函数和赋值运算符 在默认情况下(用户没有定义 ...

  4. spring boot 实战:我们的第一款开源软件

    在信息爆炸时代,如何避免持续性信息过剩,使自己变得专注而不是被纷繁的信息所累?每天会看到各种各样的新闻,各种新潮的技术层出不穷,如何筛选出自己所关心的? 各位看官会想,我们是来看开源软件的,你给我扯什 ...

  5. Python 基础之一变量和赋值

    变量:程序在运行的时候会用到很多临时存储数据,这个时候就用到了变量,临时数据的名字. Python中变量不需要声明,直接可以使用,变量的数据类型由赋值确定. >>> name=&qu ...

  6. PHP设计模式(二)工厂方法模式(Factory Method For PHP)

    简单工厂简述: 简单工厂模式实现了生产产品类的代码跟客户端代码分离,在工厂类中你可以添加需要生成长跑的逻辑代码(new 产品类),但是问题来了,优秀的代码是符合"开闭原则"如果你要 ...

  7. BPM配置故事之案例14-数据字典与数据联动

    小明遇到了点麻烦,他昨天又收到了行政主管发来的邮件,要求把出差申请单改由H3 BPM进行,表单如下 行政主管的出差申请表 小明对表单进行了调整,设计出了一份适合在系统中使用的表单,但在"出差 ...

  8. C语言可以开发哪些项目?

    C语言是我们大多数人的编程入门语言,对其也再熟悉不过了,不过很多初学者在学习的过程中难免会出现迷茫,比如:不知道C语言可以开发哪些项目,可以应用在哪些实际的开发中--,这些迷茫也导致了我们在学习的过程 ...

  9. Windows下MySQL无法启动

    问题描述: 从网上下了5.7 的MySQL,在bin目录下执行 start mysqld ,弹出个cmd窗口一闪就没了,也看不清是什么报错.mysqld --install安装了服务,也启动不了.   ...

  10. js中的null 和undefined

    参考链接:http://blog.csdn.net/qq_26676207/article/details/53100912 http://www.ruanyifeng.com/blog/2014/0 ...