Asp.net
HttpContext.Current.Session 為 null + OWIN
我對 OWIN 完全陌生,這個問題一直是我的主要障礙。
基本上,在我的 MVC 應用程序中,我在 Startup 類中有以下內容:
public partial class Startup { public void ConfigureAuth(IAppBuilder app) { app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseCookieAuthentication(new CookieAuthenticationOptions()); app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { ClientId = OfficeSettings.ClientId, Authority = OfficeSettings.Authority, TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters() { RoleClaimType = "roles" }, Notifications = new OpenIdConnectAuthenticationNotifications() { AuthorizationCodeReceived = (context) => { // code hidden for readability if(HttpContext.Current.Session == null) { // It's null. Why is that? } var session = HttpContext.Current.Session; if (session["myMockSession"] != null) { // Do stuff... } }, RedirectToIdentityProvider = (context) => { // code hidden for readability }, AuthenticationFailed = (context) => { // code hidden for readability } } });我不明白為什麼在調試時 Session 為空。HttpContext.Current 屬性不是。Sessions + OWIN 有什麼限制嗎?這個問題有什麼解決方法嗎?應該如何處理它?
旁注 1:我嘗試添加在 SO 問題之一中找到的這段程式碼,但 Session 仍然為空:
app.Use((context, next) => { // Depending on the handler the request gets mapped to, session might not be enabled. Force it on. HttpContextBase httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName); httpContext.SetSessionStateBehavior(SessionStateBehavior.Required); return next(); });旁注 2:我似乎再也找不到它了,但是有人在 SO 問題之一中建議在 Global.asax 中添加空方法 Session_Start 和 Session_End (作為空方法)。那也沒有用。
我歡迎任何建議。謝謝!
你快到了。您的會話仍然為空的原因是您沒有指示 OWIN 在執行中間件之前初始化 System.Web 會話。
通過在中間件註冊後添加*.UseStageMarker(..)* 您將告訴 OWIN 在執行管道中的哪個位置執行SetSessionStateBehaviour
app.Use((context, next) => { var httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName); httpContext.SetSessionStateBehavior(SessionStateBehavior.Required); return next(); }); // To make sure the above `Use` is in the correct position: app.UseStageMarker(PipelineStage.MapHandler);預設情況下,Owin 中間件在最後一個事件 (PipelineStage.PreHandlerExecute) 處執行,在這種情況下這對您來說太晚了。
現在,要使用會話,您需要在第二個中間件中工作,該中間件在 Asp.Net 執行時獲取會話**之後執行。**此中間件必須在PostAquireState階段執行,如下所示:
.Use((context, next) => { // now use the session HttpContext.Current.Session["test"] = 1; return next(); }) .UseStageMarker(PipelineStage.PostAcquireState);Asp.Net katana docs 有一篇關於中間件如何工作的優秀文章。有關 Asp.net 中執行順序的詳細資訊,請參閱PiplineStage列舉文件和HttpApplication文件。