2

これは、何よりも高度な質問です。

私は、とりわけユーザーを管理する MVC プロジェクトを持っています。私は現在、ビューページで宣言されたモデルのみを使用するというより厳密なアプローチに固執しています。つまり、次のものがあります。

@model MVCApp.Models.SomeModel

各 View.cshtml の上部

複数のモデルを必要とするページがいくつかあります。この時点で、2 つのモデルを 1 つに統合し、1 つのモデルとしてビューに送信します。

ここがトリッキーな部分です。ユーザーデータを保持するモデルがあるとしましょう。そのユーザー データはセッション Cookie に保存されます (通常のフォーム認証)。ユーザーモデルとそのビュー内で使用したいモデルの両方を保持する独自のモデルで、使用するすべてのモデルをラップする必要があるのは奇妙に思えます。

私が自問する質問は、ユーザー モデルを ViewBag に渡してビュー内で使用しない理由です。なぜそれが悪い習慣と見なされるのですか?最終的にすべてのモデルを複製することなく、そのモデルをすべてのページに添付できます。

どなたかご指南いただければ幸いです。私はこれを間違った方法で見ているかもしれません。どんな助けも大いに義務付けられます。

ありがとう、

4

2 に答える 2

4

ViewBag を避けるべき理由はいくつかあります。

  • ViewBag は弱く型付けされています
  • ビューでインテリセンスが得られない
  • あなたのビューはViewBagとビューモデルの混合物であり、あなたのビューは強く型付けされたビューモデルにすべてを一元化するのではなく、さまざまな場所から情報を取得します
  • ViewBag は、動的型を拡張メソッドで使用できないため、強く型付けされたヘルパーと式では機能しません (これは ASP.NET MVC の制限ではなく、.NET です => 動的型で拡張メソッドをディスパッチできません)。
  • ViewBag の弱い型付けの性質により、HTML ヘルパーは特定の型が引数として渡されることを想定しているため、ビューをキャストしてスパゲッティ コードにする必要があります。
  • ... このリストは続きます (実際に記入する時間はありませんが、非常に大きなリストです)

ViewBag は良くなく、使用すべきではないことがわかったので、ビュー モデルを使用してこの要件を解決するさまざまな方法があります。

1 つの可能性は、Html.Action ヘルパーを使用することです。これにより、完全なコントローラー/モデル/ビュー ライフサイクルを経て、HTML の一部をビューに挿入できます。このようにして、メイン ビュー モデルに干渉することなく、一般的に使用されるウィジェットを持つことができます。

もう 1 つの可能性は、ユーザーの詳細を表すプロパティを含み、コントローラー アクションの実行が終了してビューの結果を返すたびに実行できるカスタム グローバル アクション フィルターによって設定される基本ビュー モデルを持つことです。アクション フィルターは、このビューの結果をインターセプトし、認証 Cookie 情報を読み取り、ビュー モデル プロパティを設定する可能性があります。これは、すべてのビュー モデルが共通の基本ビュー モデルから派生していることを前提としています。このユーザー情報を各ページに表示する必要がある場合、これは明らかに理にかなっています。

例えば:

public class UserInfoInjectorAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var result = filterContext.Result as ViewResultBase;
        if (result == null)
        { 
            // the controller action didn't return any view result => no need to continue
            return;
        }

        var model = result.Model as BaseViewModel;
        if (model == null)
        {
            // the controller action didn't pass a model or the model passed to the view
            // doesn't derive from the common base view model that will contain 
            // the user info property => no need to continbue any further
            return;
        }

        model.UserInfo = ... go ahead and read the forms authentication cookie
                             userData portion and extract the information
                             you are looking for
    }
}

あとは、このアクション フィルターをグローバル アクション フィルターとして登録するだけで、すべてのコントローラー アクションに適用されます。

すべてのビュー モデルがこれから派生する場合BaseViewModel、ビューに到着すると、このプロパティの取得を行うコードですべてのコントローラー アクションを汚染することなく、UserInfo プロパティに関連情報が入力されることがわかります。それでも、ビューで強いタイピングが発生します => ViewBag はありません (youpeeee)。

もちろん、特定のシナリオによっては、それを達成するための他の方法があるかもしれません (明らかにViewBag.

于 2012-05-08T14:38:57.243 に答える
0

ActionFilterAttributeが可能で、特定の ViewBag アイテムを必要とするビューをロードするアクションで、それらを初期化できます。

維持するのが難しくなるため、お勧めしませんが、問題を解決する可能性のある一般的なアプローチになります。

于 2012-05-08T14:43:15.387 に答える