[水煮 ASP.NET Web API2 方法论](1-6)Model Validation
问题
想要 ASP.NET Web API 执行模型验证,同时可以和 ASP.NET MVC 共享一些验证逻辑。
解决方案
ASP.NET Web API 与 ASP.NET MVC 支持一样的验证机制,都是通过System.ComponentModel.DataAnnoataions 的属性验证。使用框架提供的相关验证属性,已足够来用来验证模型。
想要更细粒度的验证,我们可以选择在我们的模型中实现 IValudateObject(来自于System.ComponentModel.DataAnnotations)。如果所有的属性都验证通过,ASP.NET Web API 将会调用接口的Validate 方法,在这里我们可以进行更进一步的进行实体验证。这是和 MVC 里面的行为一样,并且,我们甚至可以在 Web API 和 MVC 中使用同一个 DTO。
还有另一种方法,就是可以使用一个叫做 FluentValidation(NuGet 中可以下载FluentValidation)的第三方程序库,他可以构建更强大的验证场景。在这样的情况下,我们仍然需在我们的模型中实现 IValidateObject 接口,同时需要依赖于FluentValidation 验证器,而不是内嵌的验证逻辑。
小提示 ASP.NET Web API 的验证行为在跨宿主机上是相同的。
工作原理
为了从 HTTP 请求 Body 中读取的模型并执行验证,ASP.NET Web API 依赖于一个 IBodyModelValidator 的服务。接口的大致描述如清单 1-17 所示,然而,他是一个可替代的服务,正常情况下,默认实现(DefaultBodyModelValidator)足够我们使用,在HttpConfiguration 被设置为自启动。
清单 1-17. IBodyModelValidator 接口
1
2
3
4
5
|
public interface IBodyModelValidator
{
bool Validate( object model, Type type, ModelMetadataProvider metadataProvider,
HttpActionContext actionContext, string keyPrefix);
}
|
有一个叫做FormatrtParameterBinding 的服务,在 HTTP 请求 Body 绑定到 Action 参数的处理请求时,DefaultBodyModelValidator 的 Validate 方法会被调用。对于验证程序,他会递归验证整个对象图谱,验证每一个属性以及嵌套属性。Web API 通过使用DataAnnotationModelValidatorProviderr 来支持声明。如果我们的模型使用WCF 方式的 DataMemberAttribute 声明,那么,我们需要使用框架的 DataMemberValidatorProvider。
最后,我们的模型可以实现IValidatableObject 接口,这个接口只暴露了一个简单的方法如清单1-18所示。如果实现了接口,那就需要我们自己提供额外的验证逻辑。只要所有的属性验证通过,ASP.NET Wwb API 就会调用IValidateableObject接口的 Validate 方法,
清单1-18. IValidateableObject 接口的定义
1
2
3
4
|
public interface IValidateableObject
{
IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
}
|
验证结果是通过 ASP.NET Web API 的 ModelStateDictionary 形式表示,在这里 ModelState 也是可以用的。这个和 ASP.NET MVC 中的概念是完全一样的,但是使用的对象是不同的,因为 Web API 使用自己版本的System.Web.Http.Modelbinding。ModelStateDictionary 暴露了IsValid 属性,这个属性可以用来检查 Action 内Model 验证的状态。
声明的验证机制也很好的整合到了 ASP.NET Web API Help Page,可以提供对 API 语义上的描述。我们将会在7-11 的时候详细讨论他。
小提示 在 API 中最好的做法是使用不同的模型作为 Request 和Response 实体。例如,实体 ID 一般仅仅是 Response 模型需要的,如果 Request 中需要的话,是可以从 URI 中拿到的。
代码
清单 1-19 展示了一个模型有多种验证的情况:
RequiredAttribute,MaxLengthAttribute 和
RangeAttribute。接下来,我们就可以利用 ModelState 来验证 Controller 中的验证状态,同时响应适当的提示信息给调用端。
清单 1-19. 简单的 Web API 模型验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public class Album
{
public int Id { get ; set ; }
[Required(ErrorMessage = "{0} is required" )]
[MaxLength(30)]
public string Artist { get ; set ; }
[Required(ErrorMessage = "{0} is required" )]
[MaxLength(40)]
public string Title { get ; set ; }
[Range(0, 10, ErrorMessage = "{0} in the range of {1}-{2} is required." )]
public int Rating { get ; set ; }
}
public class AlbumController : ApiController
{
public HttpResponseMessage Post(Album album)
{
if (!ModelState.IsValid)
{
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest,
ModelState));
}
//omitted for brevity
}
}
|
负责处理 ModelState 代码的一般验证可以很容易从 Controller 提取到成公共的部分,使其可以被很好的重用,不过这一部分我们将在 5-4 的时候再详细介绍。
现在,我们考虑一下这个场景,如果我们要在模型上增加增加两个额外的属性 Rating 和 Starred,同时扩展模型验证,验证的要求是这两个属性至少有一个是必填的。虽然,在两个属性之间纠缠的验证很难使用声明的方式来表示,但是,不要忘记 IValidateableObject 可以帮我们。我们可以使用接口中的 Validata 的方法去检查整个模型的状态,同时返回相应的 ValidationResult。我们要做的修改如清单 1-20 所示的代码。
清单 1-20. 修改 ASP.NET Web API 依赖于 IValidateableObject 的验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class Album : IValidatableObject
{
public int Id { get ; set ; }
[Required(ErrorMessage = "{0} is required" )]
[MaxLength(30)]
public string Artist { get ; set ; }
[Required(ErrorMessage = "{0} is required" )]
[MaxLength(40)]
public string Title { get ; set ; }
public int ? Rating { get ; set ; }
public bool ? Starred { get ; set ; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!(Rating.HasValue && Rating > 0 && Rating < 10) || (Starred.HasValue && Starred.Value))
{
yield return new ValidationResult( "You must set either the Rating in the 0-9 range orStarred flag." );
}
}
}
|
转载于:https://www.cnblogs.com/shuizhucode/p/6064260.html
[水煮 ASP.NET Web API2 方法论](1-6)Model Validation相关推荐
- [水煮 ASP.NET Web API2 方法论](1-1)在MVC 应用程序中添加 ASP.NET Web API
问题 怎么样将 Asp.Net Web Api 加入到现有的 Asp.Net MVC 项目中 解决方案 在 Visual Studio 2012 中就已经把 Asp.Net Web Api 自动地整合 ...
- [水煮 ASP.NET Web API2 方法论](12-1)创建 OData
问题 怎样用在 Web API 中创建 OData 服务. 解决方案 对于我们来说,在 Web API 中使用 OData最简单的方式就是使用 ASP.NET 模板来创建Odata Controlle ...
- 【ASP.NET Web API2】初识Web API
Web Api 是什么? MSDN:ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动设备)的 HTTP 服务 百度百科:Web API是网络应用程序接口. ...
- ASP NET Web API 2框架揭秘
ASP.NET Web API2框架揭秘(.NET领域再现力作顶级专家精讲微软全新轻量级通信平台) 蒋金楠 著 ISBN 978-7-121-23536-8 2014年7月出版 定价:108.00 ...
- Asp.Net Web API 2第七课——Web API异常处理
Asp.Net Web API 2第七课--Web API异常处理 原文:Asp.Net Web API 2第七课--Web API异常处理 前言 阅读本文之前,您也可以到Asp.Net Web AP ...
- Asp.Net Web API 2第十七课——Creating an OData Endpoint in ASP.NET Web API 2(OData终结点)...
原文:Asp.Net Web API 2第十七课--Creating an OData Endpoint in ASP.NET Web API 2(OData终结点) 前言 很久没更新博客了,加上刚过 ...
- (四)Asp.net web api中的坑-【api的返回值】
(四)Asp.net web api中的坑-[api的返回值] 原文:(四)Asp.net web api中的坑-[api的返回值] void无返回值 IHttpActionResult HttpRe ...
- WCF 和 ASP.NET Web API
地址:https://docs.microsoft.com/zh-cn/dotnet/framework/wcf/wcf-and-aspnet-web-api WCF 是 Microsoft 为生成面 ...
- ASP.NET Web API自身对CORS的支持:从实例开始
在<通过扩展让ASP.NET Web API支持W3C的CORS规范>中我们通过自定义的HttpMessageHandler为ASP.NET Web API赋予了跨域资源共享的能力,具体来 ...
最新文章
- 调用链系列四:调用链上下文传递
- 【bzoj2081】[Poi2010]Beads Hash
- Vim 实用技术,第 3 部分: 定制 Vim
- oracle 体系结构认识,Oracle数据库体系结构简单认识一
- jboss-AS目录结构了解(资料摘取)
- Postfix实现代理Exchange邮件传输方案
- 解决Idea中Cannot resolve plugin org.apache.maven.plugins:maven-clean-plugin:3.1.0配置问题
- AOJ0008 Sum of 4 Integers【暴力】
- fianl属性 java_Java反射如何有效的修改final属性值详解
- ASM的基础使用 Android 自动化埋点方案原理剖析
- MATLAB 数据拟合方法
- Spring Cloud Alibaba Nacos Config - - - >多配置文件/共享配置
- AI-Tesseract4.0-OCR训练相关
- python英语词汇读音_40行Python代码区分英语单词和汉语拼音
- 基于Labview的水位水温控制系统——虚拟仪器实验设计报告
- elasticsearch删除过期数据
- 到底什么是云计算?学云计算能从事哪些职业
- 求导——基本初等函数的导数公式
- 修改服务器2003系统时间,windows2003 时间服务器ntp配置
- Socket.io使用介绍
热门文章
- 远程服务器如何创建分支,git如何远程创建分支
- java关闭websocket_关闭代码1006关闭websocket的原因
- java 头像 微信群_java怎么生成带用户微信头像的图片,并把这张图片发送给用户。...
- 程序设计基础(c语言)复习大纲,《程序设计基础-C》复习大纲.doc
- dev的编辑器不支持getchar吗_“两头婚兴起”:你支持不娶不嫁,孩子随父姓也随母姓吗?...
- android wifi 通讯录,通过wifi和gmail从symbian手机中将名片夹(通讯录)导入到android手机 | 古意人...
- C++11的模板改进
- C语言边角料:结构体中指针类型的成员变量,它的类型重要吗?
- oracle 11g b表空间什么情况下自动增加,Oracle 11g表空间——创建和扩展(永久)表空间...
- 求解出n以内所有能被5整除的正整数的乘积_所有最常见最经典的算法题都在这里了...