Layout in ASP.NET Core

Von Steve Smith und Dave Brock

Seiten und Ansichten beinhalten häufig sowohl visuelle als auch programmgesteuerte Elemente. Dieser Artikel demonstriert Folgendes:

  • Verwendung von allgemeinen Layouts
  • Freigeben von Anweisungen
  • Führen Sie den allgemeinen Code aus, bevor Sie Seiten oder Ansichten rendern.

In diesem Dokument werden Layouts für die beiden verschiedenen Ansätze zum Erstellen ASP.NET Core MVC erläutert: Razor Seiten und Controller mit Ansichten. In diesem Thema sind die Unterschiede minimal:

  • RazorSeiten befinden sich im Ordner Pages.
  • Controller mit Ansichten verwenden einen Ordner namens Views für Ansichten.

Was ist ein Layout?

Die meisten Web-Apps haben ein gebräuchliches Layout, das dem Benutzer beim Navigieren auf den Seiten ein konsistentes Verhalten bietet. Das Layout enthält normalerweise allgemeine Benutzeroberflächenelemente wie App-Header, Navigations- oder Menüelemente sowie eine Fußzeile.

Beispiel für ein Seitenlayout

Oft verwendete HTML-Strukturen wie Skripts und Stylesheets werden auch häufig von vielen Seiten in einer App genutzt. Alle diese freigegebenen Elemente können in einer Layoutdatei definiert werden, auf die dann von jeder Ansicht verwiesen werden kann, die in der App verwendet wird. Layouts verringern Codeduplikate in Ansichten.

Gemäß Konvention ist _Layout.cshtml das Standardlayout für eine ASP.NET Core-App. Für neue ASP.NET Core-Projekte, die mit den Vorlagen erstellt wurden, sind folgende Layoutdateien vorhanden:

  • Razor Pages: Pages/Shared/_Layout.cshtml

    Ordner „Pages“ im Projektmappen-Explorer

  • Controller mit Ansichten: Views/Shared/_Layout.cshtml

    Ordner „Views“ im Projektmappen-Explorer

Das Layout definiert eine übergeordnete Vorlage für die Ansichten einer App. Für Apps ist kein Layout erforderlich. Sie können allerdings mehrere Layouts mit unterschiedlichen Ansichten aufweisen.

Der folgende Code zeigt die Layoutdatei für eine Vorlage, die mit dem Projekt mit einem Controller und Ansichten erstellt wurde:

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

Festlegen eines Layouts

Razor -Ansichten verfügen über eine Layout -Eigenschaft. Durch Festlegen dieser Eigenschaft wird das Layout der jeweiligen Ansicht bestimmt:

@{
    Layout = "_Layout";
}

Das angegebene Layout kann einen vollständigen Pfad (z.B. /Pages/Shared/_Layout.cshtml oder /Views/Shared/_Layout.cshtml) oder einen Teil des Namens (Beispiel: _Layout) aufweisen. Wenn ein Teilname angegeben wird, sucht die Ansichts-Engine mithilfe des Standardermittlungsprozesses nach Razor der Layoutdatei. Der Ordner, in dem sich die die Handlermethode (oder der Controller) befindet, wird zuerst durchsucht und danach der Ordner Shared. Dieser Ermittlungsprozess ist identisch mit dem Prozess zum Auffinden von Teilansichten.

Standardmäßig muss jedes Layout RenderBody aufrufen. Wo immer der Aufruf von RenderBody platziert ist, wird der Inhalt der Ansicht gerendert.

Abschnitte

Optional kann ein Layout auf mindestens einen Abschnitt verweisen, indem es RenderSection aufruft. Abschnitte geben an, wo bestimmte Seitenelemente platziert werden sollen. Jeder Aufruf von RenderSection kann angeben, ob dieser Abschnitt erforderlich ist:

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

@RenderSection("Scripts", required: false)

Wenn ein erforderlicher Bereich nicht gefunden werden kann, wird eine Ausnahme ausgelöst. Einzelne Ansichten geben den Inhalt an, der innerhalb eines Abschnitts mithilfe der -Syntax gerendert @section Razor werden soll. Wenn eine Seite oder eine Ansicht einen Abschnitt definiert, muss dieser auch gerendert werden. Andernfalls tritt ein Fehler auf.

Eine @section Beispieldefinition in der Razor Seitenansicht:

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

Im vorangehenden Code wird scripts/main.js zum Abschnitt scripts auf einer Seite oder in einer Ansicht hinzugefügt. Andere Seiten oder Ansichten in der gleichen App benötigen dieses Skript möglicherweise nicht und definieren einen Abschnitt zu Skripts.

In der folgenden Markupdatei wird die Datei _ValidationScriptsPartial.cshtml mit dem Partial-Taghilfsprogramm gerendert:

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

Das vorangehende Markup wurde durch den Gerüstbau Identity von generiert.

