2015-02-18 9 views
104

Na powrocie z kontrolerem Web API 2, mogę powrócić treści z odpowiedzi, czy odpowiedź jest OK (stan 200) tak:Powrót treści z IHttpActionResult dla non-OK odpowiedzi

public IHttpActionResult Get() 
    { 
     string myResult = ... 
     return Ok(myResult); 
    } 

Jeśli to możliwe, Chcę używać wbudowanych typów wyników tutaj, gdy to możliwe: https://msdn.microsoft.com/en-us/library/system.web.http.results(v=vs.118).aspx

Moje pytanie dotyczy innego rodzaju odpowiedzi (nie 200), w jaki sposób mogę zwrócić wiadomość (ciąg) z nią? Na przykład, mogę to zrobić:

public IHttpActionResult Get() 
    { 
     return InternalServerError(); 
    } 

ale nie w ten sposób:

public IHttpActionResult Get() 
    { 
     return InternalServerError("Message describing the error here"); 
    } 

Idealnie chcę to być uogólnione tak, że mogę wysłać z powrotem z którymkolwiek z implementacjami IHttpActionResult.

Czy muszę to zrobić (i zbudować własną wiadomość z odpowiedzią):

public IHttpActionResult Get() 
    { 
     HttpResponseMessage responseMessage = ... 
     return ResponseMessage(responseMessage); 
    } 

czy jest jakiś lepszy sposób?

+0

jak o tym: http://stackoverflow.com/questions/10732644/best-practice-to-return-errors-in-asp-net -web-api – Milen

+0

nie można użyć 'ApiController.InternalServerError' https://msdn.microsoft.com/en-us/library/dn292630(v=vs.118).aspx – Ric

+0

@Milen, dziękuję. Coś takiego może działać. Część, której nie lubię, wymaga stworzenia innej implementacji IHttpActionResult dla każdej istniejącej implementacji, którą chcę móc wykorzystać. – mayabelle

Odpowiedz

20

skończyło się dzieje z następującym roztworem:

public class HttpActionResult : IHttpActionResult 
{ 
    private readonly string _message; 
    private readonly HttpStatusCode _statusCode; 

    public HttpActionResult(HttpStatusCode statusCode, string message) 
    { 
     _statusCode = statusCode; 
     _message = message; 
    } 

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
    { 
     HttpResponseMessage response = new HttpResponseMessage(_statusCode) 
     { 
      Content = new StringContent(_message) 
     }; 
     return Task.FromResult(response); 
    } 
} 

... które mogą być używane tak:

public IHttpActionResult Get() 
{ 
    return new HttpActionResult(HttpStatusCode.InternalServerError, "error message"); // can use any HTTP status code 
} 

Jestem otwarty na sugestie dotyczące poprawy. :)

+0

Odpowiedź Shamila Yakupova jest najlepszą odpowiedzią, ale tylko z poziomu klasy ApiController - musi zostać przepisana jako "return new NegotiatedContentResult (kod, nowy T (...), kontroler)" do użycia spoza kontrolera klasa. W takim przypadku rozwiązanie takie jak powyższe może być bardziej czytelne. – Etherman

39

Można użyć HttpRequestMessagesExtensions.CreateErrorResponse (System.Net.Http nazw), tak jak poniżej:

public IHttpActionResult Get() 
{ 
    return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Message describing the error here")); 
} 

Zaleca się tworzyć w oparciu o odpowiedzi na wniosek w sprawie skorzystania z treścią negocjacji Web API.

+5

Request.CreateErrorResponse zwraca HttpResponseMessage, a nie IHttpActionResult. To, co opisujesz, jest dobrą praktyką do tworzenia HttpResponseMessage, ale nie odnosi się do mojego pytania. Dzięki i tak! – mayabelle

+0

@mayabelle można utworzyć IHttpActionResult betonu i owinięte w ten kod: –

+0

To działało dla mnie, ale użyłem Request.CreateResponse, tak aby błąd wyświetlał się jako ciąg zamiast klucza wiadomości. – Chemist

1

@mayabelle można tworzyć konkretne IHttpActionResult i owinięty tych kodu:

public class NotFoundPlainTextActionResult : IHttpActionResult 
{ 
    public NotFoundPlainTextActionResult(HttpRequestMessage request, string message) 
    { 
     Request = request; 
     Message = message; 
    } 

    public string Message { get; private set; } 
    public HttpRequestMessage Request { get; private set; } 

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
    { 
     return Task.FromResult(ExecuteResult()); 
    } 

    public HttpResponseMessage ExecuteResult() 
    { 
     var response = new HttpResponseMessage(); 

     if (!string.IsNullOrWhiteSpace(Message)) 
      //response.Content = new StringContent(Message); 
      response = Request.CreateErrorResponse(HttpStatusCode.NotFound, new Exception(Message)); 

     response.RequestMessage = Request; 
     return response; 
    } 
} 
13

Można również zrobić:

return InternalServerError(new Exception("SOME CUSTOM MESSAGE")); 
297

Można to wykorzystać:

