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

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 tüm HTTP durum kodlarını 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 ile birlikte 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ştururken ö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.

Not

ASP.NET Web API'sindeki özel durum filtreleri, ASP.NET MVC'dekine 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ı HTTP durum kodu 501'e dönüştüren bir filtre aşağıdadır, Uygulanmadı:

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'si özel durum filtresini kaydetmenin birkaç yolu vardır:

  • Eyleme göre
  • Denetleyiciye göre
  • Genel olarak

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ının içine 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 avantajlarından biri, diğer güçlü türe sahip 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 olarak türü belirlenmiş bir model döndürmenize olanak tanırken, bir 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;
    }
}