Как я могу реализовать API WEB-интерфейса для определенных контроллеров?
Я создаю несколько контроллеров WEB API 2, которым необходимо знать сеанс. Ранее я сделал это, добавив
/// <summary>
/// Application_s the post authorize request.
/// </summary>
protected void Application_PostAuthorizeRequest()
{
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
Однако у нас есть API-контроллеры в решении для других критически важных бизнес-узлов сайта, которые были высоко оптимизированы и возвращают ответы около 500 мс, и если он включен, он постоянно увеличивается до 2 секунд. Эти контроллеры не нуждаются в осведомленности о сеансе.
Нам нужны только определенные контроллеры, предоставляющие доступ к сеансу, я прочитал эту статью http://www.codeproject.com/Tips/513522/Providing-session-state-in-ASP-NET-WebAPI и думал, если можно добавить другую маршрут с осознанием сеанса, но при сопоставлении маршрутов не существует свойства RouteHandler.
Есть ли у кого-нибудь идеи?
Ответы
Ответ 1
Я придумал решение, которое сработало. Я добавил второй маршрут во время регистрации маршрутов, например
config.Routes.MapHttpRoute(
name: "DefaultSessionApi",
routeTemplate: "sessionapi/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
Тогда в global.asax.cs у меня есть
/// <summary>
/// Application_s the post authorize request.
/// </summary>
protected void Application_PostAuthorizeRequest()
{
if (HttpContext.Current.Request.FilePath.StartsWith("/sessionapi"))
{
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
}
Это позволяет любому контроллеру запрашивать информацию о сеансе или без него, поэтому решение моей проблемы.
Мое решение немного опрятно с константами конфигурации и тому подобное, но этот вышеприведенный код является примером.
Ответ 2
Имейте в виду, что работа с SessionStateBehavior.Required оказывает значительное влияние, и только часть ваших маршрутов на самом деле требует доступа на запись к сеансу. Хуже всего то, что только один запрос на пользователя будет обработан сразу, потому что сеанс должен быть заблокирован.
Как говорится, есть способ работать с сеансами по-разному в зависимости от маршрута.
Вы можете использовать IHttpRoute.DataTokens, чтобы добавить настраиваемые поля к вашим маршрутам.
Я создал небольшой класс расширения для установки SessionStateBehavior для каждого маршрута отдельно:
public static class SessionHelper
{
private static SessionStateBehavior GetSessionStateBehavior(IDictionary<string, object> dataTokens)
{
return dataTokens.ContainsKey("SessionStateBehavior") ? (SessionStateBehavior)dataTokens["SessionStateBehavior"] : SessionStateBehavior.Default;
}
public static SessionStateBehavior GetSessionStateBehavior(this IHttpRoute route)
{
return GetSessionStateBehavior(route.DataTokens);
}
public static SessionStateBehavior GetSessionStateBehavior(this RouteData routeData)
{
return GetSessionStateBehavior(routeData.DataTokens);
}
public static void SetSessionStateBehavior(this IHttpRoute route, SessionStateBehavior behavior)
{
route.DataTokens["SessionStateBehavior"] = behavior;
}
public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, SessionStateBehavior behavior)
{
return MapHttpRoute(routes, name, routeTemplate, defaults, null, behavior);
}
public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints, SessionStateBehavior behavior)
{
var route = routes.CreateRoute(routeTemplate, defaults, constraints);
SetSessionStateBehavior(route, behavior);
routes.Add(name, route);
return route;
}
}
При настройке маршрута вы можете использовать расширение для определения определенного поведения состояния сеанса:
config.Routes.MapHttpRoute(
"DefaultSessionApi",
"api/{controller}/{id}",
new { id = RouteParameter.Optional },
SessionStateBehavior.ReadOnly);
config.Routes.MapHttpRoute(
"WriteStuffToSession",
"api/writestufftosession",
null,
SessionStateBehavior.Required);
Затем в PostAuthorizeRequest вы можете проанализировать свой маршрут и соответственно установить SessionStateBehavior:
protected void Application_PostAuthorizeRequest()
{
var context = new HttpContextWrapper(HttpContext.Current);
var path = context.Request.AppRelativeCurrentExecutionFilePath;
if (path == null || !path.StartsWith("~/api"))
{
return;
}
var routeData = RouteTable.Routes.GetRouteData(context);
if (routeData != null)
{
context.SetSessionStateBehavior(routeData.GetSessionStateBehavior());
}
}