Neden HttpResponseMessage yerine IHttpActionResult kullanmalıyım?


326

WebApi ile geliştiriyorum ve WebApi2'ye geçtim. Burada Microsoft, bir IHttpActionResultiade işlemi için kullanılması tavsiye edilen yeni bir Arayüz tanıttı HttpResponseMessage. Bu yeni arayüzün avantajları konusunda kafam karıştı. Bu sadece oluşturmak için BÜYÜK daha kolay bir yol sağlamak gibi görünüyor HttpResponseMessage.

Bunun "soyutlama uğruna soyutlama" olduğu iddiasını ortaya koyacağım. Bir şey mi kaçırıyorum? Belki de bir kod satırını kaydetmenin yanı sıra bu yeni arayüzü kullanmaktan elde ettiğim gerçek dünya avantajları nelerdir?

Eski yol (WebApi):

public HttpResponseMessage Delete(int id)
{
    var status = _Repository.DeleteCustomer(id);
    if (status)
    {
        return new HttpResponseMessage(HttpStatusCode.OK);
    }
    else
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
}

Yeni Yol (WebApi2):

public IHttpActionResult Delete(int id)
{
    var status = _Repository.DeleteCustomer(id);
    if (status)
    {
        //return new HttpResponseMessage(HttpStatusCode.OK);
        return Ok();
    }
    else
    {
        //throw new HttpResponseException(HttpStatusCode.NotFound);
        return NotFound();
    }
}

Sadece ilginç bir şey buldum. Bu sonuçların başka biri tarafından doğrulanıp doğrulanamayacağından emin değilim. Ama yaptığım bazı çağrılarda performans çok gelişti: * Bir örnek kullanarak 9545 msHttpResponseMessage içinde yanıt aldım . * 294 ms'de aynı yanıtı aldım . IHttpActionResult
chris lesage

@ chrislesage 9545 ms neredeyse 10 saniyedir. 294 ms bile biraz yavaş. Eğer 100ms'den fazla bir şey varsa o zaman orada başka bir şey iş başında. Bu hikayede ete karşı olandan daha fazlası var.
AaronLS

Yanıtlar:


305

Kullanmamaya karar verebilirsiniz, IHttpActionResultçünkü mevcut kodunuz HttpResponseMessagehazır yanıtlardan birine uymayan bir kod oluşturur . Bununla birlikte uyum sağlayabilir HttpResponseMessageiçin IHttpActionResultbir hazır yanıtı kullanarak ResponseMessage. Bunu çözmem biraz zaman aldı, bu yüzden zorunlu olarak birini veya diğerini seçmek zorunda olmadığınızı gösteren bir mesaj göndermek istedim:

public IHttpActionResult SomeAction()
{
   IHttpActionResult response;
   //we want a 303 with the ability to set location
   HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.RedirectMethod);
   responseMsg.Headers.Location = new Uri("http://customLocation.blah");
   response = ResponseMessage(responseMsg);
   return response;
}

Not, denetleyicinizin devralması gereken ResponseMessagetemel sınıfın bir yöntemidir ApiController.


1
ResponseMessage'ın artık ResponseMessageResult olduğunu öğrenmek için biraz zaman aldı. Belki de son zamanlarda yeniden adlandırıldı? PS Ayrıca cevap yeni bir anahtar kelime kaçırdınız ve öneri için çok teşekkürler :)
Ilya Chernomordik

10
@IlyaChernomordik ResponseMessageve ResponseMessageResultiki farklı şey. ResponseMessage()Bir olan yöntem içinde ApiControllerDenetleyiciniz devralan ve bu nedenle sadece bir yöntem çağrıdır gereken. Yani neworada anahtar kelimeye gerek yok. Muhtemelen miras almıyorsunuz ApiControllerveya statik bir metodun içindesiniz. ResponseMessageResulttürünün dönüş türüdür ResponseMessage().
AaronLS

3
@IlyaChernomordik yazdım olabilir response = base.ResponseMessage(responseMsg)daha net o taban sınıfı ApiController yöntemidir emin olmak için
AaronLS

Teşekkürler, gerçekten ApiController miras olmayan bir hizmet vardı, bu yüzden bulmak biraz zaman aldı.
Ilya Chernomordik

