16

こんにちは、Razor MVC の達人:

初心者の質問です。

バックグラウンド。コントローラーとビューに到達する前に、HttpModule に設定されたカスタム IIdentity があります。それを使用するには、私はしなければなりません

   MyIdentity myIdentity = (MyIdentity)((GenericPrincipal)context.User).Identity;
   MyComplexUser user = myIdentity.User;
   //user.name //user.location //user.username  //etc

問題は、次のようなさまざまな場所でオブジェクトを使用することです

  • マスター レイアウト
  • 一部のサブレベルのネストされたレイアウト
  • 一部の部分ビュー
  • 一部のビュー

ビューが必要とする "MyComplexUser" オブジェクトのプロパティに大きく依存します。

現在、ビューでは、プロパティに到達するために非常に複雑なキャストを行う必要があります。たとえば、ユーザーの「名前」が必要な場合は、次のようにする必要があります

@(((MyComplexUser)(((MyIdentity)((GenericPrincipal)context.User).Identity).User)).Name)

私はそれをコントローラーに入れてから ViewBag に ViewBag.MyUser プロパティを設定できると思いますが、その後

  1. ViewBag を使用するのは好きではありません。強く型付けされたオブジェクトを好む
  2. ビューに厳密に型指定されたオブジェクト ("MyUser") を使用する場合、それらすべてのモデルに "MyUser" プロパティを使用する必要があります。ちょっと汚い感じ?私は自分のモデルをきれいに保ち、関係するビューに固有のものにするのが好きなので. その上、それは不必要に繰り返されます。
  3. master_layout.cshtml や partialviews のような場所で、コントローラーに配置した場合、どのように「MyUser」にアクセスしますか?
  4. RenderAction を使用し、ユーザー プロパティごとに部分ビューを構築するのはやり過ぎですか?

ありがとう。繰り返しますが、私は MVC 4 の初心者です。どんな提案でも大歓迎です。

4

1 に答える 1

22

私にとって非常にうまく機能する同様のソリューションについて説明します。小さな変更を加えるだけで、あなた (そして願わくば他の人たち) にとってもうまくいくと思います。

基本的に、継承を使用します。

コントローラー

次のようなカスタムベースコントローラーを作成しましょう

public class BaseController : Controller

そして、それを継承するようにコントローラーを変更しましょう。

public class HomeController : BaseController

モデル (ViewModels、私は言います)

おそらく、Models フォルダー内に多くのクラスがありますよね? それらはコントローラーからビューへの DTO として機能しますよね²? どちらも「はい」と答えた場合は、読み続けてください。

のような基本モデル クラスを作成し、public class BaseVMそれから継承するようにモデルを変更しましょう。public class HomeIndex : BaseVM

重要:レイアウト ファイル (_Layoutまたはその他のもの) は、厳密に型指定されているBaseVMか、その子である必要があります。

フック

すべてがきれいに型付けされたので、リクエスト パイプラインを使用してみましょう。でBaseController、次のようなメソッドを追加します。

protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
    if (filterContext.Result is ViewResultBase)//Gets ViewResult and PartialViewResult
    {
        object viewModel = ((ViewResultBase)filterContext.Result).Model;

        if (viewModel != null && viewModel is BaseVM)
        {
            BaseVM baseVM = viewModel as BaseVM;

            baseVM.MyIdentity = (MyIdentity)((GenericPrincipal)context.User).Identity;
            //and so on...
        }
    }

    base.OnActionExecuted(filterContext);//this is important!
}

OnActionExecutedアクションの実行、ビューのレンダリング前に呼び出されます。それがまさに私たちが望んでいることです。

私はあなたがすでにそれを手に入れたことを願っています。=)

于 2013-06-07T15:17:19.863 に答える