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

, Mike te son

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. Bir istemci Web API 'nize veri gönderdiğinde, genellikle herhangi bir işlem yapmadan önce verileri doğrulamak istersiniz.

Veri Açıklamaları

ASP.NET Web API 'sinde, modelinizdeki özelliklerin doğrulama kurallarını ayarlamak için System. ComponentModel. Dataaçıklamalarda ad alanındaki öznitelikleri kullanabilirsiniz. Aşağıdaki modeli göz önünde bulundurun:

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. Gerekli öznitelik Name özelliğinin null olmaması gerektiğini belirtir. Range özniteliği Weight sıfır ile 999 arasında olması gerektiğini belirtir.

Bir istemcinin aşağıdaki JSON gösterimiyle bir POST isteği gönderdiğini varsayalım:

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

İstemcinin gerekli olarak işaretlenen Name özelliğini içermediğini görebilirsiniz. Web API 'si, JSON 'ı bir Product örneğine dönüştürdüğünde, doğrulama özniteliklerine karşı Product doğrular. Denetleyici eyleinizde, modelin geçerli olup olmadığını kontrol edebilirsiniz:

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. Uygulamanın diğer katmanlarında ek doğrulama gerekebilir. (Örneğin, veri katmanı yabancı anahtar kısıtlamalarını uygulayabilir.) Web API 'sini Entity Framework kullanma öğreticisinde bu sorunlardan bazıları incelenmektedir.

"In-Posting" : altında, istemci bazı özellikleri bıraktığında gerçekleşir. Örneğin, istemcinin aşağıdakileri göndereceğini varsayalım:

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

Burada istemci, Price veya Weightiçin değerler belirtmedi. JSON biçimlendiricisi eksik özelliklere sıfır varsayılan değeri atar.

Sıfır değeri bu özellikler için geçerli bir değer olduğundan model durumu geçerli. Bunun bir sorun olup olmadığı, senaryonuza bağlıdır. Örneğin, bir güncelleştirme işleminde, "sıfır" ve "ayarlanmadı" arasında ayrım yapmak isteyebilirsiniz. İstemcileri bir değer ayarlamaya zorlamak için özelliği null yapılabilir yapın ve gerekli özniteliği ayarlayın:

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

"Aşırı gönderme" : bir istemci, beklediğinizden daha fazla veri gönderebilir. Örneğin:

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

Burada JSON, Product modelinde mevcut olmayan bir Özellik ("Color") içerir. Bu durumda, JSON biçimlendiricisi yalnızca bu değeri yoksayar. (XML biçimlendiricisi aynı şekilde yapılır.) Daha fazla bilgi için, modelinizde salt okunurdur. Örneğin:

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! En güvenli strateji, istemcinin gönderilmesine izin verilen şekilde tam olarak eşleşen bir model sınıfı kullanmaktır:

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. Post, ASP.NET MVC 2 ile ilgili olsa da, sorunlar hala Web API 'SI ile ilgilidir.

Doğrulama hatalarını işleme

Doğrulama başarısız olduğunda Web API 'SI istemciye otomatik olarak bir hata döndürmez. Bu, model durumunu denetlemek ve uygun şekilde yanıt vermek için denetleyici eylemine sahiptir.

Ayrıca, denetleyici eylemi çağrılmadan önce model durumunu denetlemek için bir eylem filtresi de oluşturabilirsiniz. Aşağıdaki kodda bir örnek gösterilir:

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. Bu durumda, denetleyici eylemi çağrılmaz.

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:

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:

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