web-dev-qa-db-ja.com

ASP.NET MVCのセッション変数

ユーザーが特定のリクエストを行って、Webサイト内の複数のWebページを閲覧できるWebアプリケーションを作成しています。ユーザーが入力するすべての情報は、作成したオブジェクトに保存されます。問題は、このオブジェクトにWebサイトの任意の部分からアクセスする必要があり、これを実現する最善の方法が本当にわからないことです。 1つの解決策はセッション変数を使用することですが、asp .net MVCでそれらを使用する方法がわかりません。そして、セッション変数をどこで宣言しますか?他の方法はありますか?

165
Draco

本当に物事がセッション状態に属しているかどうかを考えたいと思うでしょう。これは私自身が時々していることであり、全体に対するニースの強く型付けされたアプローチですが、セッションコンテキストに物を置くときには注意が必要です。あるユーザーに属しているという理由だけですべてがそこにあるべきではありません。

global.asaxでOnSessionStartイベントをフックします

void OnSessionStart(...)
{
    HttpContext.Current.Session.Add("__MySessionObject", new MySessionObject());
}

HttpContext.Currentプロパティ!= nullのコード内のどこからでも、そのオブジェクトを取得できます。これを拡張メソッドで行います。

public static MySessionObject GetMySessionObject(this HttpContext current)
{
    return current != null ? (MySessionObject)current.Session["__MySessionObject"] : null;
}

この方法でコードでできる

void OnLoad(...)
{
    var sessionObj = HttpContext.Current.GetMySessionObject();
    // do something with 'sessionObj'
}
123
John Leidegren

ここでの答えは正しいですが、ASP.NET MVC 3アプリに実装するのに苦労しました。コントローラーのSessionオブジェクトにアクセスしたかったのに、「オブジェクトエラーのインスタンスに設定されていないインスタンス」を取得し続けた理由がわかりませんでした。私が気づいたのは、次の操作を行ってセッションにアクセスしようとしたときにコントローラーでエラーが発生し続けたことです。これは、this.HttpContextがControllerオブジェクトの一部であるためです。

this.Session["blah"]
// or
this.HttpContext.Session["blah"]

ただし、System.Web名前空間の一部であるHttpContextが欲しかったのは、これが上記の回答でGlobal.asax.csでの使用が提案されているためです。そのため、次のことを明示的に行う必要がありました。

System.Web.HttpContext.Current.Session["blah"]

これは私を助けてくれました。この辺りですが、誰かの助けになることを願っています!

44
Tomasz Iniewicz

場所について「HTTPContext.Current.Session」が表示されるのが嫌いなので、シングルトンパターンを使用してセッション変数にアクセスします。これにより、強く型付けされたデータのバッグに簡単にアクセスできます。

[Serializable]
public sealed class SessionSingleton
{
    #region Singleton

    private const string SESSION_SINGLETON_NAME = "Singleton_502E69E5-668B-E011-951F-00155DF26207";

    private SessionSingleton()
    {

    }

    public static SessionSingleton Current
    {
        get
        {
            if ( HttpContext.Current.Session[SESSION_SINGLETON_NAME] == null )
            {
                HttpContext.Current.Session[SESSION_SINGLETON_NAME] = new SessionSingleton();
            }

            return HttpContext.Current.Session[SESSION_SINGLETON_NAME] as SessionSingleton;
        }
    }

    #endregion

    public string SessionVariable { get; set; }
    public string SessionVariable2 { get; set; }

    // ...

その後、どこからでもデータにアクセスできます。

SessionSingleton.Current.SessionVariable = "Hello, World!";
20
Dead.Rabit

Asp.net mvcを使用している場合、セッションにアクセスする簡単な方法を次に示します。

コントローラーから:

{Controller}.ControllerContext.HttpContext.Session["{name}"]

ビューから:

<%=Session["{name}"] %>

これは間違いなくセッション変数にアクセスする最良の方法ではありませんが、直接的な方法です。したがって、慎重に(できればラピッドプロトタイピング中に)使用し、適切になったらWrapper/ContainerとOnSessionStartを使用してください。

HTH

14
robertz

まあ、私見..

  1. ビュー/マスターページ内のセッションを参照しないでください
  2. sessionの使用を最小限に抑えます。 MVCは、このためにTempData objを提供します。これは、基本的にサーバーへの1回の旅行で存続するSessionです。

#1に関して、私はセッションオブジェクトが表すものにアクセスするプロパティを持つ強く型付けされたマスタービューを持っています....私のインスタンスでは、強く型付けされたマスタービューはジェネリックであり、強く型付けされたビューページに関して柔軟性があります

ViewMasterPage<AdminViewModel>

AdminViewModel
{
    SomeImportantObjectThatWasInSession ImportantObject
}

AdminViewModel<TModel> : AdminViewModel where TModel : class
{
   TModel Content
}

その後...

ViewPage<AdminViewModel<U>>
13
E Rolnicki

それを行うには3つの方法があります。

