Отключить состояние сеанса для запроса в ASP.Net MVC

Я создаю ActionResult в ASP.Net MVC для обслуживания изображений. При включенном состоянии сеанса IIS будет обрабатывать только один запрос от одного и того же пользователя. (Это верно не только в MVC.)

Таким образом, на странице с несколькими изображениями, обращающимися к этому действию, одновременно может обрабатываться только один запрос изображения. Это синхронно.

Мне бы хотелось, чтобы это изображение было асинхронным - я бы хотел, чтобы каждый запрос на изображение выполнялся без необходимости выполнения предыдущего. (Если бы изображения были просто статическими файлами, IIS обслуживал бы их таким образом.)

Итак, я хотел бы отключить сеанс только для вызовов этого действия или указать, что определенные запросы не имеют состояния сеанса. Кто-нибудь знает, как это делается в MVC? Спасибо!

9 ответов

Решение

Вместо того, чтобы реализовать фильтр действий для этого, почему бы вам не реализовать RouteHandler?

Вот сделка - IRouteHandler имеет один метод - GetHttpHandler, Когда вы делаете ASP.Net MVC запрос к контроллеру, по умолчанию механизм маршрутизации обрабатывает запрос, создавая новый экземпляр MvcRouteHandler, который возвращает MvcHandler, MvcHandler это реализация IHttpHandler который отмечен (сюрприз!) IRequiresSessionState интерфейс. Вот почему обычный запрос использует Session.

Если вы следите за моим сообщением в блоге о том, как реализовать кастом RouteHandler (вместо использования MvcRouteHandler) для обслуживания изображений - вы можете пропустить возврат сеанса с тегами IHttpHandler,

Это должно освободить IIS от навязывания вам синхронности. Это также, вероятно, будет более производительным, поскольку пропускает все уровни кода MVC, связанные с фильтрами.

Если кто-то находится в ситуации, в которой я находился, когда вашему контроллеру изображений действительно необходим доступ только для чтения к сеансу, вы можете поместить атрибут SessionState на свой контроллер

[SessionState(SessionStateBehavior.ReadOnly)]

См. http://msdn.microsoft.com/en-us/library/system.web.mvc.sessionstateattribute.aspx для получения дополнительной информации.

Благодаря /questions/17754767/vklyuchit-otklyuchit-sostoyanie-seansa-dlya-kontrollera-metoda-dejstviya/17754776#17754776

Я также сталкивался с той же проблемой, и после выполнения НИОКР эта ссылка работала для меня. Ссылка: https://techatfingers.wordpress.com/2016/06/14/session-state-on-action/

  1. Создать собственный атрибут
  2. Переопределите метод "GetControllerSessionBehavior", представленный в классе DefaultControllerFactory.
  3. Зарегистрируйте это в global.aspx

1> Создать пользовательский атрибут

public sealed class ActionSessionStateAttribute : Attribute
    {
            public SessionStateBehavior SessionBehavior { get; private set; }          
            public ActionSessionStateAttribute(SessionStateBehavior sessionBehavior)
            {
                SessionBehavior = sessioBehavior;
            }
    }

2. Переопределить

