【ASP.NET Web API教程】6.4 模型验证

时间:2023-01-11 13:57:00

本文是Web API系列教程的第6.4小节

6.4 Model Validation
6.4 模型验证

摘自:http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api

By Mike Wasson|July 20, 2012
作者:Mike Wasson | 2012-6-20

When a client sends data to your web API, often you want to validate the data before doing any processing.
当客户端发送数据给你的Web API时,你通常希望在做其它处理之前先对数据进行验证。

6.4.1 Data Annotations
6.4.1 数据注解

In ASP.NET Web API, you can use attributes from the System.ComponentModel.DataAnnotations namespace to set validation rules for properties on your model. Consider the following model:
在ASP.NET Web API中,你可以使用System.ComponentModel.DataAnnotations命名空间的注解属性来设置模型属性的验证规则。考虑以下模型:

public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public decimal Price { get; set; }
[Range(0,999)]
public double Weight { get; set; }
}

If you have used model validation in ASP.NET MVC, this should look familiar. The Required attribute says that the Name property must not be null. The Range attribute says that Weight must be between zero and 999.
如果你曾在ASP.NET MVC中使用过模型验证,这看上去是类似的。Required注解属性说明Name属性必须不为空。Range注解属性说明Weight必须在0-999之间。

Suppose that a client sends a POST request with the following JSON representation:
假设客户端发送了一个带有下列JSON表示的POST请求:

{ "Id":4, "Price":2.99, "Weight":5 }

You can see that the client did not include the Name property, which is marked as required. When Web API converts the JSON into a Product instance, it validates the Product against the validation attributes. In your controller action, you can check whether the model is valid:
你可以看出,客户端并未包含被标记成required的Name属性。当Web API将该JSON转换成Product实例时,它会根据这些验证注解属性对Product进行验证。在控制器动作中,你可以检查该模型是否有效:

public class ProductsController : ApiController
{
public HttpResponseMessage Post(Product product)
{
if (ModelState.IsValid)
{
// Do something with the product (not shown).
// 用product做一些事(未表示出来)
return new HttpResponseMessage(HttpStatusCode.OK);
}
else
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
}

Model validation does not guarantee that client data is safe. Additional validation might be needed in other layers of the application. (For example, the data layer might enforce foreign key constraints.) The tutorial Using Web API with Entity Framework explores some of these issues.
模型验证并不保证客户端数据是安全的。在应用程序的其它层面可能会需要附加验证(例如,数据层可能会强制外键约束)。“Using Web API with Entity Framework(与Entity Framework一起使用Web API)(本系列教程的第2章)”教程考察一些此类问题。

"Under-Posting": Under-posting happens when the client leaves out some properties. For example, suppose the client sends the following:
Under-Posting(递交不足)”:当客户端遗漏了某些属性时,便会发生“Under-posting”。例如,假设客户端发送如下:

{"Id":4, "Name":"Gizmo"}

Here, the client did not specify values for Price or Weight. The JSON formatter assigns a default value of zero to the missing properties.
此处,客户端并未指定Price或Weight的值。JSON格式化器会将默认值(这里是零)赋给这些缺失的属性。

【ASP.NET Web API教程】6.4 模型验证

图6.4-1

The model state is valid, because zero is a valid value for these properties. Whether this is a problem depends on your scenario. For example, in an update operation, you might want to distinguish between "zero" and "not set." To force clients to set a value, make the property nullable and set the Required attribute:
此时模型的状态是有效的,因为零是这些属性的有效值。这是否是一个问题取决于你所处的场景。例如,在一个更新操作中,你可能希望区分出“零”与“未设置”。为了强迫客户端要设置一个值,将该属性构造成nullable(可空的),并设置Required注解属性:

[Required]
public decimal? Price { get; set; }

"Over-Posting": A client can also send more data than you expected. For example:
Over-Posting(过份递交)”:客户端也可能发送比期望还多的数据。例如:

{"Id":4, "Name":"Gizmo", "Color":"Blue"}

Here, the JSON includes a property ("Color") that does not exist in the Product model. In this case, the JSON formatter simply ignores this value. (The XML formatter does the same.) Over-posting causes problems if your model has properties that you intended to be read-only. For example:
此处,JSON包含了Product模型中存在的属性(“Color”)。在这种情况下,JSON格式化器会简单地忽略该值(XML格式化器却不同)。若你的模型具有只读属性,Over-posting会产生问题。例如:

public class UserProfile
{
public string Name { get; set; }
public Uri Blog { get; set; }
public bool IsAdmin { get; set; } // uh-oh!(啊哦!)
}

You don't want users to update the IsAdmin property and elevate themselves to administrators! The safest strategy is to use a model class that exactly matches what the client is allowed to send:
如果你不想让用户对IsAdmin属性进行更新,并将其提升给管理员。最安全的策略是使用一个与允许客户端发送严格匹配的模型类:

public class UserProfileDTO
{
public string Name { get; set; }
public Uri Blog { get; set; }
// Leave out "IsAdmin"
// 略去了"IsAdmin"
}

Brad Wilson's blog post "Input Validation vs. Model Validation in ASP.NET MVC" has a good discussion of under-posting and over-posting. Although the post is about ASP.NET MVC 2, the issues are still relevant to Web API.
Brad Wilson的博客文档“Input Validation vs. Model Validation in ASP.NET MVC(ASP.NET MVC中的输入验证与模型验证)”对under-posting和over-posting有很好的讨论。虽然这篇博文是关于ASP.NET MVC 2的,但这种问题仍然关系到Web API。

6.4.2 Handling Validation Errors
6.4.2 处理验证错误

Web API does not automatically return an error to the client when validation fails. It is up to the controller action to check the model state and respond appropriately.
当验证失败时,Web API并不会自动地将错误返回给客户端。这取决于控制器动作对模型状态及响应进行适当的检查。

You can also create an action filter to check the model state before the controller action is invoked. The following code shows an example:
你也可以创建一个动作过滤器,以便在控制器动作被调用之前,检查模型的状态。以下代码演示了一个例子:

using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Web.Http.ModelBinding;
public class ModelValidationFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid == false)
{
// Return the validation errors in the response body.
// 在响应体中返回验证错误
var errors = new Dictionary<string, IEnumerable<string>>();
foreach (KeyValuePair<string, ModelState> keyValue in actionContext.ModelState)
{
errors[keyValue.Key] = keyValue.Value.Errors.Select(e => e.ErrorMessage);
}
actionContext.Response =
actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, errors);
}
}
}

