3

MVC3 は、[SessionState(SessionStateBehavior.Disabled)]属性を使用してセッションレス コントローラーを作成する良い機会を追加しました。これは素晴らしいことですが、コントローラー メソッドごとにセッション状態を設定できず、条件によって有効にすることもできないため、柔軟性がありません。

認証されたユーザーのみ、またはその他のカスタム条件でセッション状態を有効にすることはできますか? つまり、PHP には優れた機能があります。 if (!isset($_SESSION)) session_start(); みたいなのが見つかると良いですね

4

2 に答える 2

4

デフォルトのコントローラーファクトリ、より具体的にはGetControllerSessionBehaviorメソッドをオーバーライドできます。

public class MyControllerFactory : DefaultControllerFactory
{
    protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            return SessionStateBehavior.Default;
        }

        if (requestContext.HttpContext.User.Identity.IsAuthenticated)
        {
            // enable session if there's an authenticated user
            return SessionStateBehavior.Required;
        }

        return SessionStateBehavior.Disabled;
    }
}

そしてApplication_Start、デフォルトのコントローラーファクトリをカスタムのものに置き換えます。

ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
于 2012-05-28T08:43:39.280 に答える
2

コントローラー メソッドごとにセッション状態を無効にする方法。このようなフローでも適切に機能します。

  1. セッションが有効な request メソッド
  2. セッションを無効にした request メソッド
  3. セッションが有効なリクエストメソッド - 値が保持されます (理由はわかりませんが、そうです)

      /// <summary>
      /// Enable session if there's an authenticated user or method in controller is marked with <see cref="SessionAttribute" /> or controller class is marked within <see cref="SessionAttribute" /> or <see cref="SessionStateAttribute" />
      /// </summary>
      public class AuthSessionControllerFactory : DefaultControllerFactory
      {
    
        protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
        {
          if ( controllerType == null ) return SessionStateBehavior.Default;
    
          return requestContext.HttpContext.User.Identity.IsAuthenticated
            ? SessionStateBehavior.Required
            : GetDefaultSessionBehavior( requestContext, controllerType );
        }
    
     private static readonly ConcurrentDictionary<string, SessionStateBehavior> _sessionStateCache = new ConcurrentDictionary<string, SessionStateBehavior>();
     protected SessionStateBehavior GetDefaultSessionBehavior(RequestContext requestContext, Type controllerType)
     {
      if ( !requestContext.RouteData.Values.Keys.Contains( "action" ) ) return SessionStateBehavior.Required;
      var act = requestContext.RouteData.Values["action"].ToString();
    
      return _sessionStateCache.GetOrAdd( controllerType + act,
        (type => {
          var typeCopy = controllerType;
    
          //get current action
          var methods = typeCopy.GetMethods().Where( m => m.Name == act ).ToArray();
          foreach (var method in methods) {
    
            //look for SessionAttribute on the method
            var attr = Attribute.GetCustomAttribute( method, typeof( SessionAttribute ), false );
            if ( attr != null ) return (( SessionAttribute )attr).Behavior;
    
    
            //support default SessionState behavior
            var controllerattr = typeCopy.GetCustomAttributes( typeof( SessionStateAttribute ), true )
              .OfType<SessionStateAttribute>().FirstOrDefault();
            if ( controllerattr == null ) 
            {
              var controllerattrCustom = typeCopy.GetCustomAttributes( typeof( SessionAttribute ), true )
                .OfType<SessionAttribute>().FirstOrDefault();
              if ( controllerattrCustom != null ) return controllerattrCustom.Behavior;
            } else
              return controllerattr.Behavior;
          }
          return SessionStateBehavior.Disabled;
    
        }) );
    }
    

    }

Application_Start()Global.asaxのメソッドに登録する

ControllerBuilder.Current.SetControllerFactory( new AuthUserSessionControllerFactory() );  

ここに SessionAttribute クラスがあります - MS の SessionStateAttribute のように見えます - 唯一の違いは、これがメソッドに許可されていることです

[AttributeUsage( AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true )]
  public sealed class SessionAttribute : Attribute
  {

    public SessionAttribute(SessionStateBehavior behavior)
    {
      Behavior = behavior;
    }

    public SessionStateBehavior Behavior { get; private set; }
  }
于 2012-05-28T11:42:58.190 に答える