ASP.NET Web API 'de model doğrulamasıModel Validation in ASP.NET Web API

, Mike te sonby Mike Wasson

Bu makalede, modellerinize not ekleme, veri doğrulama için ek açıklamaları kullanma ve Web API 'nizin doğrulama hatalarını işleme işlemlerinin nasıl yapılacağı gösterilir.This article shows how to annotate your models, use the annotations for data validation, and handle validation errors in your web API. Bir istemci Web API 'nize veri gönderdiğinde, genellikle herhangi bir işlem yapmadan önce verileri doğrulamak istersiniz.When a client sends data to your web API, often you want to validate the data before doing any processing.

Veri AçıklamalarıData Annotations

ASP.NET Web API 'sinde, modelinizdeki özelliklerin doğrulama kurallarını ayarlamak için System. ComponentModel. Dataaçıklamalarda ad alanındaki öznitelikleri kullanabilirsiniz.In ASP.NET Web API, you can use attributes from the System.ComponentModel.DataAnnotations namespace to set validation rules for properties on your model. Aşağıdaki modeli göz önünde bulundurun:Consider the following model:

using System.ComponentModel.DataAnnotations;

namespace MyApi.Models
{
    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 'de model doğrulaması kullandıysanız, bu tanıdık gelmelidir.If you have used model validation in ASP.NET MVC, this should look familiar. Gerekli öznitelik Name özelliğinin null olmaması gerektiğini belirtir.The Required attribute says that the Name property must not be null. Range özniteliği Weight sıfır ile 999 arasında olması gerektiğini belirtir.The Range attribute says that Weight must be between zero and 999.

Bir istemcinin aşağıdaki JSON gösterimiyle bir POST isteği gönderdiğini varsayalım:Suppose that a client sends a POST request with the following JSON representation:

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

İstemcinin gerekli olarak işaretlenen Name özelliğini içermediğini görebilirsiniz.You can see that the client did not include the Name property, which is marked as required. Web API 'si, JSON 'ı bir Product örneğine dönüştürdüğünde, doğrulama özniteliklerine karşı Product doğrular.When Web API converts the JSON into a Product instance, it validates the Product against the validation attributes. Denetleyici eyleinizde, modelin geçerli olup olmadığını kontrol edebilirsiniz:In your controller action, you can check whether the model is valid:

using MyApi.Models;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace MyApi.Controllers
{
    public class ProductsController : ApiController
    {
        public HttpResponseMessage Post(Product product)
        {
            if (ModelState.IsValid)
            {
                // Do something with the product (not shown).

                return new HttpResponseMessage(HttpStatusCode.OK);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }
        }
    }
}

Model doğrulama, istemci verilerinin güvenli olduğunu garanti etmez.Model validation does not guarantee that client data is safe. Uygulamanın diğer katmanlarında ek doğrulama gerekebilir.Additional validation might be needed in other layers of the application. (Örneğin, veri katmanı yabancı anahtar kısıtlamalarını uygulayabilir.) Web API 'sini Entity Framework kullanma öğreticisinde bu sorunlardan bazıları incelenmektedir.(For example, the data layer might enforce foreign key constraints.) The tutorial Using Web API with Entity Framework explores some of these issues.

"In-Posting" : altında, istemci bazı özellikleri bıraktığında gerçekleşir."Under-Posting": Under-posting happens when the client leaves out some properties. Örneğin, istemcinin aşağıdakileri göndereceğini varsayalım:For example, suppose the client sends the following:

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

Burada istemci, Price veya Weightiçin değerler belirtmedi.Here, the client did not specify values for Price or Weight. JSON biçimlendiricisi eksik özelliklere sıfır varsayılan değeri atar.The JSON formatter assigns a default value of zero to the missing properties.

Sıfır değeri bu özellikler için geçerli bir değer olduğundan model durumu geçerli.The model state is valid, because zero is a valid value for these properties. Bunun bir sorun olup olmadığı, senaryonuza bağlıdır.Whether this is a problem depends on your scenario. Örneğin, bir güncelleştirme işleminde, "sıfır" ve "ayarlanmadı" arasında ayrım yapmak isteyebilirsiniz.For example, in an update operation, you might want to distinguish between "zero" and "not set." İstemcileri bir değer ayarlamaya zorlamak için özelliği null yapılabilir yapın ve gerekli özniteliği ayarlayın:To force clients to set a value, make the property nullable and set the Required attribute:

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

"Aşırı gönderme" : bir istemci, beklediğinizden daha fazla veri gönderebilir."Over-Posting": A client can also send more data than you expected. Örneğin:For example:

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

Burada JSON, Product modelinde mevcut olmayan bir Özellik ("Color") içerir.Here, the JSON includes a property ("Color") that does not exist in the Product model. Bu durumda, JSON biçimlendiricisi yalnızca bu değeri yoksayar.In this case, the JSON formatter simply ignores this value. (XML biçimlendiricisi aynı şekilde yapılır.) Daha fazla bilgi için, modelinizde salt okunurdur.(The XML formatter does the same.) Over-posting causes problems if your model has properties that you intended to be read-only. Örneğin:For example:

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

Kullanıcıların IsAdmin özelliğini güncelleştirmesini ve kendilerini yöneticilere yükseltmenizi istemezsiniz!You don't want users to update the IsAdmin property and elevate themselves to administrators! En güvenli strateji, istemcinin gönderilmesine izin verilen şekilde tam olarak eşleşen bir model sınıfı kullanmaktır:The safest strategy is to use a model class that exactly matches what the client is allowed to send:

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

Note

Atacan Solson 'un blog gönderisine "giriş doğrulaması ve ASP.NET MVC 'de model doğrulama",-Posting ve over-Posting konusunda iyi bir tartışmaya sahiptir.Brad Wilson's blog post "Input Validation vs. Model Validation in ASP.NET MVC" has a good discussion of under-posting and over-posting. Post, ASP.NET MVC 2 ile ilgili olsa da, sorunlar hala Web API 'SI ile ilgilidir.Although the post is about ASP.NET MVC 2, the issues are still relevant to Web API.

Doğrulama hatalarını işlemeHandling Validation Errors

Doğrulama başarısız olduğunda Web API 'SI istemciye otomatik olarak bir hata döndürmez.Web API does not automatically return an error to the client when validation fails. Bu, model durumunu denetlemek ve uygun şekilde yanıt vermek için denetleyici eylemine sahiptir.It is up to the controller action to check the model state and respond appropriately.

Ayrıca, denetleyici eylemi çağrılmadan önce model durumunu denetlemek için bir eylem filtresi de oluşturabilirsiniz.You can also create an action filter to check the model state before the controller action is invoked. Aşağıdaki kodda bir örnek gösterilir: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;

namespace MyApi.Filters
{
    public class ValidateModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (actionContext.ModelState.IsValid == false)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(
                    HttpStatusCode.BadRequest, actionContext.ModelState);
            }
        }
    }
}