If model validation fails, this filter returns an HTTP response that contains the validation errors. In that case, the controller action is not invoked.
如果模型验证失败,此过滤器会返回一个含有验证错误的HTTP响应。在此情况下,不会调用控制器动作。

HTTP/1.1 400 Bad Request
Server: ASP.NET Development Server/10.0.0.0
Date: Fri, 20 Jul 2012 21:42:18 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 239
Connection: Close
{
"product": [
"Required property 'Name' not found in JSON. Line 1, position 18."
],
"product.Name": [
"The Name field is required."
],
"product.Weight": [
"The field Weight must be between 0 and 999."
]
}

If you are using the latest Web API source on CodePlex, you can use the HttpError class to return validation errors to the client. The HttpError class is not available in the RC release.
如果你正在使用CodePlex上最新版的Web API,可以使用HttpError类将验证错误返回给客户端。HttpError类在RC版(指Web API的预览版)中无效。

You can apply this filter globally to all Web API controllers. In the Application_Start method, add the filter to the HttpConfiguration.Filters collection:
你可以将此过滤器全局性地运用于所有Web API控制器。在Application_Start方法中,将此过滤器添加到HttpConfiguration.Filters集合:

protected void Application_Start()
{
// ...
GlobalConfiguration.Configuration.Filters.Add(new ModelValidationFilterAttribute());
}

Alternatively, you can apply it to individual controllers or controller actions, by adding the filter as an attribute:
另一种可选办法是,通过将此过滤器作为注解属性进行添加,你可以将它运用于个别控制器或控制器动作:

public class ProductsController : ApiController
{
[ModelValidationFilter]
public HttpResponseMessage Post(Product product)
{
// ...
}
}

看完此文如果觉得有所收获,请给个推荐
你的推荐是我继续下去的动力,也会让更多人关注并获益,这也是你的贡献。

