Układ w ASP.NET Core

Przez Steve Smith i Dave Brock

Strony i widoki często udostępniają elementy wizualne i programowe. W tym artykule pokazano, jak:

  • Użyj typowych układów.
  • Dyrektywy udostępniania.
  • Uruchom wspólny kod przed renderowaniem stron lub widoków.

W tym dokumencie omówiono układy dwóch różnych podejść do ASP.NET Core MVC: Razor strony i kontrolery z widokami. W tym temacie różnice są minimalne:

  • Razor Strony znajdują się w folderze Pages .
  • Kontrolery z widokami używają folderu Views dla widoków.

Co to jest układ

Większość aplikacji internetowych ma wspólny układ, który zapewnia użytkownikowi spójne środowisko podczas przechodzenia ze strony do strony. Układ zazwyczaj zawiera typowe elementy interfejsu użytkownika, takie jak nagłówek aplikacji, elementy nawigacji lub menu oraz stopka.

Page Layout example

Typowe struktury HTML, takie jak skrypty i arkusze stylów, są również często używane przez wiele stron w aplikacji. Wszystkie te elementy udostępnione można zdefiniować w pliku układu , do którego można się odwoływać przy użyciu dowolnego widoku używanego w aplikacji. Układy zmniejszają zduplikowany kod w widokach.

Zgodnie z konwencją domyślny układ aplikacji ASP.NET Core nosi nazwę _Layout.cshtml. Pliki układu dla nowych projektów ASP.NET Core utworzonych za pomocą szablonów to:

  • Razor Stron: Pages/Shared/_Layout.cshtml

    Pages folder in Solution Explorer

  • Kontroler z widokami: Views/Shared/_Layout.cshtml

    Views folder in Solution Explorer

Układ definiuje szablon najwyższego poziomu dla widoków w aplikacji. Aplikacje nie wymagają układu. Aplikacje mogą definiować więcej niż jeden układ z różnymi widokami określającymi różne układy.

Poniższy kod przedstawia plik układu dla utworzonego projektu szablonu z kontrolerem i widokami:

<!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>

Określanie układu

Razor widoki mają Layout właściwość. Poszczególne widoki określają układ, ustawiając tę właściwość:

@{
    Layout = "_Layout";
}

Określony układ może używać pełnej ścieżki (na przykład /Pages/Shared/_Layout.cshtml lub ) lub /Views/Shared/_Layout.cshtmlczęściowej nazwy (na przykład: _Layout). Po podaniu Razor częściowej nazwy aparat widoku wyszukuje plik układu przy użyciu standardowego procesu odnajdywania. Najpierw przeszukiwany jest folder, w którym istnieje metoda obsługi (lub kontroler), a następnie folder Udostępniony . Ten proces odnajdywania jest identyczny z procesem używanym do odnajdywania widoków częściowych.

Domyślnie każdy układ musi wywoływać metodę RenderBody. Wszędzie tam, gdzie zostanie umieszczone wywołanie RenderBody , zawartość widoku zostanie wyrenderowana.

Sekcje

Układ może opcjonalnie odwoływać się do co najmniej jednej sekcji, wywołując metodę RenderSection. Sekcje umożliwiają organizowanie miejsc, w których należy umieścić określone elementy strony. Każde wywołanie w celu RenderSection określenia, czy ta sekcja jest wymagana, czy opcjonalna:

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

@RenderSection("Scripts", required: false)

Jeśli wymagana sekcja nie zostanie znaleziona, zostanie zgłoszony wyjątek. Poszczególne widoki określają zawartość, która ma być renderowana w sekcji przy użyciu @sectionRazor składni. Jeśli strona lub widok definiuje sekcję, musi być renderowana (lub wystąpi błąd).

Przykładowa @section definicja w Razor widoku strony:

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

W poprzednim kodzie scripts/main.js jest dodawany do scripts sekcji na stronie lub widoku. Inne strony lub widoki w tej samej aplikacji mogą nie wymagać tego skryptu i nie zdefiniują sekcji skryptów.

Poniższy znacznik używa pomocnika tagów częściowych do renderowania_ValidationScriptsPartial.cshtml:

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

