Может ли промежуточное ПО OWIN использовать сеанс http?
У меня было немного кода, который я дублировал для ASP.NET и SignalR, и я решил переписать его как промежуточное ПО OWIN, чтобы удалить это дублирование.
Как только я запускал его, я заметил, что HttpContext.Current.Session
имеет значение NULL, и я не видел объект сеанса на IOwinContext
, который имеет мое промежуточное ПО.
Можно ли получить доступ к сеансу http из OWIN?
Ответы
Ответ 1
Да, но это довольно взломать. Он также не будет работать с 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);
Ответ 2
Этот ответ является ремиксом из начального ответа, поэтому его суть следует отнести к @Tratcher. Это достаточно различно, хотя публиковать его отдельно, вместо того, чтобы предлагать редактирование.
Предположим, что вы хотите сделать небольшое приложение OWIN для базовых целей тестирования (например, в качестве заглушки/подделки для большего API при выполнении интеграционных тестов), в том числе немного хакильный способ использования состояния сеанса, будет работать нормально.
Прежде всего, вам понадобятся:
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 будет поднято.
В любом случае, с приведенным выше, вы теперь можете использовать HttpContext в своем приложении OWIN следующим образом:
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
, вы получите:
Написал состояние сеанса!
Затем, если вы вернетесь/зайдите на любой другой URL-адрес этого хоста, вы получите:
11/4/2015 10:28:22 AM
Или что-то подобное.