【ASP.NET Web API教程】6.4 模型验证的更多相关文章

  1. 【ASP&period;NET Web API教程】2&period;3&period;2 创建域模型

    原文:[ASP.NET Web API教程]2.3.2 创建域模型 Part 2: Creating the Domain Models 第2部分:创建域模型 本文引自:http://www.asp. ...

  2. 【ASP&period;NET Web API教程】6 格式化与模型绑定

    原文:[ASP.NET Web API教程]6 格式化与模型绑定 6 Formats and Model Binding 6 格式化与模型绑定 本文引自:http://www.asp.net/web- ...

  3. 【ASP&period;NET Web API教程】3&period;2 通过&period;NET客户端调用Web API(C&num;)

    原文:[ASP.NET Web API教程]3.2 通过.NET客户端调用Web API(C#) 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的 ...

  4. 【ASP&period;NET Web API教程】2&period;4 创建Web API的帮助页面

    原文:[ASP.NET Web API教程]2.4 创建Web API的帮助页面 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. 2.4 ...

  5. 【ASP&period;NET Web API教程】2&period;3&period;7 创建首页

    原文:[ASP.NET Web API教程]2.3.7 创建首页 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 7: Crea ...

  6. 【ASP&period;NET Web API教程】2&period;3&period;6 创建产品和订单控制器

    原文:[ASP.NET Web API教程]2.3.6 创建产品和订单控制器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 6 ...

  7. 【ASP&period;NET Web API教程】2&period;3&period;5 用Knockout&period;js创建动态UI

    原文:[ASP.NET Web API教程]2.3.5 用Knockout.js创建动态UI 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容 ...

  8. 【ASP&period;NET Web API教程】2&period;3&period;4 创建Admin视图

    原文:[ASP.NET Web API教程]2.3.4 创建Admin视图 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 4: ...

  9. 【ASP&period;NET Web API教程】2&period;3&period;3 创建Admin控制器

    原文:[ASP.NET Web API教程]2.3.3 创建Admin控制器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 3 ...

  10. 【ASP&period;NET Web API教程】2&period;3 与实体框架一起使用Web API

    原文:[ASP.NET Web API教程]2.3 与实体框架一起使用Web API 2.3 Using Web API with Entity Framework 2.3 与实体框架一起使用Web ...

随机推荐

  1. Xamarin对Visual Studio用户免费 Xamarin SDK将开源

    在 Build 2016开发者大会上,微软宣布它上个月收购的C#和.NET移动开发工具Xamarin对所有Visual Studio用户免费.所有Visual Studio版本涵盖了从免费的社区版到企 ...

  2. android应用内存占用测试(每隔一秒打印procrank的信息)

    1.内存占用 对于智能手机而言,内存大小是固定的:因此,如果单个app的内存占用越小,手机上可以安装运行的app就越多:或者说app的内存占用越小,在手机上运行就会越流畅.所以说,内存占用的大小,也是 ...

  3. 第3章 基本概念(第一部分:Js语法)

    本章就JavaScript常用功能而言阐述ECMAScript“伪语言”所描述的概念. 一. 语法 1.大小写规则 js语言本身对大小写不敏感,但是一切变量.函数.操作符都对大小写敏感. 2.注释格式 ...

  4. 趣味算法:字符串反转的N种方法(转)

    老赵在反对北大青鸟的随笔中提到了数组反转.这的确是一道非常基础的算法题,然而也是一道很不平常的算法题(也许所有的算法深究下去都会很不平常).因为我写着写着,就写出来8种方法……现在我们以字符串的反转为 ...

  5. Ajax 结构及使用

    AJAX AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术. AJAX = 异步 JavaSc ...

  6. Git教程之使用GitHub

    我们一直用GitHub作为免费的远程仓库,如果是个人的开源项目,放到GitHub上是完全没有问题的.其实GitHub还是一个开源协作社区,通过GitHub,既可以让别人参与你的开源项目,也可以参与别人 ...

  7. 用MVC4练习&comma;后台用aspx,数据库DemoDb《MvcUserDemo》

    将ado.net的cs文件SqlHelper.cs放入解决方案 using System; using System.Collections.Generic; using System.Linq; u ...

  8. canvas自适应圆形时钟绘制

    前面的话 前面介绍过canvas粒子时钟的绘制,本文将详细介绍canvas自适应圆形时钟绘制 效果演示 最终自适应圆形时钟的效果如下所示 功能分析 下面来分析一下该圆形时钟的功能 [1]静态背景 对于 ...

  9. 3Openwrt自定义CGI实现 前后端交互

    https://www.cnblogs.com/163yun/p/9834993.html 安装uhttpd. 在编译openwrt前,输入make memuconfig,查找Network -&gt ...

  10. Win10系统给文件夹添加备注

    在Win10系统中,相信大多用户都没有看到过文件或者是文件夹上有备注信息.下面给大家分享下在Win10系统中给文件夹或文件添加备注的方法.在添加备注之前,首先我们要在需要显示备注的文件夹中显示&quo ...