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两个属性,这两个属性分别表示反射使用到的类与方法名.

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

  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)

时间: 2024-10-06 01:27:51

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

ASP.NET WebAPI 05 参数绑定

ParameterBindingAttribute 在上一篇中重点讲了ModelBinderAttribute的使用场景.这一篇详细的讲一下ModelBinder背后的参数绑定原理. ModelBinderAttribute继承自ParameterBindingAttribute,从命名上就是可以看出ParameterBindingAttribute是对Action参数进行绑定的一种特性.除了ModelBinderAttribute之外,WebAPI还另外定义了ValueProviderAttr

asp.net webapi 自定义身份验证

/// <summary> /// 验证 /// </summary> /// Account API账号 /// TimeStamp 请求时间 /// Sign 所有请求参数 加密 public class AuthFilterOutside : AuthorizeAttribute { //重写基类的验证方式,加入我们自定义的Ticket验证 public override void OnAuthorization(System.Web.Http.Controllers.Htt

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

首先,请允许我说一句:shit! 因为这个问题不难,但是网上有关 ASP.NET WEBAPI的资料太少.都是PHP等等的. 我也是在看了某位大神的博客后有启发,一点点研究出来的. 来看正题! 1.微信公众平台的接入方法,无非4个参数(signature, timestamp, nonce, echostr)加1个Token(两边对应) 2.Token, timestamp, nonce字典排序后,按照字符串“SHA1”加密.得出一串字符串 tmpStr(转化为小写) 3.然后比对 tmpStr

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

一.Forms认证 1.在webapi项目中启用Forms认证 Why:为什么要在WebAPI中使用Forms认证?因为其它项目使用的是Forms认证. What:什么是Forms认证?它在WebAPI中就是一个MessageHandle,具体请查找关键字“ASP.NET Forms” How:如何启动Forms认证? 最简单的是通过配置启动Forms认证: 1 <system.web> 2 <authentication mode="Forms"> 3 <

使用ASP.Net WebAPI构建REST服务(四)——参数绑定

默认绑定方式 WebAPI把参数分成了简单类型和复杂类型: 简单类型主要包括CLR的primitive types,(int.double.bool等),系统内置的几个strcut类型(TimeSpan.Guid等)以及string.对于简单类型的参数,默认从URI中获取. 复杂类型的数据也可以直接作为参数传入进来,系统使用media-type formatter进行解析后传给服务函数.对于复杂类型,默认从正文中获取, 例如,对于如下函数 HttpResponseMessage Put(int

Asp.Net WebApi 集成OWIN架构后,出现 “没有 OWIN 身份验证管理器与此请求相关联” 的解决办法

在Asp.Net WebApi 项目中开启OWIN模块之后,如果没有在OWIN的Startup类中配置认证方式,调用WebApi的相关Controller和Action就会出现如下异常: 出现错误. 没有 OWIN 身份验证管理器与此请求相关联. ExceptionType:System.InvalidOperationException StackTrace: 在 System.Web.Http.Owin.PassiveAuthenticationMessageHandler.Suppress

分享一个前后端分离方案源码-前端angularjs+requirejs+dhtmlx 后端asp.net webapi

一.前言 半年前左右折腾了一个前后端分离的架子,这几天才想起来翻出来分享给大家.关于前后端分离这个话题大家也谈了很久了,希望我这个实践能对大家有点点帮助,演示和源码都贴在后面. 二.技术架构 这两年angularjs和reactjs算是比较火的项目了,而我选择angularjs并不是因为它火,而是因它的模块化.双向数据绑定.注入.指令等都是非常适合架构较复杂的前端应用,而且文档是相当的全,碰到问题基本上可以在网上都找到答案.所以前端基本思路就以angularjs为主.代码模块化,通过requir

Asp.Net WebApi Post请求整理(一)

Asp.Net WebApi+JQuery Ajax的Get请求整理 一.总结 1.WebApi 默认支持Post提交处理,返回的结果为json对象,前台不需要手动反序列化处理.2.WebApi 接收Post提交参数需要指定([FromBody] string name)3.WebApi 中如果只接收一个基础类型参数,不能指定key的名称4.WebApi Post请求Action只能接收一个参数,也就是说一个Action中[FromBody]仅可指定一次5.WebApi Post请求处理多个参数

ASP.NET MVC的客户端验证:jQuery验证在Model验证中的实现

原文:ASP.NET MVC的客户端验证:jQuery验证在Model验证中的实现 在简单了解了Unobtrusive JavaScript形式的验证在jQuery中的编程方式之后,我们来介绍ASP.NET MVC是如何利用它实现客户端验证的.服务端验证最终实现在相应的ModelValidator中,而最终的验证规则定义在相应的ValidationAttribute中:而客户端验证规则通过HtmlHelper<TModel>相应的扩展方法(比如TextBoxFor.EditorFor和Edid