2015-02-05 15 views
28

Czy istnieje sposób, w jaki mogę użyć nowego interfejsu IHttpActionResult, aby zwrócić komunikat odpowiedzi na HttpStatusCode.NoContent?Tworzenie nowych metod wyniku akcji IHttpActionResult

Obecnie używam return new HttpResponseMessage(HttpStatusCode.NoContent); i chciałbym przekonwertować to na return NoContent();.

IHttpActionResult ma już Ok(), Conflict() i NotFound() ale nie mogę znaleźć żadnego dla Forbidden() i NoContent() które trzeba użyć w moim projekcie.

Jak łatwo dodać inne typy wyników?

Odpowiedz

21

Znalazłem example site, który pokazuje, jak dodać niestandardową metodę IHttpActionResult i Użyłem tego, aby stworzyć Forbidden() i NoContent() metod z wielkim sukcesem.

public abstract class CommonApiController : ApiController 
{ 
    public class ForbiddenResult : IHttpActionResult 
    { 
     private readonly HttpRequestMessage _request; 
     private readonly string _reason; 

     public ForbiddenResult(HttpRequestMessage request,string reason) 
     { 
      _request = request; 
      _reason = reason; 
     } 

     public ForbiddenResult(HttpRequestMessage request) 
     { 
      _request = request; 
      _reason = "Forbidden"; 
     } 

     public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
     { 
      var response = _request.CreateResponse(HttpStatusCode.Forbidden,_reason); 
      return Task.FromResult(response); 
     } 
    } 

    public class NoContentResult : IHttpActionResult 
    { 
     private readonly HttpRequestMessage _request; 
     private readonly string _reason; 

     public NoContentResult(HttpRequestMessage request,string reason) 
     { 
      _request = request; 
      _reason = reason; 
     } 

     public NoContentResult(HttpRequestMessage request) 
     { 
      _request = request; 
      _reason = "No Content"; 
     } 

     public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
     { 
      var response = _request.CreateResponse(HttpStatusCode.NoContent,_reason); 
      return Task.FromResult(response); 
     } 
    } 
} 

I wtedy można go używać tak:

public class InvoiceController : CommonApiController 
{ 
    public async Task<IHttpActionResult> Post([FromBody]Invoice invoice) 
    { 
     if(User.IsInRole("Readonly")) 
     { 
      return Forbidden(); 
     } 

     // Rest of code 

    } 
} 
36

Nie ma metoda wygoda dla no-content wyniku, ponieważ domyślnie, gdy akcja wraca void, odpowiedź będzie mieć status HTTP 204.

Jeśli chcesz, aby wyraźnie wskazać, że na działania, można również zwrócić StatusCode(HttpStatusCode.NoContent) z działania lub

ResponseMessage(new HttpResponseMessage(HttpStatusCode.NoContent)). 

nieautoryzowanego() metoda wygoda daje status 401 tak, aby zabronione (403), to będzie też musiał użyć StatusCode(HttpStatusCode.Forbidden) lub

ResponseMessage(new HttpResponseMessage(HttpStatusCode.Forbidden)) 
+3

Nieautoryzowane = 401. Forbidden = 403. –

+0

Fajnie, to najlepsza odpowiedź. –

+2

W niektórych przypadkach zwrócenie 'void' nie jest opcją, ponieważ chcesz odpowiedzieć BadRequest lub innym kodem statusu w procesie sprawdzania poprawności tylko wyślij NoContent na sukces. Zwrócenie 'StatusCode (HttpStatusCode.NoContent)' rozwiązało to dla mnie i jest o wiele czystszym rozwiązaniem niż zaakceptowana odpowiedź. – Nemo1024

3

Jeśli chcesz dołączyć frazę rozsądku odpowiedź bez dodawania podklasę do ApiController, zbudować obiekt ResponseMessage i powrócić z działania metodą ResponseMessage(). Wypróbuj to:

public class InvoiceController : ApiController 
{ 
    public async Task<IHttpActionResult> Post([FromBody]Invoice invoice) 
    { 
     if(User.IsInRole("Readonly")) 
     { 
      var response = new HttpResponseMessage(HttpStatusCode.Forbidden); 

      response.ReasonPhrase = "User has the Readonly role"; 
      return ResponseMessage(response); 
     } 

     // Rest of code 

    } 
} 
4

Próbowałem implementacji @Intrepid i napotkałem pewne problemy. Widzę dwa rozwiązania tutaj:

Rozwiązanie 1: Część: return Forbidden(); nie powinna działać.

Kompilator nie rozpoznałby tego.

Zamiast tego powinno być: return new ForbiddenResult(Request, "my reason");

UPDATE 1

Rozwiązanie 2:

Myślę, że to co @Interpid przeznaczone na jego realizację, ale brakowało kilku rzeczy .

Aby korzystać return Forbidden();CommonApiController powinny być aktualizowane z funkcjami, które zwracają zwyczaj IHttpActionResult dla Forbidden i NoContent

Klasa powinna wyglądać następująco:

public abstract class CommonApiController: ApiController { 

    protected ForbiddenResult Forbidden() { 
    return new ForbiddenResult(this.Request); 
    } 

    protected ForbiddenResult Forbidden(string reason) { 
    return new ForbiddenResult(this.Request, reason); 
    } 

    protected NoContentResult NoContent() { 
    return new NoContentResult(this.Request); 
    } 

    protected NoContentResult NoContent(string reason) { 
    return new NoContentResult(this.Request, reason); 
    } 

    public class ForbiddenResult: IHttpActionResult { 
    private readonly HttpRequestMessage _request; 
    private readonly string _reason; 

    public ForbiddenResult(HttpRequestMessage request, string reason) { 
     _request = request; 
     _reason = reason; 
    } 

    public ForbiddenResult(HttpRequestMessage request) { 
     _request = request; 
     _reason = "Forbidden"; 
    } 

    public Task <HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) { 
     var response = _request.CreateResponse(HttpStatusCode.Forbidden, _reason); 
     return Task.FromResult(response); 
    } 
    } 

    public class NoContentResult: IHttpActionResult { 
    private readonly HttpRequestMessage _request; 
    private readonly string _reason; 

    public NoContentResult(HttpRequestMessage request, string reason) { 
     _request = request; 
     _reason = reason; 
    } 

    public NoContentResult(HttpRequestMessage request) { 
     _request = request; 
     _reason = "No Content"; 
    } 

    public Task <HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) { 
     var response = _request.CreateResponse(HttpStatusCode.NoContent, _reason); 
     return Task.FromResult(response); 
    } 
    } 
    } 

W każdym razie, jeśli jestem źle i odpowiedź @ Interpid jest poprawna. Czego mi tu brakuje, aby jego implementacja działała?

+1

Zaktualizowano odpowiedź. Dodano inne alternatywne rozwiązanie. Myślę, że drugim rozwiązaniem jest przede wszystkim to, co @Interpid. –

+0

Myślę, że masz tu dobry pomysł. To powinna być zaakceptowana odpowiedź. – valentin

+0

Uwaga: NIE powinieneś zwracać treści treści bez zawartości 204. Chciałbym usunąć z kodu "chronioną metodę NoContentResult NoContent (string reason)". Zobacz https://stackoverflow.com/a/23374724/2463738, aby uzyskać więcej informacji. – valentin

Powiązane problemy