在绑定完Action的所有参数后,WebAPI并不会马上执行该方法,而要对参数进行验证,以保证输入的合法性.

ModelState

在ApiController中一个ModelState属性用来获取参数验证结果.

public abstract class ApiController : IHttpController, IDisposable

 {

public ModelStateDictionary ModelState { get; } 

 }

ApiContext的ModelState属性实际是对每个Action参数验证的结果集合.

public class ModelStateDictionary : IDictionary<string, ModelState>, ICollection<KeyValuePair<string, ModelState>>, IEnumerable<KeyValuePair<string, ModelState>>, IEnumerable

 { 

public int Count { get; } 

public bool IsReadOnly { get; } 

public bool IsValid { get; } 

public ModelState this[string key] { get; set; } 

public void Add(KeyValuePair<string, ModelState> item); 

public void Add(string key, ModelState value); 

 }
public class ModelState

 { 

public ModelState(); 

public ModelErrorCollection Errors { get; } 

public ValueProviderResult Value { get; set; } 

}
public class ModelError

{

public string ErrorMessage { get; } 

public Exception Exception { get; } 

 }

对于ModelStateDictionary,ModelState,ModelError我们可以理解成Action所有参数(所有参数的属性)的验证结果.单个参数的验证结果.单个参数属性的单个验证结果(一个参数可能有多个难结果).

ModelStateDictionary的IsValid属性表示验证是否通过.另外 Count属性对于不同的参数绑定方式在WebAPI中可能表现不同的结果.这个后面会有具体例子.

ValidationAttribute特性

采用ValidationAttribute特性进行参数验证是WebAPI的默认验证方式.ValidationAttribute位于" System.ComponentModel.DataAnnotations"命名空间下,在这个命名空间下还定义了一些具体的ValidationAttribute,如图:

public abstract class ValidationAttribute : Attribute

 {

public string ErrorMessage { get; set; } 

public string ErrorMessageResourceName { get; set; } 

public Type ErrorMessageResourceType { get; set; } 

public virtual bool RequiresValidationContext { get; } 

public virtual string FormatErrorMessage(string name); 

public ValidationResult GetValidationResult(object value, ValidationContext validationContext); 

public virtual bool IsValid(object value); 

public void Validate(object value, string name); 

public void Validate(object value, ValidationContext validationContext); 

 }

ValidationAttribute的IsValid方法用来返回验证是否通过, FormatErrorMessage方法用来返回错误信息.

下面我就自定义一个ArrayValidatorAttribute,用来进行区间判断,即让开发者自定义一个数组,然后判断值是不是在数组内.

public class ArrayValidationAttribute : ValidationAttribute

 { 

public object[] _list; 

public ArrayValidationAttribute(params object[] list) 

 { 

 _list = list; 

 } 

public object[] List 

 { 

get { return _list; } 

set { _list = value; } 

 } 

public override bool IsValid(object value) 

 { 

return _list.Contains(value); 

 } 

public override string FormatErrorMessage(string name) 

 { 

return string.Format("{0}不在区间内.", name); 

 } 

 }

CustomerValidationAttribute的使用

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = true)] 

public sealed class CustomValidationAttribute : ValidationAttribute

 { 

public CustomValidationAttribute(Type validatorType, string method); 

public string Method { get; } 

public override object TypeId { get; } 

public Type ValidatorType { get; } 

public override string FormatErrorMessage(string name); 

protected override ValidationResult IsValid(object value, ValidationContext validationContext); 

 }

从定义中我们可以看出来CustomerValidationAttribute是不能被继承的,这是说明CustomerValidationAttribute不同于ValidaitionAttribute的使用方式.实际上CustomerValidationAttribute采用的反射的方式去进行验证.它包含了ValidationType,Method两个属性,这两个属性分别表示反射使用到的类与方法名.

对于可以用作验证的方法要满足以下条件:

  1. 方法是公开的,静态的
  2. 方法必须要有一个或者两个参数.
  3. 如果方法只有一个参数,那么这个参数必须是未做ref,out标注的(该参数实际上是要验证的值)
  4. 如果方法有两个参数,那么第一个参数的约束用3,第二个参数必须是ValidationContext类型

Model绑定与反序列化参数结果对比

Model绑定方式保存了所有的验证结果,反序列化方式只保存了验证未通过的结果

如下:

public ModelStateDictionary PostFigureFromUrlForState([ModelBinder]Figure figure) 

 { 

return ModelState; 

 } 

public ModelStateDictionary PostFigureFromBodyForState([FromBody]Figure figure) 

 { 

return ModelState; 

 }

对于Figure,将LastName,FirstName都设置成必须。

public class Figure

 { 

 [Required] 

public string FirstName { get; set; } 

 [Required]

public string LastName { get; set; } 

}

现在我们对两个方法传相同的数据:{FirstName:null,LastName:"Stack"}

url:

/api/Demo/PostFigureFromUrlForState?LastName=Stack

/api/Demo/PostFigureFromBodyForState

实际得到的结果分别如下:

源码

