2013-08-13 16 views
11

の実行順序は何か:SomethingThatDependsOnContextBeingSetUpSetUpSomeContext前に実行し、ビューがレンダリングするとき私は次のようにかみそりのレイアウトを持っているMVCかみそりビュー/レイアウト

@{ 
    Layout = "MyLayout.cshtml"; 
} 
<div>@SomethingThatDependsOnContextBeingSetUp()</div> 

@using (var context = SetUpSomeContext()) { 
    <div> 
     Some content here 
     @RenderBody(); 
    </div> 
} 

などを考慮失敗します。これは、私がレイアウト内でRenderBodyが呼び出されるまで実行しないことを期待しているので、奇妙に思えます。 RenderBodyの代わりに "PageContent"セクションを使うように切り替えると、すべてが期待通りに機能します。誰もこの行動を説明できますか?

+0

私の答えは何を解決するために残っている、この動作を説明しますか? – MstfAsan

答えて

2

実行順序は、最内から最外になります。

私は「コンテキスト」を使用する方法が最良の設計ではないと主張します。セットアップをコントローラ/アクションフィルタに移動し、データをモデルのビューに渡すことを検討する必要があります。

+0

しかし、セクションはこのルールに従っていませんか?また、このアプローチの理由は、すべてのコントローラメソッドでView()を呼び出す方法を変更する必要がなく、共通のレンダリング機能を有効にしたいということです。 – ChaseMedallion

0

すべてのビューでロジックが必要な場合は、ViewModelが継承するViewModelBaseを作成してください。

​​でViewModel.SharedContextなどのプロパティを初期化できます。

+0

私はこのビューをすべてのビューではなく、全面的に表示したいだけです。あなたはまだこのレイアウトのViewModelBaseを使用することをお勧めしますか?また、このテクニックを使用してビューの始めと終わりにコードを実行するにはどうすればよいですか(たとえば、コンテキストを作成してからそれを破棄する)? – ChaseMedallion

+0

@あなたはどんな種類の文脈について話していますか?あなたが走っている問題を考えると、私は共有ViewModelを使って言ったように、これを別のレベルで解決することを提案します。 – CodeCaster

3

状況を調べることでこれを明確にしてみましょう。

@renderSection("Header") 
    @using (var context = SetUpSomeContext()) { 
     <div> 
      Some content here 
      @RenderBody(); 
     </div> 
    } 
    @renderSection("Footer") 

私たちは、剃刀があなたが期待する順序でページを実行すると仮定しています。私たちのようなビューを宣言すればどうなりますか?

が が

は、そのビューが@RenderBody()それが何のためにレイアウトページをレンダリングすることを推測するだろう.Alsoを実行するまで、レイアウト・ページを必要とし、これはないだろうかカミソリが任意のアイデアを持っていないでしょうreasonable.Soこれは

@{ 
    Layout = null; 
} 
<div>@SomethingThatDependsOnContextBeingSetUp()</div> 
実際に何が起こるかではない。

リクエストがあったとき、Razorが最初にあなたの視界の本体を実行するのはとても自然です。 私のデモRazorのようなレイアウトが指定されていない場合は、そのページの出力をレンダリングして停止します。ビューの実行後に コードのようにレイアウトが指定されている場合、レイアウトページに制御が渡されます。上から下にレンダリング)レイアウトページの残りの部分はコンテンツ配置のみです。@RenderBody()が表示されると、既に実行されているビューの出力が配置されます。

セクションの場合;ビューボディが実行されたときには実行されません。ビューがレイアウトページにコントロールを渡した後、レイアウトページは宣言された順序でセクションの実行を明示的に呼び出します。

はまた、あなたがあなたのビュー本体でページのタイトルを指定していることがわかり、ビュー本体で宣言されているすべての変数がで利用可能なレイアウトのタイトルタグ(ViewBag.Title) .After実行ビュー本体でレンダリングされますレイアウトページ。

合計:表示順序は上から下ですが、実行順序は異なります。あなたの状況については

"SomethingThatDependsOnContextBeingSetUpはSetUpSomeContext前に実行され、失敗した"を。私はレイザー実行サイクルの自然な振る舞いだと言ったように、ビューのボディはレイアウトページが実行される前に実行されました。 セクションを作成するとき;ビュー本体は、最初に実行が、レイアウトpage.View本体を上から下へのレンダリングを開始し、それが@RenderSectionが、この場合のsection.Soの実行を呼び出す見ればSetUpSomeContextが実行されたレイアウトページとレイアウトページに制御を渡す前に、セクションは実行されませんSomethingThatDependsOnContextBeingSetUpが実行される前に

+0

これは答えではなく、質問の一部になるように移動する必要があります。 – krillgar

+0

質問者が学ぶ必要があるすべての詳細を説明していると思います – MstfAsan

+0

これは役に立つと思われますが、一般的なチュートリアルのように、* answer *と似ていません。 –

5

カミソリパイプラインは、次のとおり

  1. まず、カミソリが評価し、存在する場合、割り当てレイアウト又は他の初期化のためにのみカミソリステートメント(C#またはVB)が含ま_ViewStart.cshtml、それが必要htmlタグは決して内部にはありません。

  2. すると、それが解析し、"表示" CSHTMLファイルを評価します。

  3. すると、それが解析し、存在する場合、評価し、をレイアウト、およびCSHTMLレイアウトファイルの@RenderBody方法を評価するとき、「ビュー」CSHTMLファイルの評価から結果のHTMLスクリプトに置き換えます。

  4. 最後に、レイアウトとビューのHTMLファイルのHTMLコントロールのグラフオブジェクトを構築します。


のでは、あなたがレイアウト事業からのビューのいずれかの「カミソリ」のオブジェクトに依存やるのではなく、することはできませんあなたは_ViewStart.cshtmlあなたのビューに見えるオブジェクトのあなたの初期化の中に置いてもよいです。


あなたはController.Viewメソッドが呼び出されたときにロードされた静的コンテンツとしてCS(VB)のHTMLビューを想像することがあります。式を評価

その時点で、CSHTMLロードされたコンテンツは、カミソリによって解析される(ループ、レイアウト等の特性()、branchsを割り当てる)とActionResultオブジェクトに「HtmlControls」オブジェクトのバイナリツリーまたはグラフの種類を構築しますViewメソッドによって返されます。

次に、のActionResultはAsp.Netからhtmlとしてレンダリングされ、HTTPレスポンスとしてクライアントに返されます。 、カミソリはCSHTMLファイルを解析し、「_ViewStart.cshtml」(原点コントローラに関連するサブフォルダ鎖中に存在する場合は、1つの、またそれ以上)からの第1の開始部分の内側にコードを実行し、CSHTMLに従っていることを行うに

Viewメソッドを呼び出すときに、コンベンションによってロードされたファイル(ビューの名前はパスViews/[ControllerName] /のアクションの名前と等しい)、または表現されたビューの名前をパラメータとして指定し、最後にビューにリンクされた最終レイアウトファイルLayoutプロパティ。

関連する問題