2013-07-25 15 views
5

Ich habe ein synchrones HttpModule, das den folgenden Code enthält. Asynchrones HttpModule MVC

/// <summary> 
    /// Occurs as the first event in the HTTP pipeline chain of execution 
    /// when ASP.NET responds to a request. 
    /// </summary> 
    /// <param name="sender">The source of the event.</param> 
    /// <param name="e">An <see cref="T:System.EventArgs">EventArgs</see> that 
    /// contains the event data.</param> 
    private async void ContextBeginRequest(object sender, EventArgs e) 
    { 
     HttpContext context = ((HttpApplication)sender).Context; 
     await this.ProcessImageAsync(context); 
    } 

Wenn ich versuche, das Modul von einer leeren MVC4 Anwendung (NET 4.5) Ich erhalte die folgenden Fehler zu laufen.

Ein asynchroner Betrieb kann zu diesem Zeitpunkt nicht gestartet werden. Asynchrone Operationen können nur innerhalb eines asynchronen Handlers oder Moduls oder während bestimmter Ereignisse im Seitenlebenszyklus gestartet werden. Wenn diese Ausnahme beim Ausführen einer Seite aufgetreten ist, stellen Sie sicher, dass die Seite als <% @ Page Async = "True"%> markiert ist.

Ich vermisse etwas, aber es scheint, aber durch meine Lesung, dass der Fehler eigentlich nicht auftreten sollte.

Ich hatte eine Grabung, aber ich kann anscheinend nichts finden, um zu helfen, hat jemand irgendwelche Ideen?

Antwort

10

So haben Sie asynchronen Code in einem synchronen HttpModule-Ereignishandler und ASP.NET löst eine Ausnahme aus, die angibt, dass asynchrone Vorgänge nur innerhalb eines asynchronen Handlers/Modul gestartet werden können. Scheint ziemlich einfach für mich.

Um dies zu beheben, sollten Sie BeginRequest nicht direkt abonnieren; Erstellen Sie stattdessen einen Task -zurückgebenden "Handler", wickeln Sie ihn in EventHandlerTaskAsyncHelper ein und übergeben Sie ihn an AddOnBeginRequestAsync.

Etwas wie folgt aus:

private async Task ContextBeginRequest(object sender, EventArgs e) 
{ 
    HttpContext context = ((HttpApplication)sender).Context; 
    await ProcessImageAsync(context); 

    // Side note; if all you're doing is awaiting a single task at the end of an async method, 
    // then you can just remove the "async" and replace "await" with "return". 
} 

und abonnieren:

var wrapper = new EventHandlerTaskAsyncHelper(ContextBeginRequest); 
application.AddOnBeginRequestAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler); 
+0

Dies muss ein paar Mal sein, das Sie mir jetzt geholfen haben, Dank! Ich hätte gesagt, tut mir leid, der Code ist tatsächlich in Net 4.0 geschrieben und verwendet die BCL-Bibliotheken, um das async-Schlüsselwort zu unterstützen, so dass ich sowohl 4.0 als auch 4.5 unterstützen konnte. Daher ist EventHandlerTaskAsyncHelper für mich nicht verfügbar. –

+2

Ah, leider hat "Microsoft.Bcl.Async" [undefined Verhalten auf ASP.NET 4.0] (http://blogs.msdn.com/b/webdev/archive/2012/11/19/all-about-httpruntime -targetframework.aspx). Unter ASP.NET müssen Sie * auf .NET 4.5 und nicht auf .NET 4.0 ausführen. –

+0

Ah ok ... Also, dies zu testen, wenn ich die 'targetFramework =" 4.5 "' aus dem '' Knoten in der web.config dies funktioniert. Bedeutet das, dass mein httpModule in NET 4.0 nicht asynchron ist? Bedeutet das auch, dass ich kein asynchrones httpModule ohne 'EventHandlerTaskAsyncHelper' mit MVC verwenden kann oder gibt es einen anderen Weg. Ich bin immer noch ein bisschen verwirrt, dass es einen Fehler wirft, um ehrlich zu sein. Die Nachricht scheint zu sagen, dass httpModules in Ordnung sind. –