HttpContext.Current ist in den Methoden von Identity Framework null

8

Ich verwende ASP.NET MVC 5 und Identity Framework. Wenn ich UserManager.UpdateAsync (...) aufrufen, werden meine Eventhandler auf ApplicationDbContext () SaveChanges ausgeführt. Hier verwende ich HttpContext.Current für verschiedene Zwecke (Logging und Auditing), also muss ich sagen aktuellen Benutzer. Die gesamte Methode wird jedoch in einem Arbeitsthread ausgeführt, und hier ist HttpContext.Current null.

Das größte Problem, dass die "sync" -Methoden des UserManagers nur Wrapper um die async-Version sind, also sind die Aufrufe serialisiert, aber die Methoden (und eventhandlers) laufen immer noch in einem anderen Arbeitsthread.

Bitte beachten Sie, dass dieses Problem nichts mit dem async / await Kontext zu tun hat. In der Steuerung nach dem Warten (oder Aufruf der 'Sync' Version) habe ich den richtigen HttpContext zurück, sogar die Methode des Controllers wird in einem anderen Thread fortgesetzt. Das ist in Ordnung.

Das Problem liegt also im asynchronen Worker, der sowohl in der "sync" - als auch in der async-Version ausgeführt wird. Ich denke, ich verstehe die Phänomene (aber ich bin nicht glücklich mit den falschen 'Sync' Methodenversionen, echte Synchronisationsmethoden würden dieses Problem nicht aufweisen.) Ich weiß einfach nicht, wie ich es behandeln / umgehen kann.

[btw: Wäre es nicht natürlicher, die Operationen von UserManager als einfache reine Sync-Versionen zu implementieren und sie dann mit asynchronen Multithread-Wrappern zu umhüllen ?. Wenn wir diese asynchrone Mode ohne nachzudenken fortsetzen, werden wir bald den asynchronen Zuweisungsoperator erfinden. Es kostet mich Dutzende von Stunden (nur dieses Problem), und kostet weltweit Zillionen Dollar, ich bin mir sicher, in vielen Fällen weniger Rendite als sein Preis.]

Bonus: Wir sprechen über UserManager, was ziemlich marginal ist, aber die gleichen Prinzipien und Probleme können jede Out-of-the-Box-Bibliothek (Blackbox für Sie) anwenden, welche Autoren keine Sync-Versionen implementieren und sich nicht um den Controller kümmern Thread-Kontext. Was ist mit EF, es ist nicht so marginal ... und was ist mit DI-Container Instanziierungs-Infrastruktur wie "Request Scope" oder "Session Scope". Sicher verhalten sie sich schlecht, wenn das Auflösen in einem Thread ohne HttpContext.Current erfolgt. Kürzlich habe ich SendGrid NuGet aktualisiert, und (als brechende Änderung) Deliver () -Methode ist weg, und jetzt ist nur DeliverAsync () vorhanden ...

Ich hätte gerne einen sicheren, zuverlässigen Weg, wie ich auf den HttpContext in diesem Worker für Protokollierungs- und Auditzwecke zugreifen kann.

Beispielcode, die 'Sync' Version des Controllers:

%Vor%

Beispielcode, die asynchrone Controller-Version:

%Vor%

und der Ereignishandler, in dem HttpContext null ist:

%Vor%

Irgendwelche Ideen?

    
g.pickardou 14.07.2015, 23:21
quelle

2 Antworten

4

Wie Sie bereits gesagt haben, geschieht dies aufgrund von Threading. Der Delegat wird in einem anderen Thread ausgeführt, wodurch der HttpContext nicht zugänglich ist.

Sie können die Variable außerhalb des Delegaten verschieben, sodass sie geschlossen wird.

%Vor%     
Rowan Freeman 15.07.2015 02:19
quelle
1

Sie benutzen asp.net Identität durch owin, Eine Instanz von dbcontext wird also pro Anfrage erstellt. und Sie können diese Referenz von überall in der Anfrage-Pipeline erhalten.

nb. Das ist praktisch, aber ich denke, auf den dbcontext sollte nicht außerhalb des Managers zugegriffen werden. In asp.net Identity Design sollte nur der Manager des Geschäfts kennen. Ich glaube, dass der dbcontext offen gelegt wird, weil mehrere asp.net-Identitäts-Middleware davon abhängig sind.

Aber es könnte helfen, Ihr Problem zu lösen:

Lassen Sie Ihren benutzerdefinierten dbcontext-Handler außerhalb der Klasse festlegen:

%Vor%

Deklarieren Sie eine benutzerdefinierte ActionFilter-Klasse, registrieren Sie sie und überschreiben Sie OnActionExecuting:

Filtern in ASP.NET MVC Ссылка

%Vor%

Sie benötigen diese using-Anweisungen, um die identity.owin-Erweiterungsmethoden aufrufen zu können:

  

unter Verwendung von Microsoft.AspNet.Identity;

     

unter Verwendung von Microsoft.AspNet.Identity.Owin;

Sie sollten sich im Controller-Thread befinden, da OnActionExecuting die Controller-Aktion umschließt.

Ich habe es nicht getestet, also muss es vielleicht etwas poliert werden, aber das Konzept sollte funktionieren.

    
Bombinosh 17.07.2015 12:04
quelle