51

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

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

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

所以,我想禁用会话只是为了调用该操作,或者指定某些请求没有会话状态。有人知道这是如何在 MVC 中完成的吗?谢谢!

4

8 回答 8

57

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

[SessionState(SessionStateBehavior.ReadOnly)]

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

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

于 2012-01-09T23:16:58.043 回答
37

与其为此实施一个动作过滤器,不如实施一个RouteHandler?

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

如果您关注我的博客文章,了解如何实现自定义RouteHandler(而不是使用 MvcRouteHandler)来提供图像 - 您可以跳过返回 session-tagged IHttpHandler

这应该使 IIS 免于对您强加同步性。它也可能会更高效,因为它跳过了处理过滤器的 MVC 代码的所有层。

于 2009-09-23T06:29:05.343 回答
9

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

  1. 创建自定义属性
  2. 覆盖类 DefaultControllerFactory 中的“GetControllerSessionBehavior”方法。
  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));
        }
}
于 2016-06-15T08:13:24.047 回答
7

尝试提供来自另一个域的图像。所以像 images.mysite.com 这样的东西。

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

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

于 2009-09-23T06:11:01.207 回答
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()
                ));

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

于 2012-02-11T16:38:47.290 回答
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.创建 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()
  );
}
于 2009-09-23T15:29:12.043 回答
1

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

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

于 2009-09-23T06:36:19.830 回答
1

创建新控制器

用 [SessionState(SessionStateBehavior.Disabled)] 装饰控制器

重构您希望对该控制器禁用的代码

于 2013-09-27T12:58:27.940 回答