Can OWIN middleware use the http session?

空扰寡人 提交于 2019-12-18 02:00:51

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!