我在ASP.Net MVC中创建一个ActionResult来提供图像。启用会话状态后,IIS将一次只处理来自同一用户的一个请求。 (这不仅适用于MVC。)
因此,在具有多个图像回调此Action的页面上,一次只能处理一个图像请求。这是同步的。
我希望这个图像Action是异步的 - 我希望每次执行多个图像请求而不需要完成前一个。 (如果图像只是静态文件,IIS会以这种方式为它们提供服务。)
因此,我想仅针对该Action的调用禁用Session,或者指定某些请求没有Session状态。任何人都知道如何在MVC中完成这项工作?谢谢!
答案 0 :(得分:55)
如果有人遇到我所在的情况,你的图像控制器实际上只需要对会话进行只读访问,你可以将SessionState属性放在你的控制器上
[SessionState(SessionStateBehavior.ReadOnly)]
有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/system.web.mvc.sessionstateattribute.aspx。
答案 1 :(得分:36)
为什么不实现RouteHandler
?
这是交易 - IRouteHandler
有一种方法 - GetHttpHandler
。当您向控制器发出ASP.Net MVC请求时,默认情况下,路由引擎通过创建MvcRouteHandler
的新实例来处理请求,该实例返回MvcHandler
。 MvcHandler
是IHttpHandler
的一个实现,它标有(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> 创建自定义属性
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)
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)]
装饰控制器您想要将禁用的声明重新编码到该控制器