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 für ASP.NET Core MVC erläutert: Razor Seiten und Controller mit Ansichten. In diesem Thema sind die Unterschiede minimal:

  • Razor Seiten befinden sich im Ordner "Seiten" .
  • 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 Seiten: 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 Teilnamen (Beispiel: _Layout) verwenden. Wenn ein Teilname bereitgestellt wird, sucht das Razor Ansichtsmodul mithilfe des Standardermittlungsprozesses nach 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 in einem Abschnitt mithilfe der @sectionRazor Syntax gerendert werden soll. Wenn eine Seite oder eine Ansicht einen Abschnitt definiert, muss dieser auch gerendert werden. Andernfalls tritt ein Fehler auf.

@section Beispieldefinition in der Razor Seitenansicht:

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

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

Im folgenden Markup wird die Teiltaghilfe zum Rendern_ValidationScriptsPartial.cshtmlverwendet:

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

Das vorherige Markup wurde durch Gerüsterstellung Identitygeneriert.

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. Das Razor Ansichtsmodul erzwingt dies durch Nachverfolgen, ob der Textkörper und jeder Abschnitt gerendert wurde.

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

Der Textkörper und jeder Abschnitt in einer Razor Seite muss entweder gerendert oder ignoriert werden.

Importieren gemeinsam verwendeter Anweisungen

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

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

Die Datei unterstützt keine anderen Razor Features, 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 _ViewImports.cshtml Datei für eine ASP.NET Core MVC-App wird in der Regel im Ordner "Seiten" (oder "Ansichten") platziert. Eine _ViewImports.cshtml Datei kann in einem beliebigen Ordner platziert werden, in diesem Fall wird sie nur auf Seiten oder Ansichten innerhalb dieses Ordners und dessen Unterordner 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 Stammebenendatei _ViewImports.cshtml enthält @model MyModel1 und @addTagHelper *, MyTagHelper1.
  • Eine Unterordnerdatei _ViewImports.cshtml enthält @model MyModel2 und @addTagHelper *, MyTagHelper2.

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

Wenn mehrere _ViewImports.cshtml Dateien in der Dateihierarchie gefunden werden, sind die kombinierten Verhaltensweisen der Direktiven:

  • @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 jede Ansicht oder Seite in der _ViewStart.cshtml Datei platziert werden muss. In der Konvention befindet sich die _ViewStart.cshtml Datei 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. Wie ViewImports.cshtml ist _ViewStart.cshtml hierarchisch. Wenn eine _ViewStart.cshtml Datei im Ordner "Ansicht" oder "Seiten" definiert ist, wird sie nach dem im Stammverzeichnis des Ordners "Seiten " (oder "Ansichten") (falls vorhanden) definierten Datei ausgeführt.

Eine _ViewStart.cshtml-Beispieldatei:

@{
    Layout = "_Layout";
}

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

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