2009-09-23 31 views
38

Tôi đang tạo ActionResult trong ASP.Net MVC để phân phát hình ảnh. Với trạng thái Session được kích hoạt, IIS sẽ chỉ xử lý một yêu cầu tại một thời điểm từ cùng một người dùng. (Điều này đúng không chỉ trong MVC.)Tắt trạng thái phiên cho mỗi yêu cầu trong ASP.Net MVC

Do đó, trên một trang có nhiều hình ảnh gọi lại cho Hành động này, chỉ có thể xử lý một yêu cầu hình ảnh cùng một lúc. Nó đồng bộ.

Tôi muốn hình ảnh này Hành động không đồng bộ - Tôi muốn nhiều yêu cầu hình ảnh cho mỗi lần thực thi mà không cần yêu cầu trước đó để hoàn thành. (Nếu hình ảnh chỉ là các tệp tĩnh, IIS sẽ phục vụ chúng theo cách này.)

Vì vậy, tôi muốn tắt Phiên chỉ dành cho các cuộc gọi đến Hành động đó hoặc để chỉ định một số yêu cầu nhất định không có trạng thái Phiên. Bất cứ ai biết làm thế nào điều này được thực hiện trong MVC? Cảm ơn!

+0

http://stackoverflow.com/questions/2250940/enable-disable-session-state-per-controller-action-method –

Trả lời

33

Thay vì triển khai bộ lọc hành động cho việc này, tại sao bạn không triển khai RouteHandler?

Đây là giao dịch - IRouteHandler có một phương thức - GetHttpHandler. Khi bạn thực hiện một yêu cầu ASP.Net MVC cho bộ điều khiển, theo mặc định công cụ định tuyến xử lý yêu cầu bằng cách tạo một phiên bản mới MvcRouteHandler, trả về một MvcHandler. MvcHandler là triển khai IHttpHandler được đánh dấu bằng giao diện (bất ngờ!) IRequiresSessionState. Đây là lý do tại sao một yêu cầu bình thường sử dụng Session.

Nếu you follow my blog post về cách triển khai RouteHandler tùy chỉnh (thay vì sử dụng MvcRouteHandler) để phân phát hình ảnh - bạn có thể bỏ qua trả về phiên được gắn thẻ IHttpHandler.

Điều này sẽ miễn phí IIS từ áp đặt đồng bộ trên bạn. Nó cũng có thể có hiệu suất cao hơn vì nó bỏ qua tất cả các lớp của mã MVC xử lý các bộ lọc.

+0

wow, bài đăng trên blog tuyệt vời. có vẻ như bằng cách sử dụng một bộ điều khiển MVC tiêu chuẩn, phụ thuộc phiên sẽ là không thể tránh khỏi ..? –

+0

Vâng. May mắn thay, họ đã làm MVC càng mở rộng càng tốt vì vậy nó không phải là quá nhiều công việc để bỏ qua bất cứ điều gì bạn không thích. – womp

+0

Cảm ơn! Đó là một nỗi đau cho tôi khi tôi tắt phiên và hành động trở lại hình ảnh đã được trộn kết quả (có thể hình ảnh trên trang bằng cách sử dụng hành động này). –

6

Thử phân phối hình ảnh từ một tên miền khác. Vì vậy, một cái gì đó như images.mysite.com.

Điều này sẽ cung cấp cho bạn hai lợi ích: Một, phiên được theo dõi bởi một cookie, vì vậy images.mysite.com sẽ không có cookie. Hai, nó sẽ cung cấp cho bạn thêm hai yêu cầu đồng thời để truy xuất hình ảnh.

Bạn đã cân nhắc thiết lập HttpHandler để phục vụ hình ảnh của mình chưa?

+0

đó là một ý tưởng thú vị.tôi có thể vô hiệu hóa trạng thái phiên trên bảng cho ứng dụng/trang web đó. tôi vẫn muốn biết nếu điều kiện cho mỗi yêu cầu/hành động là có thể, quá. –

1

Trên máy chủ của chúng tôi, IIS thậm chí không biết về phiên - đó là ngăn xếp ASP.NET xử lý một yêu cầu mỗi phiên một lúc. Các tệp tĩnh, như hình ảnh, không bao giờ bị ảnh hưởng.

Có thể ứng dụng ASP.NET của bạn đang phân phát các tệp thay vì IIS không?

