21

ASP.NET MVC プロジェクトを開発しており、厳密に型指定されたセッション オブジェクトを使用したいと考えています。このオブジェクトを公開するために、次の Controller 派生クラスを実装しました。

public class StrongController<_T> : Controller
    where _T : new()
{
    public _T SessionObject
    {
        get
        {
            if (Session[typeof(_T).FullName] == null)
            {
                _T newsession = new _T();
                Session[typeof(_T).FullName] = newsession;
                return newsession;
            }
            else
                return (_T)Session[typeof(_T).FullName];
        }
    }

}

これにより、コントローラーごとにセッション オブジェクトを定義できます。これは、コントローラー分離の概念に沿ったものです。より良い/より「正しい」方法、おそらくMicrosoftによって公式にサポートされているものはありますか?

4

5 に答える 5

18

これにより、他のオブジェクトはこのオブジェクトにアクセスできなくなります (例: ActionFilter)。私はこのようにします:

public interface IUserDataStorage<T>
{
   T Access { get; set; }
}

public class HttpUserDataStorage<T>: IUserDataStorage<T>
  where T : class
{
  public T Access
  {
     get { return HttpContext.Current.Session[typeof(T).FullName] as T; }
     set { HttpContext.Current.Session[typeof(T).FullName] = value; }
  }
}

次に、コントローラーのコンストラクターに IUserDataStorage を挿入するか、ActionFilter 内で ServiceLocator.Current.GetInstance(typeof(IUserDataStorage<T>)) を使用します。

public class MyController: Controller
{
   // automatically passed by IoC container
   public MyController(IUserDataStorage<MyObject> objectData)
   {
   }
}

もちろん、すべてのコントローラーがこれを必要とする場合 (ICurrentUser など) には、代わりにプロパティ インジェクションを使用することもできます。

于 2009-11-10T20:55:17.583 に答える
5

これは、あなたが望むものにとってより良いかもしれません。セッションにアクセスできる拡張メソッドを作成するだけです。拡張メソッドの追加の利点は、コントローラーから継承する必要がなくなったり、そもそも必要のない依存関係を注入したりする必要がないことです。

public static class SessionExtensions {
  public static T Get<T>(this HttpSessionBase session, string key)  {
     var result;
     if (session.TryGetValue(key, out result))
     {
        return (T)result;
     }
     // or throw an exception, whatever you want.
     return default(T);
   }
 }


public class HomeController : Controller {
    public ActionResult Index() {
       //....

       var candy = Session.Get<Candy>("chocolate");

       return View(); 
    }

}
于 2013-02-05T18:33:32.727 に答える
2

はい、この質問が出されてから何年も経ちますが、これを行う他の方法があります...しかし、他の誰かが上記のアプローチを魅力的なワンストップショップに組み合わせたものを探している場合に備えて(少なくとも私のチームにアピールしたもの)そして私は...) これが私たちが使用するものです。

 public enum SessionKey { CurrentUser, CurrentMember, CurrentChart, CurrentAPIToken, MemberBanner }

 public static class SessionCache {

    public static T Get<T>(this HttpSessionStateBase session, SessionKey key)
    {
        var value = session[key.ToString()];
        return value == null ? default(T) : (T) value;
    }

    public static void Set<T>(this HttpSessionStateBase session, SessionKey key, T item)
    {
        session[key.ToString()] = item;
    }

    public static bool contains(this HttpSessionStateBase session, SessionKey key)
    {
        if (session[key.ToString()] != null)
            return true;
        return false;
    }

    public static void clearKey(this HttpSessionStateBase session, SessionKey key)
    {
        session[key.ToString()] = null;
    }
}

次に、コントローラーで、より厳密に型指定された方法でセッション変数を使用して処理を実行できます。

// get member
var currentMember = Session.Get<Member>(SessionKey.CurrentMember);
// set member
Session.Set<Member>(SessionKey.CurrentMember, currentMember);
// clear member
Session.ClearKey(SessionKey.CurrentMember);
// get member if in session
if (Session.Contains(SessionKey.CurrentMember))
{
     var current = Session.Get<Member>(SessionKey.CurrentMember);
}

これが誰かを助けることを願っています!

于 2017-01-19T17:34:06.337 に答える