问题
I had a little bit of code that I was duplicating for ASP.NET and SignalR and I decided to rewrite it as OWIN middleware to remove this duplication.
Once I was running it I noticed that HttpContext.Current.Session
was null, and I didn't see any session object on the IOwinContext
that my middleware has.
Is it possible to access the http session from OWIN?
回答1:
Yes, but it's quite a hack. It also won't work with SignalR because SignalR MUST run before session is acquired to prevent long session locks.
Do this to enable session for any request:
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;
}
}
Then you can access the session with either HttpContext.Current.Session
or
HttpContextBase httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
回答2:
This answer is a remix from the initial answer, so the gist of it should be attributed to @Tratcher. It's different enough though to post it seperately instead of suggesting an edit.
Supposing you want to make a small OWIN app for basic testing purposes (e.g. as a stub/fake for a bigger API when doing integration tests), including a slightly hakish way of using session state would work just fine.
First up, you need these:
using Microsoft.Owin;
using Microsoft.Owin.Extensions;
using Owin;
With those you can create a helper method:
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);
}
You could also create that as an extension method as the original answer did.
Note that if you don't use the UseStageMarker
you would encounter this error:
Server Error in '/' Application.
'HttpContext.SetSessionStateBehavior' can only be invoked before 'HttpApplication.AcquireRequestState' event is raised.
In any case, with the above you can now use HttpContext in your OWIN app like this:
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);
}
});
}
If you fire up IIS Express with this little app you'll first get:
No data in session state yet.
Then if you go to http://localhost:12345/write
you'll get:
Wrote to session state!
Then if you go back / go to any other url on that host you'll get:
11/4/2015 10:28:22 AM
Or something similar.
来源:https://stackoverflow.com/questions/23565543/can-owin-middleware-use-the-http-session