在ASP.Net MVC中禁用每个请求的会话状态

时间:2009-09-23 06:07:55

标签: asp.net asp.net-mvc asynchronous session-state actionresult

我在ASP.Net MVC中创建一个ActionResult来提供图像。启用会话状态后,IIS将一次只处理来自同一用户的一个请求。 (这不仅适用于MVC。)

因此,在具有多个图像回调此Action的页面上,一次只能处理一个图像请求。这是同步的。

我希望这个图像Action是异步的 - 我希望每次执行多个图像请求而不需要完成前一个。 (如果图像只是静态文件,IIS会以这种方式为它们提供服务。)

因此,我想仅针对该Action的调用禁用Session,或者指定某些请求没有Session状态。任何人都知道如何在MVC中完成这项工作?谢谢!

8 个答案:

答案 0 :(得分:55)

如果有人遇到我所在的情况,你的图像控制器实际上只需要对会话进行只读访问,你可以将SessionState属性放在你的控制器上

[SessionState(SessionStateBehavior.ReadOnly)]

有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/system.web.mvc.sessionstateattribute.aspx

感谢https://stackoverflow.com/a/4235006/372926

答案 1 :(得分:36)

为什么不实现RouteHandler

,而不是为此实现动作过滤器

这是交易 - IRouteHandler有一种方法 - GetHttpHandler。当您向控制器发出ASP.Net MVC请求时,默认情况下,路由引擎通过创建MvcRouteHandler的新实例来处理请求,该实例返回MvcHandlerMvcHandlerIHttpHandler的一个实现,它标有(surprise!)IRequiresSessionState接口。这就是普通请求使用Session的原因。

如果you follow my blog post了解如何实现自定义RouteHandler(而不是使用MvcRouteHandler)来提供图片 - 您可以跳过返回会话标记的IHttpHandler

这应该可以让IIS免于同步。它也可能更具性能,因为它正在跳过处理过滤器的MVC代码的所有层。

答案 2 :(得分:8)

我也遇到了同样的问题,在做完R& D之后,这个链接对我有用 参考: https://techatfingers.wordpress.com/2016/06/14/session-state-on-action/

  1. 创建自定义属性
  2. 重写类DefaultControllerFactory中的“GetControllerSessionBehavior”方法。
  3. 在global.aspx中注册
  4. 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));
            }
    }
    

答案 3 :(得分:6)

尝试提供来自其他域的图片。像images.mysite.com这样的东西。

这将为您提供两个好处:一,会话由cookie跟踪,因此images.mysite.com将没有cookie。第二,它将为您提供额外的两个并发请求来检索图像。

您是否考虑过设置HttpHandler来提供图像?

答案 4 :(得分:5)

如果您使用mvc3,

SessionState属性非常有用。如何用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()
                ));

添加此路由会使您的所有请求由您的自定义路由处理程序类处理。您可以通过定义不同的路线使其具体化。

答案 5 :(得分:3)

将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.Create 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()
  );
}

答案 6 :(得分:1)

在我们的服务器上,IIS甚至不知道会话 - 它是ASP.NET堆栈,每次会话处理一个请求。静态文件(如图像)永远不会受到影响。

您的ASP.NET应用程序是否可能提供文件而不是IIS?

答案 7 :(得分:1)

创建新的控制器

使用[SessionState(SessionStateBehavior.Disabled)]

装饰控制器

您想要将禁用的声明重新编码到该控制器