2013-06-07 10 views
14

こんにちはRazor MVC Gurus:面倒なMVCでは、マスターページ、パービジョン、ビューからアクセスできるグローバル変数はどこに置かれますか?

初心者質問です。

背景。私はそれがコントローラ&ビューになる前に、HttpModuleで設定されたカスタムIIdentityを持っています。これを使用するには、私はこの問題は、私は、このような

  • マスターレイアウト
  • いくつかのサブレベルのネストされたレイアウト
  • 一部partialviews
  • など、さまざまな場所でオブジェクトを使用し、ある

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

    をしなければなりません

  • いくつかのビュー

実際にはビューが必要とする "MyComplexUser"オブジェクトのどのプロパティのリスト。

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

@(((MyIdentity)((GenericPrincipal)context.User).Identity)。ユーザー))。 )

私はViewBagを使用するために好きではない私はコントローラに入れた後、ViewBag.MyUserプロパティでViewBagを読み込むことができたとしたが、その後

  1. 。私は強く型付けされたオブジェクトを好む
  2. 強く型付けされたオブジェクト( "MyUser")をビューに使うと、 "MyUser"プロパティを持つすべてのモデルに人気があります。少し汚れていると感じますか?私のモデルをきれいに保ち、彼らが関与しているビューに特化しているように。しかも、不必要に繰り返してしまう。
  3. master_layout.cshtmlやpartialviewsのような場所では、コントローラに入れた場合、「MyUser」にどのようにアクセスしますか?
  4. RenderActionを使用し、各ユーザープロパティの部分ビューをビルドすることは過剰ですか?

ありがとうございます。再び、私はMVC 4の初心者ですが、どんな提案も大変感謝しています。

+1

同様のシナリオがあります。コメントとして投稿します。私が答えとして追加したい場合は、私のすべてのコントローラは、私が書いた 'BaseController'を継承します。この基本クラスでは、 'ExecuteCore'のようなライフサイクルのイベントを配線しました。私はまた、このようなもののためにフィルターを使います。ビュー側では、すべてのビューモデルが 'BaseVM'から継承されます。ここでは、ユーザーにメッセージなどの一般的なプロパティ、ユーザー名などを配置します。 –

+0

@AndreCalil、もう少し説明できますか?ベースコントローラーからベースモデルを取り込むのですか? フィルタを使用する部分が得られません。例を挙げることはできますか? また、基本モデルの共通プロパティに値を設定した場合、マスターレイアウトページでどのように使用しますか? \\ @ Model BaseVMを実行してから、\\ @ Model.UserNameを実行しますか? ありがとう – Liming

+1

あなたは行き​​ます。そして、これは初心者の質問ではないと私は考えています。 –

答えて

21

私のためによく働く同様のソリューションについて説明します。小さな変更を加えた場合、私はだと信じています(他の人もうまくいけば)。

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

コントローラ

のは、カスタムベースのコントローラを作成してみましょう、

などなど

public class BaseController : Controller 

とのそれを継承するために、当社のコントローラを変更でき、

public class HomeController : BaseController 

モデルは、(のviewmodelsは、私が言います)

あなたのモデルの中にはたくさんのクラスがありますデール、そう?彼らはコントローラからビューへのDTOとして動作します、右の? と答えた場合は両方ともとなっています。強くBaseVMかに入力する必要がありますあなたのレイアウトファイル(全く_Layoutまたは):

などpublic class BaseVMとして、のは、ベースモデルクラスを作成してみましょう、とのはpublic class HomeIndex : BaseVM

重要のように、それを継承するために私たちのモデルを変更してみましょうそれの子供。

フック

今すべてがbeautifuly型付けだと、私たちの好意で要求パイプラインを使用してみましょう。

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は、アクションの後に実行が、前にビューのレンダリングと呼ばれる: はBaseControllerで、あなたはこのようになります方法を追加します。それがまさに私たちが望むものです。

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

+0

Andreに感謝します。 BaseController + BaseModelは理にかなっています:)もう一度、ありがとう! – Liming

+0

@Liming Glad to help =) –

+0

良い解決策 - 最後に、ViewBagを使用せずにすべてのビューにオブジェクトを渡す簡単な方法です。 – 79IT

関連する問題