  1. HttpContext.Current.Sessionに直接アクセスできます

  2. HttpContextBaseをモックできます

  3. HttpContextBaseの拡張メソッドを作成します

私は3番目の方法を好む。

BaseControllerのHttpContextセッションメソッドの取得/設定とHttpContextBaseのモックによるGet/Setメソッドの作成

7

Asp.net mvcについては知りませんが、これは通常の.net Webサイトですべきことです。 asp.net mvcでも機能するはずです。

YourSessionClass obj=Session["key"] as YourSessionClass;
if(obj==null){
obj=new YourSessionClass();
Session["key"]=obj;
}

簡単にアクセスできるように、メソッド内にこれを配置します。 HTH

7
DotNET

みんなからのすばらしい答えですが、私は常にセッションに依存することに対して警告します。すばやく簡単に実行でき、もちろん動作しますが、すべての状況で素晴らしいとは限りません。

たとえば、ホスティングでセッションの使用が許可されていないシナリオに遭遇した場合、Webファームにいる場合、または共有SharePointアプリケーションの例です。

別のソリューションが必要な場合は、 IOC Container などの Castle Windsor を使用して、プロバイダークラスをラッパーとして作成し、クラスの1つのインスタンスを使用して、要求に応じて、リクエストまたはセッションのライフスタイルごとに。

IOCは、毎回同じインスタンスが返されるようにします。

もっと複雑です。単純なソリューションが必要な場合は、セッションを使用するだけです。

以下に、興味のない実装例をいくつか示します。

このメソッドを使用すると、次の行に沿ってプロバイダークラスを作成できます。

public class CustomClassProvider : ICustomClassProvider
{
    public CustomClassProvider(CustomClass customClass)
    { 
        CustomClass = customClass;
    }

    public string CustomClass { get; private set; }
}

そして、次のように登録します:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Register(
            Component.For<ICustomClassProvider>().UsingFactoryMethod(
                () => new CustomClassProvider(new CustomClass())).LifestylePerWebRequest());
    }
6
shenku

セッションにアクセスする私の方法は、さまざまなフィールド名とそのタイプをカプセル化するヘルパークラスを作成することです。この例が役立つことを願っています:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.SessionState;

namespace dmkp
{
    /// <summary>
    /// Encapsulates the session state
    /// </summary>
    public sealed class LoginInfo
    {
        private HttpSessionState _session;
        public LoginInfo(HttpSessionState session)
        {
            this._session = session;
        }

        public string Username
        {
            get { return (this._session["Username"] ?? string.Empty).ToString(); }
            set { this._session["Username"] = value; }
        }

        public string FullName
        {
            get { return (this._session["FullName"] ?? string.Empty).ToString(); }
            set { this._session["FullName"] = value; }
        }
        public int ID
        {
            get { return Convert.ToInt32((this._session["UID"] ?? -1)); }
            set { this._session["UID"] = value; }
        }

        public UserAccess AccessLevel
        {
            get { return (UserAccess)(this._session["AccessLevel"]); }
            set { this._session["AccessLevel"] = value; }
        }

    }
}
4
Daniel

ViewModelBaseをすべてのモデルの基本クラスとして使用できます。このクラスはセッションからのデータのプルを処理します

class ViewModelBase 
{
  public User CurrentUser 
  {
     get { return System.Web.HttpContext.Current.Session["user"] as User };
     set 
     {
        System.Web.HttpContext.Current.Session["user"]=value; 
     }
  }
}

セッションデータを処理するためにHttpContextBaseに拡張メソッドを書くことができます

T FromSession<T>(this HttpContextBase context ,string key,Action<T> getFromSource=null) 
{
    if(context.Session[key]!=null) 
    {
        return (T) context.Session[key];
    }
  else if(getFromSource!=null) 
  {
    var value = getFromSource();
   context.Session[key]=value; 
   return value; 
   }
  else 
  return null;
}

コントローラで以下のようにこれを使用してください

User userData = HttpContext.FromSession<User>("userdata",()=> { return user object from service/db  }); 

2番目の引数はオプションであり、セッションに値が存在しない場合にそのキーのセッションデータを埋めるために使用されます。

4
Ajay Kelkar