Model doğrulaması başarısız olursa, bu filtre doğrulama hatalarını içeren bir HTTP yanıtı döndürür.If model validation fails, this filter returns an HTTP response that contains the validation errors. Bu durumda, denetleyici eylemi çağrılmaz.In that case, the controller action is not invoked.

HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Date: Tue, 16 Jul 2013 21:02:29 GMT
Content-Length: 331

{
  "Message": "The request is invalid.",
  "ModelState": {
    "product": [
      "Required property 'Name' not found in JSON. Path '', line 1, position 17."
    ],
    "product.Name": [
      "The Name field is required."
    ],
    "product.Weight": [
      "The field Weight must be between 0 and 999."
    ]
  }
}

Bu filtreyi tüm Web API denetleyicilerine uygulamak için, yapılandırma sırasında HttpConfiguration. Filters koleksiyonuna filtrenin bir örneğini ekleyin:To apply this filter to all Web API controllers, add an instance of the filter to the HttpConfiguration.Filters collection during configuration:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Filters.Add(new ValidateModelAttribute());

        // ...
    }
}

Farklı bir seçenek, filtreyi ayrı denetleyicilerde veya denetleyici eylemlerinde bir öznitelik olarak ayarlamanıza olanak sağlar:Another option is to set the filter as an attribute on individual controllers or controller actions:

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