前言html
閱讀本文以前,您也能夠到Asp.Net Web API 2 系列導航進行查看 http://www.cnblogs.com/aehyok/p/3446289.htmlweb
本文參考連接文章地址http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-apijson
當客戶端發送數據給你的Web API時,你一般但願在作其它處理以前先對數據進行驗證。api
Data Annotations——數據註解安全
在ASP.NET Web API中,你可使用System.ComponentModel.DataAnnotations命名空間的註解屬性來設置模型屬性的驗證規則。考慮如下模型:app
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; } }
若是你曾在ASP.NET MVC中使用過模型驗證,這看上去是相似的。Required註解屬性說明Name屬性必須不爲空。Range註解屬性說明Weight必須在0-999之間。asp.net
假設客戶端發送了一個帶有下列JSON表示的POST請求:ide
{ "Id":4, "Price":2.99, "Weight":5 }
你能夠看出,客戶端並未包含被標記成required的Name屬性。當Web API將該JSON轉換成Product實例時,它會根據這些驗證註解屬性對Product進行驗證。在控制器動做中,你能夠檢查該模型是否有效:post
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); } } }
模型驗證並不保證客戶端數據是安全的。在應用程序的其它層面可能會須要附加驗證(例如,數據層可能會強制外鍵約束)。ui
{"Id":4, "Name":"Gizmo"}
此處,客戶端並未指定Price或Weight的值。JSON格式化器會將默認值(這裏是零)賦給這些缺失的屬性。
「Under-Posting(遞交不足)」:當客戶端遺漏了某些屬性時,便會發生「Under-posting」。例如,假設客戶端發送以下:
此時模型的狀態是有效的,由於零是這些屬性的有效值。這是不是一個問題取決於你所處的場景。例如,在一個更新操做中,你可能但願區分出「零」與「未設置」。爲了強迫客戶端要設置一個值,將該屬性構形成nullable(可空的),並設置Required註解屬性:
[Required] public decimal? Price { get; set; }
「Over-Posting(過份遞交)」:客戶端也可能發送比指望還多的數據。例如:
{"Id":4, "Name":"Gizmo", "Color":"Blue"}
此處,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!(啊哦!) }
若是你不想讓用戶對IsAdmin屬性進行更新,並將其提高給管理員。最安全的策略是使用一個與容許客戶端發送嚴格匹配的模型類:
public class UserProfileDTO { public string Name { get; set; } public Uri Blog { get; set; } // Leave out "IsAdmin" // 略去了"IsAdmin" }
Handling Validation Errors——處理驗證錯誤
當驗證失敗時,Web API並不會自動地將錯誤返回給客戶端。這取決於控制器動做對模型狀態及響應進行適當的檢查。
你也能夠建立一個動做過濾器,以便在控制器動做被調用以前,檢查模型的狀態。如下代碼演示了一個例子:
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); } } }
若是模型驗證失敗,此過濾器會返回一個含有驗證錯誤的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." ] }
若是你正在使用CodePlex上最新版的Web API,可使用HttpError類將驗證錯誤返回給客戶端。HttpError類在RC版(指Web API的預覽版)中無效。
你能夠將此過濾器全局性地運用於全部Web API控制器。在Application_Start方法中,將此過濾器添加到HttpConfiguration.Filters集合:
protected void Application_Start() { // ... GlobalConfiguration.Configuration.Filters.Add(new ModelValidationFilterAttribute()); }
另外一種可選辦法是,經過將此過濾器做爲註解屬性進行添加,你能夠將它運用於個別控制器或控制器動做:
public class ProductsController : ApiController { [ModelValidationFilter] public HttpResponseMessage Post(Product product) { // ... } }