ASP.NET Web API'sinde Özel Durum İşleme

Bu makalede, ASP.NET Web API'sinde hata ve özel durum işleme açıklanmaktadır.

HttpResponseException (HTTP Yanıt Hatası)

Web API denetleyicisi yakalanmamış bir özel durum oluşturursa ne olur? Varsayılan olarak, çoğu özel durum 500, İç Sunucu Hatası durum koduyla bir HTTP yanıtına çevrilir.

HttpResponseException türü özel bir durumdur. Bu özel durum, özel durum oluşturucusunda belirttiğiniz herhangi bir HTTP durum kodunu döndürür. Örneğin, id parametresi geçerli değilse aşağıdaki yöntem 404, Bulunamadı değerini döndürür.

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return item;
}

Yanıt üzerinde daha fazla denetim için, yanıt iletisinin tamamını oluşturabilir ve HttpResponseException'a ekleyebilirsiniz:

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
        {
            Content = new StringContent(string.Format("No product with ID = {0}", id)),
            ReasonPhrase = "Product ID Not Found"
        };
        throw new HttpResponseException(resp);
    }
    return item;
}

Özel Durum Filtreleri

Özel durum filtresi yazarak Web API'lerinin özel durumları işleme biçimini özelleştirebilirsiniz. Bir denetleyici yöntemi HttpResponseException özel durumu olmayan işlenmemiş bir özel durum oluşturduğunda bir özel durum filtresi yürütülür. HttpResponseException türü özel bir durumdur, çünkü özellikle bir HTTP yanıtı döndürmek için tasarlanmıştır.

Özel durum filtreleri System.Web.Http.Filters.IExceptionFilter arabirimini uygular. Özel durum filtresi yazmanın en basit yolu , System.Web.Http.Filters.ExceptionFilterAttribute sınıfından türetmek ve OnException yöntemini geçersiz kılmaktır.

Uyarı

ASP.NET Web API'sindeki özel durum filtreleri, ASP.NET MVC'deki filtrelere benzer. Ancak bunlar ayrı bir ad alanında bildirilir ve ayrı ayrı çalışır. Özellikle, MVC'de kullanılan HandleErrorAttribute sınıfı Web API denetleyicileri tarafından oluşan özel durumları işlemez.

NotImplementedException özel durumlarını 501, Uygulanmadı HTTP durum koduna dönüştüren bir filtre aşağıdadır:

namespace ProductStore.Filters
{
    using System;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http.Filters;

    public class NotImplExceptionFilterAttribute : ExceptionFilterAttribute 
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            if (context.Exception is NotImplementedException)
            {
                context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
            }
        }
    }
}

HttpActionExecutedContext nesnesinin Response özelliği, istemciye gönderilecek HTTP yanıt iletisini içerir.

Özel Durum Filtrelerini Kaydetme

Web API'sinde özel durum filtresi kaydetmenin birkaç yolu vardır:

  • Hareket bazında
  • Denetleyiciye göre
  • Genel

Filtreyi belirli bir eyleme uygulamak için, filtreyi eyleme öznitelik olarak ekleyin:

public class ProductsController : ApiController
{
    [NotImplExceptionFilter]
    public Contact GetContact(int id)
    {
        throw new NotImplementedException("This method is not implemented");
    }
}

Filtreyi bir denetleyicideki tüm eylemlere uygulamak için filtreyi denetleyici sınıfına öznitelik olarak ekleyin:

[NotImplExceptionFilter]
public class ProductsController : ApiController
{
    // ...
}

Filtreyi tüm Web API denetleyicilerine genel olarak uygulamak için , GlobalConfiguration.Configuration.Filters koleksiyonuna filtrenin bir örneğini ekleyin. Bu koleksiyondaki özel durum filtreleri herhangi bir Web API denetleyicisi eylemi için geçerlidir.

GlobalConfiguration.Configuration.Filters.Add(
    new ProductStore.NotImplExceptionFilterAttribute());

Projenizi oluşturmak için "ASP.NET MVC 4 Web Uygulaması" proje şablonunu kullanırsanız, Web API yapılandırma kodunuzu WebApiConfig App_Start klasöründe bulunan sınıfına yerleştirin:

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

        // Other configuration code...
    }
}

HttpError

HttpError nesnesi, yanıt gövdesinde hata bilgilerini döndürmek için tutarlı bir yol sağlar. Aşağıdaki örnekte, yanıt gövdesinde HttpError ile 404 (Bulunamadı) HTTP durum kodunun nasıl döndürüleceği gösterilmektedir.

public HttpResponseMessage GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var message = string.Format("Product with id = {0} not found", id);
        return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
    }
    else
    {
        return Request.CreateResponse(HttpStatusCode.OK, item);
    }
}

CreateErrorResponse , System.Net.Http.HttpRequestMessageExtensions sınıfında tanımlanan bir uzantı yöntemidir. CreateErrorResponse, dahili olarak bir HttpError örneği oluşturur ve ardından HttpError'ı içeren bir HttpResponseMessage oluşturur.

Bu örnekte yöntem başarılı olursa ÜRÜNÜ HTTP yanıtında döndürür. Ancak istenen ürün bulunamazsa, HTTP yanıtı istek gövdesinde bir HttpError içerir. Yanıt aşağıdaki gibi görünebilir:

HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Date: Thu, 09 Aug 2012 23:27:18 GMT
Content-Length: 51

{
  "Message": "Product with id = 12 not found"
}

Bu örnekte HttpError'ın JSON olarak seri hale getirildiğine dikkat edin. HttpError kullanmanın bir avantajı, diğer güçlü türdeki modellerle aynı içerik anlaşması ve serileştirme işleminden geçmesidir.

HttpError ve Model Doğrulaması

Model doğrulaması için, yanıta doğrulama hatalarını eklemek için model durumunu CreateErrorResponse'a geçirebilirsiniz:

public HttpResponseMessage PostProduct(Product item)
{
    if (!ModelState.IsValid)
    {
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
    }

    // Implementation not shown...
}

Bu örnek aşağıdaki yanıtı döndürebilir:

HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Content-Length: 320

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

Model doğrulama hakkında daha fazla bilgi için bkz. ASP.NET Web API'sinde Model Doğrulama.

HttpResponseException ile HttpError Kullanma

Önceki örnekler denetleyici eyleminden bir HttpResponseMessage iletisi döndürür, ancak httperror döndürmek için HttpResponseException da kullanabilirsiniz. Bu, normal başarı durumunda kesin türemiş bir model döndürmenize olanak tanırken, hata varsa HttpError'ı döndürmeye devam etmenizi sağlar:

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var message = string.Format("Product with id = {0} not found", id);
        throw new HttpResponseException(
            Request.CreateErrorResponse(HttpStatusCode.NotFound, message));
    }
    else
    {
        return item;
    }
}