2009-12-21 9 views
5

Ich habe eine Web-Anwendung, die stark auf Web-Services beruht. Alles mit den Diensten erfolgt asynchron und mit AddOnPreRequestHandlerExecuteAsync. Jedenfalls funktionieren die meisten meiner Anrufe gut, aber einige kehren von ihren asynchronen Serviceaufrufen zurück, um ein NULL-HttpContext.Current.Response/Request-Objekt in der Endanforderung zu finden, was natürlich Fehler in dem Moment, in dem ich versuche, zu verwenden. Beide Objekte (Response und Request sind bei Beginn der Anforderung fehlgeschlagener Anrufe verfügbar und nicht null und arbeiten in der Endanforderung anderer Anrufe).Asynchrone HttpWebRequests und ein null HttpContext.Current.Response/Request-Objekt

Irgendjemand, der auf ähnlichem trifft, oder eine Rate hat, was das Problem sein könnte?

Update: Scheint, eine Lösung gefunden zu haben, wenn ich eine Variable für die HttpApplication auf Init (des HttpModules, in dem alles vorkommt) erstelle, kann der HttpContext von dieser Variable aus erreicht werden.

Update: Die Übergabe von entweder HttpApplication oder HttpContext.Current auf die Begin-Funktion hat das gleiche Problem. Wenn sie als Teil des "Zustands" des asynchronen Aufrufs übergeben werden, enden sie in der Endfunktion auf Null, obwohl sie in der Begin-Funktion gültig sind.

Update: Ich habe einige Protokollierung hinzugefügt und festgestellt, dass der asynchrone Aufruf, den ich mache, korrekt zurückgibt, die Ergebnisse sind da, die Callback-Funktion wird ordnungsgemäß aufgerufen.

Antwort

0

Scheint eine Lösung gefunden zu haben, wenn ich eine Variable für die HttpApplication auf Init (des HttpModules, in dem alles vorkommt) erstelle, kann der HttpContext von dieser Variable aus erreicht werden.

+0

Können Sie mit Details beschreiben, wie Sie das Problem gelöst haben – omoto

+0

In meinem HttpModule habe ich eine Variable vom Typ HttpApplication. Im Funktionsaufruf init() setze ich diese Variable auf die HttpApplication, die an init übergeben wird. In BeginPreRequestHandlerExecute und EndPreRequestHandlerExecute verweise ich auf den aktuellen HttpContext mit oApplication.Context, wobei oApplication der Name der HttpApplication-Variable in meinem HttpModule ist. – aepheus

5

Ich vermute, ich kenne das Problem, in das Sie geraten. Die Antwort lautet mit ziemlicher Sicherheit, die Verwendung von HttpWebRequest durch WebClient zu ersetzen und die * Async-Methoden von WebClient zu verwenden.

Hier ist die lange Erklärung: Es gibt zwei völlig verschiedene Async-Programmiermodelle: die IAsyncResult Async Pattern und die Event-based Asynchronous Pattern. Das IAsyncResult-Muster verwendet die Methoden BeginXXX und EndXXX, verwendet IAsyncResult-Instanzen, verwendet Delegaten für Rückrufe und unterstützt das Warten auf den Abschluss. Das ereignisbasierte Muster verwendet XXXAsync-Methoden, um asynchrone Aktionen zu initiieren, verwendet XXXCompleted Ereignisse anstelle von Rückrufen, um die Vervollständigung zu verarbeiten, und (dies ist in Ihrem Fall wichtig) überträgt Thread-spezifischen Kontext in jeden Callback-Ereignishandler.

Mit anderen Worten, wenn Sie Ihren Rückrufcode in einem XXXCompleted-Ereignishandler (wie WebClient.DownloadStringCompleted) setzen, wird HttpContext.Current korrekt ausgefüllt.

Wenn Sie jedoch eine BeginXXX-Methode (wie HttpWebRequest.BeginGetResponse) und einen Delegaten-Rückruf verwenden, wird Ihr Rückruf im Zusammenhang mit einem Thread ausgeführt, der nicht garantiert, dass der richtige ASP.NET-Kontext angehängt ist.

Im Allgemeinen verwenden .NET Framework-Bibliotheksklassen entweder ein asynchrones Muster oder das andere. In der Regel verwenden die untergeordneten Klassen (z. B. HttpWebRequest) das IAsyncResult-Muster, während die übergeordneten Klassen (z. B. WebClient) das ereignisbasierte Muster verwenden. Einige Oddball-Klassen (z. B. automatisch generierte .NET-Remoteproxys) unterstützen beide Muster, aber das ist eine Seltenheit.

Also, wenn es einfach zu tun ist, würde ich vorschlagen, zu WebClient und Event-Handler anstelle von HttpWebRequest und Callback-Delegaten zu verschieben. Dies sollte dein Problem lösen. Wenn der Wechsel zu WebClient zu schwierig ist, kommentieren Sie mich, und ich kann Ihnen wahrscheinlich einige obskure Alternativen vorschlagen.

+0

Ich bin mir nicht sicher, wie einfach das in meinem Fall zu implementieren wäre.Ich glaube, dass ich zumindest auf der Basisebene an das IAsyncResult-Muster gebunden bin, da dies das Muster ist, das AddOnPreRequestHandlerExecuteAsync unterstützt. Und da ich die Dinge momentan nur durch Speichern des Zustands in einer Variable funktioniere, würde ich es vorziehen, mich nicht damit zu beschäftigen. – aepheus