web-dev-qa-db-ja.com

ASP.NET MVCのViewBagはバックグラウンドでどのように機能しますか?

ASP.NET MVCに関する本を読んでいますが、次の例がどのように機能するのか疑問に思っています。

例1

コントローラ

public class MyController : Controller
{
    public ActionResult Index()
    {
        ViewBag.MyProperty = 5;

        return View();
    }
}

表示する

<h1>@ViewBag.MyProperty</h1>

これで、ViewBagが動的オブジェクトであることがわかりました。そのため、プロパティを設定できます(動的オブジェクトについてはあまり知りませんが、動的オブジェクトを操作したことはありません)。コントローラーからViewBagを取得しますが、直接何も渡しませんか?

ViewBagpublicstaticオブジェクトになる可能性があると思いましたが、それに対する変更はグローバルであり、ビューインスタンスに固有ではありません。

これが舞台裏でどのように機能するかについて詳しく説明していただけますか?

例2

コントローラ

public class MyController : Controller
{
    public ActionResult Index()
    {
        ViewBag.MyProperty = 5;

        return View();
    }

    public ActionResult Index2()
    {
        ViewBag.MyProperty = 6;

        return View();
    }
}

ここで、最初にIndexメソッドが呼び出され、次にIndex2が呼び出されたとします。最終的に、ViewBag.MyPropertyの値は6(Index2の値)になります。行うのは良いことではないと感じていますが、同時にデスクトップ開発の観点から考えていると感じています。 Webはステートレスであるため、ASP.NET MVCで使用する場合は問題になりません。 これは事実ですか?

33
hattenn

ViewBagControllerBaseのプロパティで、すべてのコントローラーが継承する必要があります。これはdynamicオブジェクトです。そのため、コンパイル時にエラーが発生することなく、新しいプロパティを追加できます。

staticではなく、オブジェクトのメンバーです。リクエストの有効期間中、コントローラーインスタンスが作成および破棄されるため、値の上書きなどの「同時実行性」の問題は発生しません。

View(およびそのバリアント)メソッドもstaticではありません。これは、ビューがViewBag値を受け取る方法です。ビューのレンダリングプロセス中、コントローラーインスタンスにはViewBagインスタンスもあります。

28
Andre Calil

ControllerBase classを分析する場合、ViewBagプロパティは、ソースをより見やすくするためにViewDataプロパティの「プロキシ」であることがわかります。 (Scott HanselmanがPhil Haackからインタビューを受け、PhilがViewDataへのショートカットとしてViewBagプロパティを導入し、角括弧と引用符を繰り返す必要をなくしたことさえ覚えています)。 ViewBagプロパティはdynamicオブジェクトとして公開されますが、ViewDataと直接連携する DynamicViewDataDictionary クラスを実装します。

Controller クラスのソースコードを見ると、このメソッドを見つけることができます:

_protected internal virtual ViewResult View(string viewName, string masterName, object model)
_

基本的に、コントローラーからreturn View();を呼び出すと、コントローラーからViewDataをコンストラクターに渡すActionResultクラスの新しいインスタンスが作成されます。 ActionResultのインスタンスは、特定のビューエンジン(ASPX、Razor)に渡されるため、問題のビューをレンダリングするために使用できます。

ViewBag/ViewDataをpublic staticにすることは有害です。 MVCアプリケーションへの各Web要求は、コントローラーの新しいインスタンスを作成します。パブリックスタティックとしてViewData/ViewBagがある場合、2人の同時ユーザーがViewBag/ViewDataから同じデータを共有します。

ここ はビデオです。 ViewBag(以前のViewModel)に関する議論は04:05に始まります

11
Ramunas

ViewBagControllerBase のプロパティです。次のように定義されます。

public Object ViewBag { get; }

この署名は実際には間違っていることに注意してください。ソースコードは実際には次のようになります。

public dynamic ViewBag {
        get {
            if (_dynamicViewDataDictionary == null) {
                _dynamicViewDataDictionary = new DynamicViewDataDictionary(() => ViewData);
            }
            return _dynamicViewDataDictionary;
        }
    }

_dynamicViewDataDictionaryはExpandoObjectです。実行時にプロパティを追加できます。その有効期間は、コントローラーの有効期間と同じです。これは、HTTP要求の有効期間です。

6
Robert Harvey