Powyższy znacznik został wygenerowany przez tworzenie szkieletu Identity.

Sekcje zdefiniowane na stronie lub widoku są dostępne tylko na stronie układu bezpośredniego. Nie można odwoływać się do nich z części, składników widoku ani innych części systemu widoków.

Ignorowanie sekcji

Domyślnie treść i wszystkie sekcje na stronie zawartości muszą być renderowane przez stronę układu. Aparat Razor widoku wymusza to, śledząc, czy treść i każda sekcja zostały renderowane.

Aby poinstruować aparat wyświetlania, aby zignorował treść lub sekcje, wywołaj IgnoreBody metody i IgnoreSection .

Treść i każda sekcja na Razor stronie muszą być renderowane lub ignorowane.

Importowanie dyrektyw udostępnionych

Widoki i strony mogą używać Razor dyrektyw do importowania przestrzeni nazw i używania iniekcji zależności. Dyrektywy współużytkowane przez wiele widoków mogą być określone w typowym _ViewImports.cshtml pliku. Plik _ViewImports obsługuje następujące dyrektywy:

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

Plik nie obsługuje innych Razor funkcji, takich jak funkcje i definicje sekcji.

Przykładowy _ViewImports.cshtml plik:

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

Plik _ViewImports.cshtml ASP.NET Core MVC aplikacji jest zwykle umieszczany w folderze Pages (lub Views). Plik _ViewImports.cshtml można umieścić w dowolnym folderze, w takim przypadku będzie on stosowany tylko do stron lub widoków w tym folderze i jego podfolderach. _ViewImports pliki są przetwarzane począwszy od poziomu głównego, a następnie dla każdego folderu prowadzącego do lokalizacji strony lub samego widoku. _ViewImports ustawienia określone na poziomie głównym mogą zostać zastąpione na poziomie folderu.

Załóżmy na przykład:

  • Plik poziomu _ViewImports.cshtml głównego zawiera @model MyModel1 pliki i @addTagHelper *, MyTagHelper1.
  • Plik podfolderu _ViewImports.cshtml zawiera @model MyModel2 pliki i @addTagHelper *, MyTagHelper2.

Strony i widoki w podfolderze będą miały dostęp zarówno do pomocników tagów, jak MyModel2 i modelu.

Jeśli w hierarchii plików znajduje się wiele _ViewImports.cshtml plików, połączone zachowanie dyrektyw to:

  • @addTagHelper, : @removeTagHelperwszystkie uruchomienia, w kolejności
  • @tagHelperPrefix: najbliżej widoku zastępuje wszystkie inne
  • @model: najbliżej widoku zastępuje wszystkie inne
  • @inherits: najbliżej widoku zastępuje wszystkie inne
  • @using: wszystkie są uwzględnione; duplikaty są ignorowane
  • @inject: dla każdej właściwości, najbliżej widoku zastępuje wszystkie inne z tą samą nazwą właściwości

Uruchamianie kodu przed każdym widokiem

Kod, który należy uruchomić przed każdym widokiem lub stroną, powinien zostać umieszczony w _ViewStart.cshtml pliku. Zgodnie z konwencją _ViewStart.cshtml plik znajduje się w folderze Pages (lub Views). Instrukcje wymienione w pliku _ViewStart.cshtml są uruchamiane przed każdym pełnym widokiem (nie układami, a nie częściowymi widokami). Podobnie jak ViewImports.cshtml, _ViewStart.cshtml jest hierarchiczny. _ViewStart.cshtml Jeśli plik jest zdefiniowany w folderze widoku lub stron, zostanie on uruchomiony po tym, jak został zdefiniowany w folderze głównym folderu Pages (lub Widoki) (jeśli istnieje).

Przykładowy _ViewStart.cshtml plik:

@{
    Layout = "_Layout";
}

Powyższy plik określa, że wszystkie widoki będą używać _Layout.cshtml układu.

_ViewStart.cshtmli _ViewImports.cshtml niezwykle umieszczane w folderze /Pages/Shared (lub /Views/Shared). Wersje tych plików na poziomie aplikacji powinny zostać umieszczone bezpośrednio w folderze /Pages (lub /Views).