問題の説明
アプリケーションにView.cshtmlとViewWithSide.cshtmlのビューがいくつかあるとします。また、2つのマスターページがあります。Layout.cshtmlとLayoutWithSide.cshtmlです。1つ目は2つ目のマスターページです。 ファイル名から推測できるように、XxxWithSide.cshtmlはページにサイドバーを追加します。サイドバーの出力形式はマスターページで定義され、ビューの内部は定義されます。 メインレイアウトマスターページでは、メインレイアウトに加えて、「ナビゲーション」セクションの出力が定義され、ビューで設定されます。
そして今、「ナビゲーション」セクションがViewWithSideコードで定義されているが、LayoutWithSideでは定義されていない場合、このセクションは「次の」マスターページ(レイアウト)で処理される必要があるため、アプリケーションでViewWithSideを開こうとするとエラーが発行されます: 次のセクションが定義されましたレイアウトページ "〜/ Views / Shared / LayoutWithSide.cshtml": "navigation" ( " Navigation" セクションが定義されていますが、マスターページのどこにも表示 されていません)に対してレンダリングされて いません 。
この問題を解決するアイデアは非常に簡単です。このセクションの出力を「次の」マスターページに転送し、そこで理解してもらう必要があります。
いくつかのコード
Layout.cshtml
<!DOCTYPE html> <html> <head> <title>@ViewBag.Title</title> </head> <body> <div> @if (IsSectionDefined("navigation")) { <div class="navigation">@RenderSection("navigation")</div> } @RenderBody() </div> </body> </html>
LayoutWithSide.cshtml
@{ Layout = "~/Views/Shared/Layout.cshtml"; } <div class="side">@RenderSection("side", required:false)</div> <div class="main">@RenderBody()</div>
View.cshtml
@{ ViewBag.Title = "view"; Layout = "~/Views/Shared/Layout.cshtml"; } @section navigation { <a href="@Url.Action("Page1")">page1</a> | <a href="@Url.Action("Page2")">page2</a> } <h2>viewWithoutSide</h2> <div>Main content</div>
ViewWithSide.cshtml
@{ ViewBag.Title = "viewWithSide"; Layout = "~/Views/Shared/LayoutWithSide.cshtml"; } @section navigation { <a href="@Url.Action("Page1")">page1</a> | <a href="@Url.Action("Page2")">page2</a> } @section side { <strong>side content</strong> } <h2>viewWithSide</h2> <div>Main content</div>
当然、RazorとASP.NET MVCがそれを把握し、必要なマスターページのセクションを表示することを期待していました。 しかし、悲しいかな...しかし、問題があり、解決する方法のアイデアがあります-解決する必要があります。
ソリューションを検索する
私の場合、「ナビゲーション」セクションは単なるオプションではありませんが、定義されていない場合は、マークアップの一部が表示されません。 このため、LayoutWithSideに同じ名前のセクションを入力し、ビューから転送されたコンテンツを表示するだけでは機能しません。
私は
if (IsSectionDefined("navigation"))
でセクション宣言をラップしようとしましたが、多分...このメソッドに特に希望はありませんでした-うまくいきませんでした(アナライザーはそのようなデザインを期待せず、「パーサーエラー」を宣誓します)。
MSDNおよびインターネットでの迅速で表面的な検索では、有用なものは何も得られませんでした。 しかし、ビュー内で使用可能なメソッドでは、 DefineSectionメソッド(文字列名、SectionWriterアクション)がすぐに気付きました
if宣言でRazorスタイルのセクション宣言をラップすることはできなかったため、C#コードからセクション作成をラップすることができます。 次のようになりました。
if (IsSectionDefined("navigation")) { DefineSection("navigation", delegate() { Write(RenderSection("navigation")); }); }
そして、このコードは正常に機能し、タスクを完了しました。
解決策
もちろん、マスターページに転送する必要のある各セクション
public static class WebPageHelpers { public static void PropagateSection(this WebPageBase page, string sectionName) { if (page.IsSectionDefined(sectionName)) { page.DefineSection(sectionName, delegate() { page.Write(page.RenderSection(sectionName)); }); } } public static void PropagateSections(this WebPageBase page, params string[] sections) { foreach (var s in sections) PropagateSection(page, s); } }
そして、プロジェクトに接続したら、メソッドを呼び出して、必要なセクションの名前を渡します。 この場合、LayoutWithSide.cshtmlは次のようになります。
@{ Layout = "~/Views/Shared/Layout.cshtml"; this.PropagateSection("navigation"); } <div class="side">@RenderSection("side", required:false)</div> <div class="main">@RenderBody()</div>
複数のセクションをマスターページに転送する必要がある場合は、
this.PropagateSections("section1", "section2", "section3")
呼び出すことができます。