次の方法で共有


ASP.NET Core のレイアウト

作成者: Steve SmithDave Brock

ページとビューは、視覚的要素とプログラム要素を頻繁に共有します。 この記事では、次の方法を示します。

  • 一般的なレイアウトを使用します。
  • ディレクティブを共有します。
  • ページまたはビューをレンダリングする前に、一般的なコードを実行します。

このドキュメントでは、ASP.NET Core MVC の 2 つの異なるアプローチである Razor ページとビュー付きコントローラーのレイアウトについて説明します。 このトピックでは、違いは最小限です。

  • Razor ページは Pages フォルダーにあります
  • ビューを含むコントローラーでは、 ビューに Views フォルダーが使用されます。

レイアウトとは

ほとんどの Web アプリには共通のレイアウトがあり、ユーザーはページ間を移動する間に一貫したエクスペリエンスを提供します。 通常、レイアウトには、アプリ ヘッダー、ナビゲーション要素、メニュー要素、フッターなどの一般的なユーザー インターフェイス要素が含まれます。

ページ レイアウトの例

スクリプトやスタイルシートなどの一般的な HTML 構造も、アプリ内の多くのページで頻繁に使用されます。 これらの共有要素はすべて レイアウト ファイルで定義できます。このファイルは、アプリ内で使用される任意のビューで参照できます。 レイアウトにより、ビュー内の重複するコードが減ります。

慣例により、ASP.NET Core アプリの既定のレイアウトには _Layout.cshtml という名前が付けられます。 テンプレートで作成された新しい ASP.NET Core プロジェクトのレイアウト ファイルは次のとおりです。

  • Razor ページ: Pages/Shared/_Layout.cshtml

    ソリューション エクスプローラーの Pages フォルダー

  • ビュー付きコントローラー: Views/Shared/_Layout.cshtml

    ソリューション エクスプローラーの Views フォルダー

レイアウトでは、アプリ内のビューの最上位レベルのテンプレートを定義します。 アプリにはレイアウトは必要ありません。 アプリは異なるビューを持つ複数のレイアウトを定義できますが、それぞれのビューが異なるレイアウトを指定します。

次のコードは、コントローラーとビューを使用して作成されたテンプレート プロジェクトのレイアウト ファイルを示しています。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebApplication1</title>

    <environment include="Development">
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
        <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
    </environment>
</head>
<body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a asp-page="/Index" class="navbar-brand">WebApplication1</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a asp-page="/Index">Home</a></li>
                    <li><a asp-page="/About">About</a></li>
                    <li><a asp-page="/Contact">Contact</a></li>
                </ul>
            </div>
        </div>
    </nav>

    <partial name="_CookieConsentPartial" />

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; 2018 - WebApplication1</p>
        </footer>
    </div>

    <environment include="Development">
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
    </environment>
    <environment exclude="Development">
        <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
                asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
                asp-fallback-test="window.jQuery"
                crossorigin="anonymous"
                integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
        </script>
        <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
                asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
                asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
                crossorigin="anonymous"
                integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
        </script>
        <script src="~/js/site.min.js" asp-append-version="true"></script>
    </environment>

    @RenderSection("Scripts", required: false)
</body>
</html>

レイアウトの指定

Razor ビューには Layout プロパティがあります。 個々のビューでは、次のプロパティを設定してレイアウトを指定します。

@{
    Layout = "_Layout";
}

指定したレイアウトでは、完全なパス ( /Pages/Shared/_Layout.cshtml/Views/Shared/_Layout.cshtmlなど) または部分的な名前 (例: _Layout) を使用できます。 部分的な名前を指定すると、 Razor ビュー エンジンは、標準の検出プロセスを使用してレイアウト ファイルを検索します。 ハンドラー メソッド (またはコントローラー) が存在するフォルダーが最初に検索され、次に Shared フォルダーが検索されます。 この検出プロセスは、 部分ビューの検出に使用されるプロセスと同じです。

既定では、すべてのレイアウトで RenderBodyを呼び出す必要があります。 RenderBodyの呼び出しが配置されるたびに、ビューの内容がレンダリングされます。

セクション

レイアウトでは、必要に応じて、を呼び出すことによって、1 つ以上のRenderSectionを参照できます。 セクションは、特定のページ要素を配置する場所を整理する方法を提供します。 RenderSectionを呼び出すたびに、そのセクションが必須か省略可能かを指定できます。

<script type="text/javascript" src="~/scripts/global.js"></script>

@RenderSection("Scripts", required: false)

必要なセクションが見つからない場合は、例外が発生します。 個々のビューでは、 @sectionRazor 構文を使用してセクション内でレンダリングされるコンテンツを指定します。 ページまたはビューでセクションが定義されている場合は、そのセクションをレンダリングする必要があります (またはエラーが発生します)。

@section ページ ビューのRazor定義の例を次に示します。