public class SessionControllerFactory : DefaultControllerFactory
{       
        protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
        {
            if (controllerType == null)
                return SessionStateBehavior.Default;

            var actionName = requestContext.RouteData.Values["action"].ToString();
            Type typeOfRequest=requestContext.HttpContext.Request.RequestType.ToLower() =="get"?typeof(HttpGetAttribute):typeof(HttpPostAttribute);
            // [Line1]
            var cntMethods = controllerType.GetMethods()
                   .Where(m => 
                    m.Name == actionName &&
                    (  (  typeOfRequest == typeof(HttpPostAttribute) && 
                          m.CustomAttributes.Where(a => a.AttributeType == typeOfRequest).Count()>0
                       )
                       ||
                       (  typeOfRequest == typeof(HttpGetAttribute) &&
                          m.CustomAttributes.Where(a => a.AttributeType == typeof(HttpPostAttribute)).Count() == 0
                       )
                    )
                );
            MethodInfo actionMethodInfo = actionMethodInfo = cntMethods != null && cntMethods.Count() == 1 ? cntMethods.ElementAt(0):null;
            if (actionMethodInfo != null)
            {
                var sessionStateAttr = actionMethodInfo.GetCustomAttributes(typeof(ActionSessionStateAttribute), false)
                                    .OfType<ActionSessionStateAttribute>()
                                    .FirstOrDefault();

                if (sessionStateAttr != null)
                {
                    return sessionStateAttr.Behavior;
                }
            }
            return base.GetControllerSessionBehavior(requestContext, controllerType);
 }

3. Зарегистрируйте класс в Global.asax

public class MvcApplication : System.Web.HttpApplication
 {
        protected void Application_Start()
        {
            // --- other code ---
            ControllerBuilder.Current.SetControllerFactory(typeof(SessionControllerFactory));
        }
}

Попробуйте отправить изображения из другого домена. Так что-то вроде images.mysite.com.

Это даст вам два преимущества: во-первых, сеансы отслеживаются с помощью cookie, поэтому на images.mysite.com не будет cookie. Во-вторых, это даст вам еще два одновременных запроса на получение изображений.

Рассматривали ли вы настройку HttpHandler для обслуживания ваших изображений?

Атрибут SessionState очень полезен, если вы используете mvc3. Как этого добиться с помощью mvc2, нужно немного больше кодирования.

Идея состоит в том, чтобы сообщить asp.net, что конкретный запрос не будет использовать объект сеанса.

Итак, создайте собственный обработчик маршрута для конкретных запросов

public class CustomRouteHandler : IRouteHandler
    {
        public System.Web.IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            requestContext.HttpContext.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.ReadOnly);
            return new MvcHandler(requestContext);
        }
    }

Перечисление SessionStateBehavior имеет 4 члена, для получения асинхронного поведения следует использовать режимы "отключен" или "только для чтения".

После создания этого пользовательского обработчика маршрута убедитесь, что ваши конкретные запросы проходят через этот обработчик. Это можно сделать путем определения новых маршрутов в Global.asax

routes.Add("Default", new Route(
                "{controller}/{action}",
               new RouteValueDictionary(new { controller = "Home", action = "Index"}),
               new CustomRouteHandler()
                ));

При добавлении этого маршрута все ваши запросы будут обрабатываться вашим классом обработчика пользовательских маршрутов. Вы можете сделать это конкретным, определив различные маршруты.

Измените DefaultCOntrollerFactory на пользовательский класс ControllerFactory. По умолчанию Controller.TempDataProvider использует SessionStateTempDataProvider. Вы можете изменить это.

1. Установите web.config / system.web / sessionState: mode = "Off".

2. создать класс DictionaryTempDataProvider.

  public class DictionaryTempDataProvider : ITempDataProvider
  {
    public IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
    {
      return new Dictionary<string, object>();
    }

    public void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
    {
    }
  }

3.Создать DictionaryTempDataControllerFactory

  public class DictionaryTempDataControllerFactory : DefaultControllerFactory
  {
    public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
      var controller = base.CreateController(requestContext, controllerName) as Controller;
      if (controller!=null)
        controller.TempDataProvider = new DictionaryTempDataProvider();

      return controller;
    }
  }

4. В global.asax.cs установите событие Apprication_Start для DictionaryTempDataControllerFactory.

protected void Application_Start()
{
  RegisterRoutes(RouteTable.Routes);

  ControllerBuilder.Current.SetControllerFactory(
   new DictionaryTempDataControllerFactory()
  );
}

Создать новый контроллер

Украсить контроллер с помощью [SessionState(SessionStateBehavior.Disabled)]

Код рефакторинга, для которого вы хотите, чтобы указанный контроллер был отключен для этого контроллера

На нашем сервере IIS даже не знает о сессиях - это стек ASP.NET, который обрабатывает один запрос за сессию за раз. Статические файлы, такие как изображения, никогда не затрагиваются.

Возможно ли, что ваше приложение ASP.NET обслуживает файлы вместо IIS?

Я хотел бы поделиться своим решением для отключения сеанса ASP.NET для определенного запроса (в моем случае службы WCF) с использованием HttpModule:

      public class AspNetSessionFilterModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PostMapRequestHandler += OnPostMapRequestHandler;
    }

    private void OnPostMapRequestHandler(object sender, EventArgs e)
    {
        var context = (sender as HttpApplication).Context;
        DisableSessionForSomeRequests(context);
    }

    private void DisableSessionForSomeRequests(HttpContext context)
    {
        if ("~/Services/MyService.svc".Equals(context.Request.AppRelativeCurrentExecutionFilePath, StringComparison.InvariantCultureIgnoreCase))
        {
            context.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Disabled);
        }
    }

    public void Dispose()
    { }
}
Другие вопросы по тегам