3
@pootzko Haklısın, OP'nin iki yaklaşımın aslında olmadığında "eski yol" ya da "yeni yol" olarak çerçeveleyerek birbirini dışladığını ima ettikleri gerçeğini ele aldım. Darrel'in cevabının, IHttpActionResult'u döndürmenin bazı faydalarını açıklamak için iyi bir iş yaptığını düşünüyorum ve cevabım, eski HttpResponseMessage'ı bir IHttpActionResult'a nasıl dönüştürebileceğinizi gösteriyor, böylece her iki dünyanın da en iyisini elde edebilirsiniz.
AaronLS

84

Yine de kullanabilirsiniz HttpResponseMessage. Bu yetenek ortadan kalkmayacak. Seninle aynı şekilde hissettim ve ek bir soyutlamaya gerek olmadığını ekiple kapsamlı bir şekilde tartıştım. Varlığını denemek ve meşrulaştırmak için etrafa atılan birkaç argüman vardı ama beni buna değdiğine ikna eden hiçbir şey yoktu.

Yani, bu örneği Brad Wilson'dan görene kadar . Eğer inşa halinde IHttpActionResultzincirleme edilebilir şekilde sınıflar, bir oluşturma yeteneği kazandırmak "eylem düzeyinde" üretmek için tepki boru hattı HttpResponseMessage. Kapakların altında, bu nasıl ActionFiltersuygulanır, ancak ActionFilterseylem filtreleri hayranı olmamamın bir nedeni olan eylem yöntemini okurken bunların sıralaması açık değildir.

Bununla birlikte, IHttpActionResulteylem yönteminizde açıkça zincirlenebilecek bir tane oluşturarak, yanıtınızı oluşturmak için her türlü farklı davranışı oluşturabilirsiniz.


62

İşte çeşitli yararları vardır IHttpActionResultüzerinde HttpResponseMessagebelirtilen Microsoft ASP.Net Dokümantasyon :

  • Denetleyicilerinizin birim testini basitleştirir.
  • HTTP yanıtları oluşturmak için ortak mantığı ayrı sınıflara taşır.
  • Yanıt oluşturmanın düşük düzeyli ayrıntılarını gizleyerek denetleyici eyleminin amacını daha net hale getirir.

Ancak, IHttpActionResultbelirtmeye değer olmanın diğer avantajları :

  • Tek sorumluluk ilkesine saygı duymak : eylem yöntemlerinin HTTP isteklerini sunma sorumluluğunu taşımasına neden olur ve bunları HTTP yanıt iletilerini oluşturmaya dahil etmez.
  • System.Web.Http.Results içinde zaten tanımlanmış faydalı uygulamalar : Ok NotFound Exception Unauthorized BadRequest Conflict Redirect InvalidModelState( tam listeye bağlantı )
  • Varsayılan olarak Async ve Await'i kullanır .
  • Sadece ExecuteAsyncyöntem kullanarak kendi ActionResult'u oluşturmak kolaydır .
  • Kullanabileceğiniz ResponseMessageResult ResponseMessage(HttpResponseMessage response)için IHttpActionResult için HttpResponseMessage dönüştürmek .

32
// this will return HttpResponseMessage as IHttpActionResult
return ResponseMessage(httpResponseMessage); 

18

Bu sadece benim kişisel görüşüm ve web API ekibinden millet muhtemelen daha iyi ifade edebilir ama işte benim 2c.

Her şeyden önce, bence bu birbiri üzerine bir soru değil. Hem size eylem yönteminde yapmak istediğinize ama gerçek gücünü anlamak için bağlı kullanabilirsiniz IHttpActionResultmuhtemelen bu kullanışlı yardımcı yöntemler dışında adım gerekecektir, ApiControllergibi Ok, NotFoundvb

Temelde bence bir sınıf IHttpActionResultfabrikası olarak uygulanıyor HttpResponseMessage. Bu zihin ayarlandığında, artık geri döndürülmesi gereken bir nesne ve onu üreten bir fabrika haline gelir. Genel programlama anlamında, nesneyi belirli durumlarda kendiniz oluşturabilirsiniz ve bazı durumlarda bunu yapmak için bir fabrikaya ihtiyacınız vardır. Burada aynı.

Karmaşık bir mantık, örneğin çok sayıda yanıt üstbilgisi, vb. İle oluşturulması gereken bir yanıtı geri döndürmek istiyorsanız, tüm bu mantığı bir eylem sonucu sınıf uygulamasına soyutlayabilir IHttpActionResultve yanıtı döndürmek için birden fazla eylem yönteminde kullanabilirsiniz.