@section Scripts {
     <script type="text/javascript" src="~/scripts/main.js"></script>
}

前のコードでは、ページまたはビューの scripts/main.js セクションにscriptsが追加されています。 同じアプリ内の他のページまたはビューでは、このスクリプトは必要なく、スクリプト セクションは定義されない場合があります。

次のマークアップでは、 部分タグ ヘルパー を使用して _ValidationScriptsPartial.cshtmlをレンダリングします。

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

上記のマークアップは、Identityをスキャフォールディングすることによって生成されました。

ページまたはビューで定義されているセクションは、その即時レイアウト ページでのみ使用できます。 ビュー システムの部分、ビュー コンポーネント、またはその他の部分から参照することはできません。

セクションを無視する

既定では、コンテンツ ページ内の本文とすべてのセクションは、すべてレイアウト ページによってレンダリングされる必要があります。 Razor ビュー エンジンは、本文と各セクションがレンダリングされたかどうかを追跡することによってこれを強制します。

本文またはセクションを無視するようにビュー エンジンに指示するには、 IgnoreBody メソッドと IgnoreSection メソッドを呼び出します。

本文と Razor ページ内のすべてのセクションは、レンダリングするか無視する必要があります。

共有ディレクティブのインポート

ビューとページでは、 Razor ディレクティブを使用して名前空間をインポートし、 依存関係の挿入を使用できます。 多くのビューで共有されるディレクティブは、共通の _ViewImports.cshtml ファイルで指定できます。 _ViewImports ファイルは、次のディレクティブをサポートしています。

  • @addTagHelper
  • @removeTagHelper
  • @tagHelperPrefix
  • @using
  • @model
  • @inherits
  • @inject
  • @namespace

このファイルは、関数やセクション定義など、他の Razor 機能をサポートしていません。

サンプル _ViewImports.cshtml ファイル:

@using WebApplication1
@using WebApplication1.Models
@using WebApplication1.Models.AccountViewModels
@using WebApplication1.Models.ManageViewModels
@using Microsoft.AspNetCore.Identity
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

ASP.NET Core MVC アプリの _ViewImports.cshtml ファイルは、通常、 Pages (または Views) フォルダーに配置されます。 _ViewImports.cshtml ファイルは任意のフォルダー内に配置できます。その場合、そのフォルダーとそのサブフォルダー内のページまたはビューにのみ適用されます。 _ViewImports ファイルは、ルート レベルから始まり、ページまたはビュー自体の場所に至る各フォルダーに対して処理されます。 _ViewImports ルート レベルで指定された設定は、フォルダー レベルでオーバーライドできます。

たとえば、次の例を示します。

  • ルート レベル _ViewImports.cshtml ファイルには、 @model MyModel1@addTagHelper *, MyTagHelper1が含まれます。
  • サブフォルダー _ViewImports.cshtml ファイルには、 @model MyModel2@addTagHelper *, MyTagHelper2が含まれます。

サブフォルダー内のページとビューは、タグ ヘルパーと MyModel2 モデルの両方にアクセスできます。

ファイル階層内に複数の _ViewImports.cshtml ファイルが見つかった場合、ディレクティブの組み合わせ動作は次のようになります。

  • @addTagHelper@removeTagHelper: すべての実行が順番に行われます
  • @tagHelperPrefix: ビューに最も近いものが他のビューよりも優先されます。
  • @model: ビューに最も近いものが他のビューよりも優先されます。
  • @inherits: ビューに最も近いものが他のビューよりも優先されます。
  • @using: すべてが含まれています。重複は無視されます
  • @inject: 各プロパティについて、ビューに最も近いものは、同じプロパティ名を持つ他のプロパティをオーバーライドします

各ビューの前にコードを実行する

各ビューまたはページの前に実行する必要があるコードは、 _ViewStart.cshtml ファイルに配置する必要があります。 慣例により、 _ViewStart.cshtml ファイルは Pages (または Views) フォルダーにあります。 _ViewStart.cshtmlに一覧表示されているステートメントは、すべてのフル ビューの前に実行されます (レイアウトではなく、部分ビューではありません)。 ViewImports.cshtml と同様に、_ViewStart.cshtmlは階層構造です。 _ViewStart.cshtml ファイルがビューまたはページ フォルダーで定義されている場合は、Pages (または Views) フォルダーのルートで定義されたファイル (存在する場合) の後に実行されます。

サンプル _ViewStart.cshtml ファイル:

@{
    Layout = "_Layout";
}

上記のファイルは、すべてのビューが _Layout.cshtml レイアウトを使用することを指定します。

_ViewStart.cshtmlおよび_ViewImports.cshtmlは通常、/Pages/Shared (または /Views/Shared) フォルダーに配置されません。 これらのファイルのアプリ レベルのバージョンは 、/Pages (または /Views) フォルダーに直接配置する必要があります。