return Content(HttpStatusCode.BadRequest, "Any object"); 
+0

Krótkie i proste rozwiązanie. Posiadanie większej liczby kodów oznacza więcej błędów i czasochłonną konserwację. –

+1

Kiedy próbuję tego, zwracana wartość 'code' (gdzie kod jest ciągiem) w' Zwróć zawartość (HttpStatusCode.OK, kod) 'jest enkapsulowany w" co jest nieoczekiwane, czy jest jakikolwiek powód tego? Np. Wartość który jest zwracany jest '" \ "wartość \" "Używam mvc5 – Deza

+0

Jeśli musisz to zrobić spoza klasy ApiController, możesz użyć: return new NegotiatedContentResult (kod, nowy T (...), kontroler) – Etherman

6

Każdy, kto jest zainteresowany zwróceniem czegokolwiek z dowolnym kodem statusu z powracaniem ResponseMessage:

//CreateResponse(HttpStatusCode, T value) 
return ResponseMessage(Request.CreateResponse(HttpStatusCode.XX, object)); 
0

Przepraszam za opóźnienie w odpowiedzi, dlaczego nie proste użycie

return BadRequest("your message");

Używam go dla wszystkich moich IHttpActionResult błędów jego pracy dobrze

Oto dokumentacja: https://msdn.microsoft.com/en-us/library/system.web.http.apicontroller.badrequest(v=vs.118).aspx

+6

Ponieważ nie wszystkie błędy są wynikiem złych żądań, więc odpowiedź '400' byłaby nieodpowiednia, OP konkretnie dał jako przykład odpowiedź 500. – user1620220

+0

Tak, to jest możliwe tylko przy BadRequest inne typy nie biorą Argument wiadomości: – benraay

5

W ASP.NET Web API 2, można owinąć każdy ResponseMessage w sposób ResponseMessageResult:

public IHttpActionResult Get() 
{ 
    HttpResponseMessage responseMessage = ... 
    return new ResponseMessageResult(responseMessage); 
} 

W niektórych przypadkach może to być najprostszy sposób, aby uzyskać pożądany efekt, choć na ogół może być korzystne do korzystania z różnych wyników w System.Web.Http.Results.

3

Jest tak wiele odpowiedzi tutaj, ale nie znalazłem żadnych, które pozwalają mi bezpośrednio zwrócić komunikat o wyjątku w opisie statusu odpowiedzi.

Na przykład, gdybym pisał usługi WCF, mogłem śledzić this tutorial bezpośrednio zwrócić komunikat Exception jako część stanu Odpowiedź:

Error

Większość odpowiedzi tutaj także zwrócić 500 Status, ale komunikat o błędzie jest zwracany jako obiekt JSON lub oddzielny ciąg odpowiedzi, a nie jako część statusu odpowiedzi.

Na przykład, jeśli miałbym użyć tego kodu:

catch (Exception ex) 
{ 
    return new System.Web.Http.Results.ResponseMessageResult(
     Request.CreateErrorResponse((HttpStatusCode)500, 
      new HttpError("Something went wrong"))); 
} 

... wówczas zwraca rodzajowe 500 wiadomości, a wyjątek jest zwracany w ciąg JSON.

enter image description here

Uważam to za dużo neater bezpośrednio mieć tekst wiadomości wyjątek jako część StatusDescription. Czy istnieje sposób, aby to zrobić, w kontrolerze Web API 2, który zwraca IHttpActionResult?

+5

To pytanie powinno być zadane w innym poście. To jest miejsce na odpowiedzi: – ilans

+0

Błąd \t CS1955 \t Nie wywoływanie Element członkowski "ResponseMessageResult" nie może być użyty jak metoda. – Mike

0

Miałem ten sam problem. Chcę utworzyć niestandardowy wynik dla moich kontrolerów api, aby połączyć je jak return Ok("some text");

Potem zrobiłem to: 1) Utwórz niestandardowy typ wynikowy singletone

public sealed class EmptyResult : IHttpActionResult 
{ 
    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
    { 
     return Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.NoContent) { Content = new StringContent("Empty result") }); 
    } 
} 

2) Utwórz niestandardowy sterownik z nowej metody :

public class CustomApiController : ApiController 
{ 
    public IHttpActionResult EmptyResult() 
    { 
     return new EmptyResult(); 
    } 
} 

I wtedy można nazwać je w moich kontrolerów, tak:

public IHttpActionResult SomeMethod() 
    { 
     return EmptyResult(); 
    } 
-1

Ta odpowiedź jest oparta na odpowiedzi Shamila Yakupova, z rzeczywistym obiektem zamiast z ciągiem znaków.

using System.Dynamic; 

dynamic response = new ExpandoObject(); 
response.message = "Email address already exist"; 

return Content<object>(HttpStatusCode.BadRequest, response); 
0

Wyjątki zwykle zrobić

catch (Exception ex) 
     { 
      return InternalServerError(new ApplicationException("Something went wrong in this request. internal exception: " + ex.Message)); 
     } 
Powiązane problemy