IHttpActionResultDönüş türü olarak kullanmanın diğer bir avantajı da ASP.NET Web API eylem yöntemini MVC'ye benzetmesidir. Medya biçimlendiricilerine takılmadan herhangi bir işlem sonucunu döndürebilirsiniz.

Tabii ki, Darrel tarafından belirtildiği gibi, eylem sonuçlarını zincirleyebilir ve API boru hattındaki mesaj işleyicilerine benzer güçlü bir mikro boru hattı oluşturabilirsiniz. Bu, eylem yönteminizin karmaşıklığına bağlı olarak ihtiyacınız olacaktır.

Uzun lafın kısası - IHttpActionResultkarşı değil HttpResponseMessage. Temel olarak, yanıtı nasıl oluşturmak istersiniz. Kendiniz veya bir fabrika aracılığıyla yapın.


Fabrika gerekçesi ile yaşadım sorun kolayca ResponseFactory.CreateOkResponse()HttpResponseMessage döndürmek gibi statik yöntemler oluşturabilir ve yanıtı oluştururken zaman uyumsuz şeyler ile uğraşmak zorunda değildi. Bir ekip üyesi, üstbilgi değerleri oluşturmak için G / Ç yapmanız gerektiğinde zaman uyumsuzluğun yararlı olabileceğinden bahsetti. Bunun ne sıklıkta gerçekleştiğinden emin değilim.
Darrel Miller

Bence neden fabrika metodu modeline ihtiyacımız olduğunu söylemekle aynı şey. Neden sadece nesneleri oluşturmak için statik yöntemler kullanmıyorsunuz? Elbette, yapılabilir - her nesne yaratımı uygun bir fabrika modelini hak etmez. Ama sonra IMHO, sınıflarınızı nasıl modellemek istediğinize bağlıdır. Birden çok statik yöntem biçiminde bir sınıfa sıkışmış farklı türde yanıtlar oluşturmak için mantığınız mı yoksa arabirime dayalı farklı sınıflarınız mı var? Yine, iyi ya da kötü yoktur. Her şey bağlıdır. Her neyse, benim açımdan, bu bir diğerinin üzerinde değil ve şahsen fabrika şey daha iyi gibi :)
Badri

6

: Web API temelde nesnenin 4 türünü döndürür void, HttpResponseMessage, IHttpActionResultve diğer güçlü türleri. Web API'sinin ilk sürümü HttpResponseMessageoldukça basit olan HTTP yanıt iletisidir.

IHttpActionResultSarmasını bir tür WebAPI 2 ile tanıtıldı HttpResponseMessage. Bir ExecuteAsync()oluşturma yöntemi içerir HttpResponseMessage. Denetleyicinizin birim testini basitleştirir.

Diğer dönüş türü, yanıt gövdesine bir ortam biçimlendiricisi kullanılarak Web API'sı tarafından serileştirilen güçlü türden sınıflardır. Tek dezavantajı, 404 gibi bir hata kodunu doğrudan döndürememenizdi. Tek yapabileceğiniz bir HttpResponseExceptionhata atmak .


3

IHttpActionResult için TaskExecuteAsync arabirim işlevini uygulamayı tercih ederim. Gibi bir şey:

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = _request.CreateResponse(HttpStatusCode.InternalServerError, _respContent);

        switch ((Int32)_respContent.Code)
        { 
            case 1:
            case 6:
            case 7:
                response = _request.CreateResponse(HttpStatusCode.InternalServerError, _respContent);
                break;
            case 2:
            case 3:
            case 4:
                response = _request.CreateResponse(HttpStatusCode.BadRequest, _respContent);
                break;
        } 

        return Task.FromResult(response);
    }

, burada _request HttpRequest ve _respContent yüktür.


2

IHttpActionResultÜzerinden yararlanmanın aşağıdaki faydaları vardır HttpResponseMessage:

  1. Kullanarak IHttpActionResultsadece durum koduna değil gönderilecek verilere yoğunlaşıyoruz. Yani burada kod daha temiz ve bakımı çok kolay olacak.
  2. Uygulanan denetleyici yönteminin birim testi daha kolay olacaktır.
  3. Kullanır asyncve awaitvarsayılan olarak.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.