我有一些代码,我正在为ASP.NET和SignalR复制,我决定将其重写为OWIN中间件,以消除这种重复。
一旦我运行它,我注意到HttpContext.Current.Session
为空,我没有在IOwinContext
上看到我的中间件有任何会话对象。
是否可以从OWIN访问http会话?
答案 0 :(得分:28)
是的,但这是一个非常黑客。它也不适用于SignalR,因为SignalR必须在获取会话之前运行,以防止长会话锁定。
执行此操作以启用任何请求的会话:
public static class AspNetSessionExtensions
{
public static IAppBuilder RequireAspNetSession(this IAppBuilder app)
{
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();
});
// SetSessionStateBehavior must be called before AcquireState
app.UseStageMarker(PipelineStage.MapHandler);
return app;
}
}
然后,您可以使用HttpContext.Current.Session
或
HttpContextBase httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
答案 1 :(得分:7)
这个答案是来自the initial answer的混音,所以它的要点应该归功于@Tratcher。虽然单独发布它而不是建议编辑,但它已经不同了。
假设你想制作一个小的OWIN应用程序用于基本测试目的(例如,当进行集成测试时作为更大的API的存根/伪造),包括使用会话状态的稍微有点hakish的方式就可以正常工作。
首先,你需要这些:
using Microsoft.Owin;
using Microsoft.Owin.Extensions;
using Owin;
有了这些,你可以创建一个帮助方法:
public static void RequireAspNetSession(IAppBuilder app)
{
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);
}
您也可以将其创建为原始答案所做的扩展方法。
请注意,如果您不使用UseStageMarker
,则会遇到此错误:
“/”应用程序中的服务器错误。
'HttpContext.SetSessionStateBehavior'只能在引发'HttpApplication.AcquireRequestState'事件之前调用。
在任何情况下,使用上述内容,您现在可以在OWIN应用程序中使用HttpContext,如下所示:
public void Configuration(IAppBuilder app)
{
RequireAspNetSession(app);
app.Run(async context =>
{
if (context.Request.Uri.AbsolutePath.EndsWith("write"))
{
HttpContext.Current.Session["data"] = DateTime.Now.ToString();
await context.Response.WriteAsync("Wrote to session state!");
}
else
{
var data = (HttpContext.Current.Session["data"] ?? "No data in session state yet.").ToString();
await context.Response.WriteAsync(data);
}
});
}
如果您使用这个小应用程序启动IIS Express,您将首先获得:
会话状态中没有数据。
然后,如果你去http://localhost:12345/write
,你会得到:
写入会话状态!
然后,如果您返回/转到该主机上的任何其他网址,您将获得:
11/4/2015 10:28:22 AM
或类似的东西。