web-dev-qa-db-ja.com

ASP.Net MVCで要求ごとのセッション状態を無効にする

画像を提供するためにASP.Net MVCでActionResultを作成しています。セッション状態を有効にすると、IISは、同じユーザーからの一度に1つの要求のみを処理します(これはMVCだけではありません)。

したがって、このアクションにコールバックする複数の画像があるページでは、一度に1つの画像リクエストしか処理できません。同期です。

この画像のアクションを非同期にしたい-前のものを完了する必要なく、各実行に対する複数の画像リクエストが欲しい。 (画像が静的ファイルのみの場合、IISはこの方法で画像を提供します。)

そのため、そのアクションの呼び出しに対してのみセッションを無効にするか、特定のリクエストにセッション状態がないことを指定します。誰もがこれがMVCでどのように行われるか知っていますか?ありがとう!

45
Matt Sherman

これにアクションフィルターを実装するのではなく、RouteHandlerを実装してみませんか?

これが取引です-IRouteHandlerには1つのメソッド-GetHttpHandlerがあります。コントローラーにASP.Net MVC要求を行うと、デフォルトでは、ルーティングエンジンはMvcRouteHandlerの新しいインスタンスを作成して要求を処理し、MvcHandlerを返します。 MvcHandlerIHttpHandlerの実装であり、(驚き!)IRequiresSessionStateインターフェースでマークされています。これが通常のリクエストがセッションを使用する理由です。

画像を提供するためにカスタムRouteHandlerを実装する方法について あなたは私のブログ投稿に従います の場合(MvcRouteHandlerを使用する代わりに)-セッションのタグが付けられたIHttpHandlerを返すのをスキップできます。

これにより、IIS=同期を強制する必要がなくなります。フィルターを処理するMVCコードのすべてのレイヤーがスキップされるため、パフォーマンスが向上する可能性があります。

36
womp

イメージコントローラーが実際にセッションへの読み取り専用アクセスを必要とする状況に誰かがいる場合は、コントローラーにSessionState属性を設定できます

[SessionState(SessionStateBehavior.ReadOnly)]

詳細は http://msdn.Microsoft.com/en-us/library/system.web.mvc.sessionstateattribute.aspx を参照してください。

おかげで https://stackoverflow.com/a/4235006/372926

55
SamStephens

私も同じ問題に遭遇し、R&Dを行った後、このリンクは私のために機能しました参照: 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));
        }
}
8
SeeTheC

別のドメインから画像を提供してみてください。つまり、images.mysite.comのようなものです。

これには2つの利点があります。1つ目は、セッションがCookieによって追跡されるため、images.mysite.comにCookieがないことです。 2つ目は、画像を取得するための追加の2つの同時リクエストを提供します。

画像を提供するためにHttpHandlerを設定することを検討しましたか?

6
Chuck Conway

SessionState属性は、mvc3を使用する場合に非常に役立ちます。 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
Serdar

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

新しいコントローラーを作成する

[SessionState(SessionStateBehavior.Disabled)]でコントローラーを装飾する

そのコントローラーに対して参照を無効にしたいリファクタリングコード

1
Diemar

私たちのサーバーでは、IISはセッションについてさえ知りません。セッションごとに一度に1つの要求を処理するのはASP.NETスタックです。画像などの静的ファイルは影響を受けません。

ASP.NETアプリがIISではなくファイルを提供している可能性はありますか?

1
orip