Github: https://github.com/BarlowDu/WebAPI (API_11)

ASP.NET WebAPI 11 参数验证的更多相关文章

  1. Asp.net WebAPI Request参数验证-请不要重复造轮子

    随着web客户端的发展,现在很多公司都有专业的前端开发,做到系统前后端分离.ap.net后端典型的就是采用webapi,但是发现很多时候大家对webapi并不了解,这里我们来说说输入参数的验证.前一段 ...

  2. 自动化CodeReview - ASP.NET Core请求参数验证

    自动化CodeReview系列目录 自动化CodeReview - ASP.NET Core依赖注入 自动化CodeReview - ASP.NET Core请求参数验证 参数验证实现 在做服务端开发 ...

  3. ASP.NET WEBAPI 的身份验证和授权

    定义 身份验证(Authentication):确定用户是谁. 授权(Authorization):确定用户能做什么,不能做什么. 身份验证 WebApi 假定身份验证发生在宿主程序称中.对于 web ...

  4. ASP.NET WebApi实现Token验证

    记录笔记,在博客园中有很多实现Token的方法,这是我看过他们学到的,然后找到适合自己的解决方案,自己无聊总结一下学习经验写下的 WebApi后端接口实现Token验证 Token是在客户端频繁向服务 ...

  5. asp.net webapi 自定义身份验证

    /// <summary> /// 验证 /// </summary> /// Account API账号 /// TimeStamp 请求时间 /// Sign 所有请求参数 ...

  6. ASP.NET WebAPI 05 参数绑定

    ParameterBindingAttribute 在上一篇中重点讲了ModelBinderAttribute的使用场景.这一篇详细的讲一下ModelBinder背后的参数绑定原理. ModelBin ...

  7. nodejs获取ASP.Net WebAPI(IIS Windows验证)

    处理了很多天,终于使用Nodejs可以发出请求至WebAPI,能够正常处理数据了 首先加入npm包 npm install httpntlm 在app.js中加入代码 var httpntlm = r ...

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

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

  9. [原创] ASP.NET WEBAPI 接入微信公众平台 总结,Token验证失败解决办法

    首先,请允许我说一句:shit! 因为这个问题不难,但是网上有关 ASP.NET WEBAPI的资料太少.都是PHP等等的. 我也是在看了某位大神的博客后有启发,一点点研究出来的. 来看正题! 1.微 ...

随机推荐

  1. thinkphp的伪静态化

    1. 设置默认的控制器和模块 // 绑定访问Admin模块 define('BIND_MODULE','Home'); // 绑定访问Index控制器 define('BIND_CONTROLLER' ...

  2. 谈"自驱力"

    最新说明: 1.标题是为了博眼球取的,请不大家不要纠结具体薪资数字,我瞎取的 2.请注意素质,不要满口喷粪,不要搞人身攻击,尊重别人,就是尊重你自己 3.请大家就事论事,不要胡乱臆想,请站在全局的角度 ...

  3. Android开发中内存和UI优化

    1.内存||效率 GC这东西对于开发人员用起来比较爽,但对于技术总监或产品总监来说,他们并不在乎,在乎的是用户运行App的流畅度,待你开发完了,笑眯眯的走过来,让你测试N个适配器,烦都烦死你. 说到这 ...

  4. 用qt代码怎样编写图片保存格式[qt4.6]

    用qt代码怎样编写图片保存格式 qt提供了多个保存图片的接口,比较常用的接口如下 bool QPixmap::save ( const QString & fileName, const ch ...

  5. 如何准备PMP考试?

    东西在精,而不在多.话不多说,干货如下: 1.参加培训,不要持续时间太长,通常情况下3个月时间足够了:许多和我一起参加培训的学员,有时候准备6个月时间,反而没有3个月冲刺的时间考试结果好. 2.培训老 ...

  6. ASP.NET MVC 4 Web编程

    http://spu.jd.com/11309606.html 第1章 入门第2章 控制器第3章 视图第4章 模型第5章 表单和HTML辅助方法第6章 数据注解和验证第7章 成员资格.授权和安全性第8 ...

  7. ruby 中文字符to_json后乱码(unicode)

    今天遇到一个中文to_json问题 text = "第1章 青豆 不要被外表骗了" text.to_json => "\"\\u7b2c1\\u7ae0 ...

  8. 再次讲解js中的回收机制是怎么一回事。

    在前几天的一篇闭包文章中我们简单的介绍了一下闭包,但是并没有深入的讲解,因为闭包涉及的知识点比较多,为了能够更好的理解闭包,今天讲解一下关于js中的回收机制. 在初识闭包一文中我说过js中有回收机制这 ...

  9. ruby -- 问题解决(七)ActionController::InvalidAuthenticityToken解决办法

    学习链接:http://cnkerry.iteye.com/blog/350718 解决方法一: class FooController < ApplicationController prot ...

  10. 比较HTML元素和Native组件的区别

    我们开发web应用,会使用到各种Html基本元素,比较<div>,<span>,<img>等. 当我们在开发React Native时,我们不能使用HTML元素,但 ...