在绑定完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)

转载于:https://www.cnblogs.com/gangtianci/p/4951351.html

ASP.NET WebAPI 11 参数验证相关推荐

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

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

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

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

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

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

  4. ASP.NET WEBAPI实现微信接入验证

    本主题所有内容以软认知服务为技术基础 关于微软人脸识别,请参阅 本节内容请先参阅微软认知服务人脸API接口列表 ##ASP.NET WEBAPI实现微信接入验证 首先你需要一个微信公众号,很重要的是你 ...

  5. Winform宿主Asp.Net WebApi中Owin 自定义Token请求参数

    本文介绍的是Winform宿主Asp.net WebAPI的过程,利用了Microsoft.AspNet.WebApi.OwinSelfHost. Asp.NET WebAPI中的授权验证有很多: 例 ...

  6. dotNET Core WebAPI 统一处理(返回值、参数验证、异常)

    现在 Web 开发比较流行前后端分离 现在 Web 开发比较流行前后端分离,我们的产品也是一样,前端使用Vue,后端使用 dotNet Core WebAPI ,在写 API 的过程中有很多地方需要统 ...

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

    默认绑定方式 WebAPI把参数分成了简单类型和复杂类型: 简单类型主要包括CLR的primitive types,(int.double.bool等),系统内置的几个strcut类型(TimeSpa ...

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

    一.前言 半年前左右折腾了一个前后端分离的架子,这几天才想起来翻出来分享给大家.关于前后端分离这个话题大家也谈了很久了,希望我这个实践能对大家有点点帮助,演示和源码都贴在后面. 二.技术架构 这两年a ...

  9. 后台参数验证的几种方式

    前言 参数验证是一个常见的问题,无论是前端还是后台,都需对用户输入进行验证,以此来保证系统数据的正确性.对于web来说,有些人可能理所当然的想在前端验证就行了,但这样是非常错误的做法,前端代码对于用户 ...

最新文章

  1. variant 字符串数组_VB数组部分核心知识总结
  2. JavaScript (二)
  3. Spring Security 入门(五):在 Spring-Boot中的应用
  4. 饿了么高稳定、高性能、高可用、高容错API架构实践!
  5. python 链表 【测试题】
  6. c 语言str.size,C/C++ strlen(str)和str.length()和str.size()的区别
  7. 日常((⊙_⊙)…)
  8. 【kudu】未解决 Flink 读取 kudu KuduReaderIterator not found it may have expired
  9. [转]awsome-java
  10. GT_Trace的使用
  11. iOS自带的GPS 定位
  12. daemontools的安装、简介
  13. Leo:一个outlining editor
  14. BP网络异或问题C语言实现,bp网络实现xor异或的C语言实现202102
  15. 零基础如何快速学习Java?Java基础入门秘诀
  16. codeforces CF1736B Playing with GCD
  17. Java学习笔记(三十五)
  18. 婚恋社交项目,寻找创业合伙人,坐标上海
  19. 【Leetcode 3】无重复字符的最长子串
  20. 大麦回忆录-maizuo开发

热门文章

  1. 水题/poj 1852 Ants
  2. 服务器可以响应字符类型的数据吗,HTTP - Response
  3. hashids php 如何使用,Hashids使用
  4. oracle 开始一个事务,oracle的启动与关闭原理-事务commit或者rollback
  5. stc15w404as引脚图_STC15F2K6S2与stc15w404AS的spi通讯
  6. paoding java_中文分词器-PaodingAnalyzer
  7. asp.net mysql 创建变_[ASP.net教程]EF Core使用CodeFirst在MySql中创建新数据库以及已有的Mysql数据库如何使用DB First生成域模型...
  8. c语言中比较两个数组函数,输入两个数组,调用large函数比较,计数,输出统计结果...
  9. MySQL面试题 | 附答案解析(十一)
  10. 2020年全球十大突破性技术公布:数字货币等在列