+0

đó là chính xác, đó là ASP thực thi các công cụ phiên/đồng bộ, chứ không phải bản thân IIS. giải pháp là để đi trước đó trong các đường ống như womp mô tả ở trên. –

3

Thay đổi DefaultCOntrollerFactory thành lớp ControllerFactory tùy chỉnh. Controller.TempDataProvider mặc định sử dụng SessionStateTempDataProvider. Bạn có thể thay đổi nó.

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

2.tạo từ điểnTempDataProvider 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.Tạo 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 tổ chức sự kiện DictionaryTempDataControllerFactory.

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

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

Nếu ai ở trong hoàn cảnh tôi đang ở, nơi điều khiển hình ảnh của bạn thực sự cần chỉ đọc truy cập vào phiên giao dịch, bạn có thể đặt thuộc tính sessionState trên bộ điều khiển của bạn

[SessionState(SessionStateBehavior.ReadOnly)] 

Xem http://msdn.microsoft.com/en-us/library/system.web.mvc.sessionstateattribute.aspx để biết thêm thông tin.

Nhờ https://stackoverflow.com/a/4235006/372926

+0

Đó là một thuộc tính tuyệt vời, tuy nhiên nó chỉ hoạt động trong MVC3 + – Kousha

+2

Thuộc tính phiên cấp hành động https://technologyatfingertips.wordpress.com/2016/06/14/session-state-on-action/ – SeeTheC

4

Thuộc tính SessionState khá hữu ích nếu bạn sử dụng mvc3. Làm thế nào để đạt được điều này với mvc2 cần mã hóa nhiều hơn một chút.

Ý tưởng là nói với asp.net rằng yêu cầu cụ thể sẽ không sử dụng đối tượng phiên.

Vì vậy, Tạo một handler đường tùy chỉnh cho các yêu cầu cụ thể

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 có 4 thành viên, bạn nên sử dụng "tàn tật" hoặc "chỉ đọc" chế độ để có được hành vi async.

Sau khi tạo trình xử lý tuyến đường tùy chỉnh này, hãy đảm bảo rằng các yêu cầu cụ thể của bạn trải qua trình xử lý này. Điều này có thể được thực hiện thông qua việc xác định các tuyến mới tại Global.asax

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

Thêm tuyến này làm cho tất cả yêu cầu của bạn được xử lý bởi lớp xử lý tuyến tùy chỉnh của bạn. Bạn có thể làm cho nó cụ thể bằng cách xác định các tuyến đường khác nhau.

+1

Giải pháp của bạn là dành cho mvc 3+ , bạn sẽ chia sẻ làm thế nào để làm trong mvc 2 khi bạn viết rằng nó có thể đạt được trong mvc 2 w/ít mã hóa hơn? – adardesign

+0

Chỉ trong trường hợp nó có giá trị cho bất cứ ai, điều này vẫn làm việc cho tôi trong MVC 5.2.3.0. Tuy nhiên tôi đã phải thay đổi 'SessionStateBehaviour' thành' Disabled' và thêm route trong 'RouteConfig.cs' (phương thức' RegisterRoutes (RouteCollection) ') thay vì trong' Global.asax'. – MeterLongCat

0

Tạo điều khiển mới

Trang trí khiển với [sessionState (SessionStateBehavior.Disabled)]

đang

Refactor bạn muốn seesion tuyên bố vô hiệu hoá cho đến bộ điều khiển mà

+0

không phải lúc nào cũng khả thi cho ứng dụng lớn hơn – SeeTheC

3

Tôi cũng đã xem qua cùng một vấn đề và sau đang làm R & D liên kết này hoạt động với tôi Tham chiếu: https://techatfingers.wordpress.com/2016/06/14/session-state-on-action/

  1. Tạo thuộc tính tùy chỉnh
  2. Ghi đè phương thức "GetControllerSessionBehavior" có trong lớp DefaultControllerFactory.
  3. đăng ký nó trong global.aspx

1>Tạo tùy chỉnh thuộc tính

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. Đăng ký lớp học trong Global.asax

public class MvcApplication : System.Web.HttpApplication 
{ 
     protected void Application_Start() 
     { 
      // --- other code --- 
      ControllerBuilder.Current.SetControllerFactory(typeof(SessionControllerFactory)); 
     } 
} 
Các vấn đề liên quan