5

Ich habe einige widersprüchliche Informationen zu diesem Thema gesehen, und ich möchte hier einige Klarheit erreichen.Wie richtig asynchronicity in Web API implementieren 2

Ursprünglich würden Sie Web Api Aktionen haben, wie:

  • Model Action();
  • HttpResponseMessage Action();

Dann mit dem Zusatz von TPL Erweiterungen Web Api, könnten Sie haben

  • Task<Model> Action();
  • Task<HttpResponseMessage> Action();

Und angeblich würde ASP.NET intelligent genug, um diejenigen zu handhaben durch das Warten auf die Aufgabe, zu beenden und durch die Fadenfreigabe, der die Anforderung in der Zwischenzeit abgeholt.

Schön! Alles war einfach in der Welt. Aber jetzt, mit Web API 2, gibt es einen Zusatz von IHttpActionResult, ein dritter Fall, der die Task<HttpResponseMessage> ExecuteAsync() Methode zur Verfügung stellt.

Zunächst einmal, wenn Sie Implementierungen von IHttpActionResult untersuchen, sehen Sie, dass jeder ExecuteAsync eigentlich nur wieder Task.FromResult (nicht im ASYNC und scheint nicht, wie es synchron jede Performance-Gewinn geben würde über HttpResponseMessage Rückkehr). Zweitens sehe ich Leute, die die Verwendung von Task<IHttpActionResult> empfehlen, was völlig redundant erscheint. Ich sehe sogar eine Handvoll Leute, die vorschlagen, dass Sie diese Ansätze kombinieren und Task.Factory.StartNew(..) von Ihrer Aktion zurückgeben, was irgendwie absurd erscheint.

Also, was ist der richtige Weg, IHttpActionResult asynchron zu verwenden? Implementieren Sie einfach Ihre eigenen und führen Sie asynchrone Operationen dort aus † oder geben Sie Task<IHttpActionResult> zurück, machen Sie Ihre Methode async, und warten Sie auf IO-gebundene Operationen, bevor Sie return Ok() (oder gleichwertig) aufrufen?

Um klar zu sein, ich verstehe natürlich, dass einfach von IHttpActionResult Action(); bis Task<IHttpActionResult> Action(); ohne Änderung der Methode Körper wird in keiner Weise helfen. Es ist die Absicht der ExecuteAsync das ist ein Puzzle.

https://stackoverflow.com/a/21609402/661422

+0

Mit 'Task.FromResult' ist ein Detail Umsetzung - das ist hat die Implementierer die Entscheidung, nicht zu verwenden Asynchronität genommen, aber entscheiden kann es in Zukunft zu verwenden, wenn es gerechtfertigt ist. Während es keine gute Möglichkeit gibt, eine synchrone API asynchron zu implementieren. So –

Antwort

3

Alles war in der Welt einfach. Aber jetzt, mit Web-API-2 gibt es eine Zugabe von IHttpActionResult

IHttpActionResult auf die Welt kam zum Zwecke der Erzeugung von HttpResponseMessage eingekapselt wird. Auf diese Weise können Sie eine allgemeine Logik kapseln, um ähnliche Antworten innerhalb einer Gruppe von Klassen zu erstellen, die wiederverwendet werden können, leicht getestet werden können und die Controller-Aktionen freigeben, um sich um die eigentliche Geschäftslogik zu kümmern.

Zunächst, wenn Sie Implementierungen von IHttpActionResult überprüfen, sehen Sie, dass jedes ExecuteAsync tatsächlich nur Task zurückgibt.FromResult

Ich gehe davon aus, dass geschieht, weil zum Beispiel NotFound(); und Ok() Erweiterungsmethoden einfach ein HttpResponseMessage konstruiert zurückzukehren, nicht mehr. Vielleicht sind Sie nicht in reale Szenarien geraten, wo das nötig wäre.

Zweitens sehe ich Leute empfehlen, die Aufgabe zu verwenden, die völlig überflüssig scheint.

Sie würden Task<IHttpActionResult> zurückgeben, wenn Ihre Aktion eine natürlich asynchrone Operation verwendet. Ich sehe nicht, wie das überflüssig sein kann. Es wird gebraucht.

Also, was ist der richtige Weg, IHHTpActionResult asynchron zu verwenden?

Der korrekte Weg ist der gleiche wie für alle asynchronen Methoden. Lassen Sie uns sagen Sie jede Antwort vor der Rückkehr in eine 3rd-Party-Logging-Framework protokollieren wollen, die über HTTP-Endpunkt eine asynchrone API zeigt, dann würden Sie tun:

public class LogActionResult : IHttpActionResult 
{ 
    string uri = /* ... */ 

    public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
    { 
     var response = new HttpResponseMessage() 
     { 
      Content = new StringContent(_value), 
      RequestMessage = _request 
     }; 

     var httpClient = new HttpClient(); 
     await httpClient.PostAsJsonAsync(uri, response); 

     return response; 
    } 
} 

Asynchronoysly anmelden und die HttpResponseMessage zurückzukehren. Wenn Sie keinen Asynchron-Betrieb haben, würde Task.FromResult völlig in Ordnung sein.

+0

in der Praxis gehen die Menschen vor und erstellen Implementierungen von IHttpActionResult in realen Szenarien? – Kir

+0

@Kir Ja, sie tun. –

0

Ich mag nicht die Art und Weise, wo ich brauche Anbieter Schnittstellen zu implementieren, die von Version zu Version geändert hat, gibt es eine genauere Version:

public class FibonacciController : ApiController 
{ 
    public IHttpActionResult Get(int fibN) 
    { 
     Task.Factory.StartNew(() => 
     { 
      var fibNResult = FibonacciHelpers.CalculateFibonacci(fibN); 
     }); 

     return Ok(); 
    } 
}