Die Abschnitte, die auf einer Seite oder in einer Ansicht definiert wurden, stehen nur auf deren Layoutseite zur Verfügung. Teilansichten, Ansichtskomponenten und andere Teile eines Ansichtssystems können nicht auf sie verweisen.

Ignorieren von Abschnitten

Standardmäßig müssen der Text und die Abschnitte einer Inhaltsseite alle von der Layoutseite gerendert werden. Die Razor Ansichts-Engine erzwingt dies, indem nachverfolgt wird, ob der Text und die einzelnen Abschnitte gerendert wurden.

Rufen Sie die Methoden IgnoreBody und IgnoreSection auf, um die Ansichtsengine anzuweisen, den Text oder die Abschnitte zu ignorieren.

Der Text und jeder Abschnitt auf Razor einer Seite müssen entweder gerendert oder ignoriert werden.

Importieren gemeinsam verwendeter Anweisungen

Ansichten und Seiten können Razor -Anweisungen verwenden, um Namespaces zu importieren und Abhängigkeitsinjektion zu verwenden. Anweisungen, die von mehreren Ansichten gemeinsam verwendet werden, können in einer gemeinsam verwendeten Datei namens _ViewImports.cshtml angegeben werden. Die _ViewImports-Datei unterstützt die folgenden Anweisungen:

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

Die Datei unterstützt keine anderen Razor Funktionen, z. B. Funktionen und Abschnittsdefinitionen.

Eine _ViewImports.cshtml-Beispieldatei:

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

Die Datei _ViewImports.cshtml für eine ASP.NET Core MVC-App befindet sich normalerweise im Ordner Pages (oder Views). Eine Datei _ViewImports.cshtml kann auch in einen anderen Ordner verschoben werden. In diesem Fall wird sie nur auf die Seiten oder Ansichten in diesem Ordner und in dessen Unterordnern angewendet. _ViewImports-Dateien werden beginnend ab der Stammebene verarbeitet und dann einzeln für jeden Ordner bis zum Speicherort der Seite oder der Ansicht selbst. Die _ViewImports-Einstellungen auf der Stammebene werden möglicherweise auf Ordnerebene außer Kraft gesetzt.

Nehmen Sie beispielsweise Folgendes an:

  • Die Datei _ViewImports.cshtml auf der Stammebene enthält @model MyModel1 und @addTagHelper *, MyTagHelper1.
  • Die Datei _ViewImports.cshtml in einem Unterordner enthält @model MyModel2 und @addTagHelper *, MyTagHelper2.

Seiten und Ansichten im Unterordner haben Zugriff auf beide Taghilfsprogramme und das Modell MyModel2.

Wenn sich mehrere Dateien namens _ViewImports.cshtml in der Hierarchie befinden, umfasst das kombinierte Verhalten der Anweisungen Folgendes:

  • @addTagHelper, @removeTagHelper: werden nach der Reihe ausgeführt
  • @tagHelperPrefix: dasjenige, das der Ansicht am Nächsten ist, setzt die anderen außer Kraft
  • @model: dasjenige, das der Ansicht am Nächsten ist, setzt die anderen außer Kraft
  • @inherits: dasjenige, das der Ansicht am Nächsten ist, setzt die anderen außer Kraft
  • @using: alle einbezogen; Duplikate werden ignoriert
  • @inject: dasjenige, das der Ansicht am Nächsten ist, setzt für jede Eigenschaft alle anderen mit dem gleichen Namen außer Kraft

Ausführen von Code vor jeder Ansicht

Code, der ausgeführt werden muss, bevor die einzelnen Ansichten oder Seiten in die Datei _ViewStart.cshtml platziert werden. Gemäß der Konvention befindet sich die Datei _ViewStart.cshtml im Ordner Seiten (oder Ansichten). Die in _ViewStart.cshtml aufgelisteten Anweisungen werden vor jeder vollständigen Ansicht (also keine Layouts und keine Teilansichten) ausgeführt. _ViewStart.cshtml ist genauso wie ViewImports.cshtml hierarchisch. Wenn eine Datei namens _ViewStart.cshtml im Ordner „Ansichten“ oder „Seiten“, der mit einem Controller verknüpft ist, definiert wird, wird sie nach derjenigen ausgeführt, die im Stamm des Ordners Seiten (oder Ansichten) definiert wurde (falls vorhanden).

Ein Beispiel für die Datei _ViewStart.cshtml:

@{
    Layout = "_Layout";
}

Die oben stehende Datei gibt an, dass alle Ansichten das Layout _Layout.cshtml verwenden.

_ViewStart.cshtml und _ViewImports.cshtml werden in der Regel nicht in den Ordner /Pages/Shared (oder /Views/Shared) platziert. Die Versionen dieser Dateien auf Anwendungsebene sollten direkt in den Ordner /Pages (oder /Views) platziert werden.