ASP.NET WebAPI 11 参数验证
在绑定完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两个属性,这两个属性分别表示反射使用到的类与方法名.
对于可以用作验证的方法要满足以下条件:
- 方法是公开的,静态的
- 方法必须要有一个或者两个参数.
- 如果方法只有一个参数,那么这个参数必须是未做ref,out标注的(该参数实际上是要验证的值)
- 如果方法有两个参数,那么第一个参数的约束用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 参数验证的更多相关文章
- Asp.net WebAPI Request参数验证-请不要重复造轮子
随着web客户端的发展,现在很多公司都有专业的前端开发,做到系统前后端分离.ap.net后端典型的就是采用webapi,但是发现很多时候大家对webapi并不了解,这里我们来说说输入参数的验证.前一段 ...
- 自动化CodeReview - ASP.NET Core请求参数验证
自动化CodeReview系列目录 自动化CodeReview - ASP.NET Core依赖注入 自动化CodeReview - ASP.NET Core请求参数验证 参数验证实现 在做服务端开发 ...
- ASP.NET WEBAPI 的身份验证和授权
定义 身份验证(Authentication):确定用户是谁. 授权(Authorization):确定用户能做什么,不能做什么. 身份验证 WebApi 假定身份验证发生在宿主程序称中.对于 web ...
- ASP.NET WebApi实现Token验证
记录笔记,在博客园中有很多实现Token的方法,这是我看过他们学到的,然后找到适合自己的解决方案,自己无聊总结一下学习经验写下的 WebApi后端接口实现Token验证 Token是在客户端频繁向服务 ...
- asp.net webapi 自定义身份验证
/// <summary> /// 验证 /// </summary> /// Account API账号 /// TimeStamp 请求时间 /// Sign 所有请求参数 ...
- ASP.NET WebAPI 05 参数绑定
ParameterBindingAttribute 在上一篇中重点讲了ModelBinderAttribute的使用场景.这一篇详细的讲一下ModelBinder背后的参数绑定原理. ModelBin ...
- nodejs获取ASP.Net WebAPI(IIS Windows验证)
处理了很多天,终于使用Nodejs可以发出请求至WebAPI,能够正常处理数据了 首先加入npm包 npm install httpntlm 在app.js中加入代码 var httpntlm = r ...
- 在asp.net WebAPI 中 使用Forms认证和ModelValidata(模型验证)
一.Forms认证 1.在webapi项目中启用Forms认证 Why:为什么要在WebAPI中使用Forms认证?因为其它项目使用的是Forms认证. What:什么是Forms认证?它在WebAP ...
- [原创] ASP.NET WEBAPI 接入微信公众平台 总结,Token验证失败解决办法
首先,请允许我说一句:shit! 因为这个问题不难,但是网上有关 ASP.NET WEBAPI的资料太少.都是PHP等等的. 我也是在看了某位大神的博客后有启发,一点点研究出来的. 来看正题! 1.微 ...
随机推荐
- jQuery诞生记-原理与机制
一.看似偶然的东西实际是必然会发生的 我大学时候在图书馆翻过一本很破旧的书,讲生物理论的,主要内容就是探讨生命的产生是偶然还是必然.里面很多亚里士多德都看不懂的公式计算什么的,还有模拟原始地球环境出现 ...
- __declspec(dllimport)
我相信写WIN32程序的人,做过DLL,都会很清楚__declspec(dllexport)的作用,它就是为了省掉在DEF文件中手工定义导出哪些函数的一个方法.当然,如果你的DLL里全是C++的类的话 ...
- WPF国际化(多语言)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...
- 基于LoadRunner构建接口测试框架
基于LoadRunner构建接口测试框架 http://www.docin.com/p-775544153.html
- 『WPF』实现拖动文件到窗体(控件)
前言 实现从窗口外部拖文件到窗口内部并自动捕获文件地址. 第一步 开启属性 启用底层Window的AllowDrop属性,添加Drop事件. Drop事件:当你拖动文件到对应控件后,松开触发. 除Dr ...
- jqGrid标题行与第一行之间有很大空白的问题解决。
如题的问题,网上找了很久,都没有解决方案.最后发现,问题不在jqgrid的配置代码,问题在前台HTML代码. <table id="grid" height="30 ...
- Mysql 导入数据,推荐Source命令,太快了
http://jingyan.baidu.com/article/cbf0e500d15c762eab289362.html
- Web services 安全 - HTTP Basic Authentication
根据 RFC2617 的规定,HTTP 有两种标准的认证方式,即,BASIC 和 DIGEST.HTTP Basic Authentication 是指客户端必须使用用户名和密码在一个指定的域 (Re ...
- MyBatis知多少(11)企业数据库
企业数据库比应用程序数据库更大,其外部影响也更大.它们与其他系统之间存在更多的关系,包括依赖关系和被依赖关系.这些关系可能是Web应用程序与报表工具之间的,但也很有可 能是与其他的复杂系统和数据库的接 ...
- Teambition可用性测试记
引言:最开始知道Teambition是几个月前,当时是想找一个团队协作工具.Teambition是候选之一,它的界面设计给我留下了印象.后来得知其背后年轻的创始团队还是让我有些小惊讶的.这次通过朋友介 ...