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

发布于 2024-08-05 17:33:58 字数 295 浏览 2 评论 0原文

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

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

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

因此,我想仅针对对该操作的调用禁用会话,或者指定某些请求没有会话状态。有人知道 MVC 中是如何实现的吗?谢谢!

I am creating an ActionResult in ASP.Net MVC to serve images. With Session state enabled, IIS will only handle one request at a time from the same user. (This is true not just in MVC.)

Therefore, on a page with multiple images calling back to this Action, only one image request can be handled at a time. It's synchronous.

I'd like this image Action to be asynchronous -- I'd like multiple image requests to each execute without needing the previous one to complete. (If the images were just static files, IIS would serve them up this way.)

So, I'd like to disable Session just for calls to that Action, or to specify that certain requests do not have Session state. Anyone know how this is done in MVC? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

〆凄凉。 2024-08-12 17:33:58

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

[SessionState(SessionStateBehavior.ReadOnly)]

请参阅 http://msdn.microsoft.com/en-us/library/system.web.mvc.sessionstateattribute.aspx 的更多信息。

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

If anyone is in the situation I was in, where your image controller actually needs read only access to the session, you can put the SessionState attribute on your controller

[SessionState(SessionStateBehavior.ReadOnly)]

See http://msdn.microsoft.com/en-us/library/system.web.mvc.sessionstateattribute.aspx for more info.

Thanks to https://stackoverflow.com/a/4235006/372926

菩提树下叶撕阳。 2024-08-12 17:33:58

与其实现一个动作过滤器,为什么不实现一个 RouteHandler 呢?

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

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

这应该使 IIS 不再强加同步性。它还可能会提高性能,因为它跳过了处理过滤器的 MVC 代码的所有层。

Rather than implementing an action filter for this, why don't you implement a RouteHandler?

Here's the deal - IRouteHandler has one method - GetHttpHandler. When you make an ASP.Net MVC request to a controller, by default the routing engine handles the request by creating a new instance of MvcRouteHandler, which returns an MvcHandler. MvcHandler is an implementation of IHttpHandler which is marked with the (surprise!) IRequiresSessionState interface. This is why a normal request uses Session.

If you follow my blog post on how to implement a custom RouteHandler (instead of using MvcRouteHandler) for serving up images - you can skip returning a session-tagged IHttpHandler.

This should free IIS from imposing synchronicity on you. It would also likely be more performant because it's skipping all the layers of the MVC code dealing with filters.

深府石板幽径 2024-08-12 17:33:58

我也遇到了同样的问题,在进行研发之后,这个链接对我有用
参考:
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));
        }
}

I also came across the same problem and after doing R&D this link worked for me
Reference:
https://techatfingers.wordpress.com/2016/06/14/session-state-on-action/

  1. Create custom Attribute
  2. Override the “GetControllerSessionBehavior” method present in class DefaultControllerFactory.
  3. Register it in global.aspx

1> Create custom Attribute

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

2. Override

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. Register class in Global.asax

public class MvcApplication : System.Web.HttpApplication
 {
        protected void Application_Start()
        {
            // --- other code ---
            ControllerBuilder.Current.SetControllerFactory(typeof(SessionControllerFactory));
        }
}
回忆那么伤 2024-08-12 17:33:58

尝试从另一个域提供图像。比如 images.mysite.com。

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

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

Try serving the images from another domain. So something like images.mysite.com.

This will provide you two benefits: One, sessions are tracked by a cookie, so images.mysite.com won't have the cookie. Two, it will give you an additional two concurrent requests to retrieve images.

Have you considered setting up a HttpHandler to serve up your images?

阳光①夏 2024-08-12 17:33:58

如果你使用 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()
                ));

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

SessionState attribute is quite helpful if u use mvc3. How to achieve this with mvc2 needs a little more coding.

Idea is to tell the asp.net that specific request wont use session object.

So, Create a custom route handler for specific requests

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

SessionStateBehavior enum has 4 members, you should use "disabled" or "readonly" modes to get async behavior.

After creating this custom route handler, be sure that your specific requests goes through this handler. This can be done via defining new routes at Global.asax

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

Adding this route makes all your requests to be handled by your custom route handler class. You can make it specific by defining different routes.

知足的幸福 2024-08-12 17:33:58

将 DefaultCOntrollerFactory 更改为自定义 ControllerFactory 类。默认Controller.TempDataProvider使用SessionStateTempDataProvider。你可以改变它。

1.设置web.config/system.web/sessionState:mode=“关闭”。

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

Change DefaultCOntrollerFactory to custom ControllerFactory class. Default Controller.TempDataProvider use SessionStateTempDataProvider. you can change it.

1.Set web.config/system.web/sessionState:mode="Off".

2.create DictionaryTempDataProvider class.

  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.In global.asax.cs Apprication_Start event set DictionaryTempDataControllerFactory.

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

  ControllerBuilder.Current.SetControllerFactory(
   new DictionaryTempDataControllerFactory()
  );
}
长安忆 2024-08-12 17:33:58

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

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

On our server, IIS doesn't even know about sessions - it's the ASP.NET stack that handles one request per session at a time. Static files, like images, are never affected.

Is it possible that your ASP.NET app is serving the files instead of IIS?

蓬勃野心 2024-08-12 17:33:58

创建新的控制器

使用 [SessionState(SessionStateBehavior.Disabled)]

重构您想要为该控制器禁用的看到的代码

Create new Controller

Decorate controler with [SessionState(SessionStateBehavior.Disabled)]

Refactor code you want seesion stated disabled for to that controller

潇烟暮雨 2024-08-12 17:33:58

我想分享我的解决方案,使用 HttpModule 禁用特定请求(在我的例子中是 WCF 服务)的 ASP.NET 会话:

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()
    { }
}

I would to share my solution for disable ASP.NET Session for an specific request (in my case, a WCF Service) using an 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()
    { }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文