Layout in ASP.NET Core

Von Steve Smith und Dave Brock

Seiten und Ansichten teilen häufig visuelle und programmgesteuerte Elemente. Dieser Artikel demonstriert Folgendes:

  • Verwenden Sie allgemeine Layouts.
  • Freigabedirektiven.
  • Führen Sie allgemeinen Code vor dem Rendern von Seiten oder Ansichten aus.

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. Für diesen Artikel sind die Unterschiede minimal:

  • Razor Seiten befinden sich im Ordner "Seiten" .
  • Controller mit Ansichten verwenden einen Ansichtenordner für Ansichten.

Was ist ein Layout?

Die meisten Web-Apps verfügen über ein gemeinsames Layout, das dem Benutzer eine konsistente Benutzererfahrung bietet, während er von Seite zu Seite navigiert. Das Layout enthält in der Regel allgemeine Benutzeroberflächenelemente wie die App-Kopfzeile, navigations- oder Menüelemente und Fußzeile.

Beispiel für seitenlayout

Allgemeine HTML-Strukturen wie Skripts und Stylesheets werden auch häufig von vielen Seiten in einer App verwendet. Alle diese freigegebenen Elemente können in einer Layoutdatei definiert werden, auf die jede Ansicht, die in der App verwendet wird, dann referenziert werden kann. Layouts reduzieren doppelten Code in Ansichten.

In der Konvention heißt _Layout.cshtmldas Standardlayout für eine ASP.NET Core-App. Die Layoutdateien für neue ASP.NET Core-Projekte, die mit den Vorlagen erstellt wurden, sind:

  • Razor Seiten: Pages/Shared/_Layout.cshtml

    Ordner

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

    Ordner

Das Layout definiert eine Vorlage auf oberster Ebene für Ansichten in der App. Apps benötigen kein Layout. Apps können mehrere Layouts definieren, wobei unterschiedliche Ansichten unterschiedliche Layouts angeben.

Der folgende Code zeigt die Layoutdatei für ein Vorlage-erstelltes Projekt mit einem Controller und Ansichten:

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

Angeben eines Layouts

Razor-Ansichten verfügen über eine Layout-Eigenschaft Einzelne Ansichten geben ein Layout an, indem Sie diese Eigenschaft festlegen:

@{
    Layout = "_Layout";
}

Das angegebene Layout kann einen vollständigen Pfad (z. B. /Pages/Shared/_Layout.cshtml oder /Views/Shared/_Layout.cshtml) oder einen teilweisen Namen (Beispiel: _Layout) verwenden. Wenn ein Teilname angegeben wird, sucht das Razor Ansichtsmodul mithilfe seines standardmäßigen Ermittlungsprozesses nach der Layoutdatei. Der Ordner, in dem die Handlermethode (oder der Controller) vorhanden ist, wird zuerst durchsucht, gefolgt vom Ordner "Freigegeben" . Dieser Ermittlungsprozess ist identisch mit dem Prozess, der zum Ermitteln von Teilansichten verwendet wird.

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

Abschnitte

Ein Layout kann optional auf einen oder mehrere Abschnitte verweisen, indem es RenderSection aufruft. Abschnitte bieten eine Möglichkeit zum Organisieren, wo bestimmte Seitenelemente platziert werden sollen. Jeder Aufruf RenderSection kann angeben, ob dieser Abschnitt erforderlich oder optional ist:

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

@RenderSection("Scripts", required: false)

Wenn ein erforderlicher Abschnitt nicht gefunden wird, 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 Ansicht einen Abschnitt definiert, muss er gerendert werden (oder ein Fehler tritt auf).

@section Beispieldefinition in der Razor Seitenansicht:

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

Im vorherigen Code wird scripts/main.js dem scripts Abschnitt auf einer Seite oder Ansicht hinzugefügt. Andere Seiten oder Ansichten in derselben App erfordern dieses Skript möglicherweise nicht und definieren keinen Skriptabschnitt.

Das folgende Markup verwendet den Partial Tag Helper, um _ValidationScriptsPartial.cshtml zu rendern:

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

Gerüstbau Identity generierte das vorangehende Markup.

Abschnitte, die in einer Seite oder Ansicht definiert sind, sind nur auf der unmittelbaren Layoutseite verfügbar. Teilansichten, Ansichtskomponenten und andere Teile eines Ansichtssystems können nicht auf sie verweisen.

Ignorieren von Abschnitten

Standardmäßig muss die Layoutseite den Textkörper und alle Abschnitte auf einer Inhaltsseite rendern. Die Razor-Ansichts-Engine erzwingt dies, indem sie erfasst, ob der Text und jeder Abschnitt gerendert wurde.

Rufen Sie die Methoden IgnoreBody und IgnoreSection auf, um die View-Engine anzuweisen, den Body oder die Abschnitte zu ignorieren.

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

Importieren gemeinsam verwendeter Anweisungen

Ansichten und Seiten können Razor-Direktiven verwenden, um Namespaces zu importieren und Dependency Injection zu verwenden. Richtlinien, die von vielen Ansichten gemeinsam verwendet werden, können in einer gemeinsamen _ViewImports.cshtml Datei angegeben werden. Die _ViewImports Datei unterstützt die folgenden Direktiven:

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

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

Beispieldatei _ViewImports.cshtml :

@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 seiner Unterordner angewendet. _ViewImports Dateien werden beginnend auf der Stammebene und dann für jeden Ordner verarbeitet, der zum Speicherort der Seite oder Ansicht selbst führt. _ViewImports Einstellungen, die auf der Root-Ebene angegeben sind, können auf Ordner-Ebene überschrieben werden.

Nehmen wir 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: Alle in der Reihenfolge ausführen.
  • @tagHelperPrefix: Das der Ansicht am nächsten liegende, setzt die anderen außer Kraft.
  • @model: Das der Ansicht am nächsten liegende, setzt die anderen außer Kraft.
  • @inherits: Das der Ansicht am nächsten liegende, setzt die anderen außer Kraft.
  • @using: Alle sind enthalten; Duplikate werden ignoriert.
  • @inject: Das der Ansicht am nächsten liegende setzt alle anderen mit dem gleichen Eigenschaftsnamen 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 soll. Üblicherweise befindet sich die _ViewStart.cshtml-Datei im Ordner „Seiten“ (oder „Ansichten“). Die darin _ViewStart.cshtml aufgeführten Anweisungen werden vor jeder Vollansicht ausgeführt (keine Layouts und keine Teilansichten). 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.

Beispieldatei _ViewStart.cshtml :

@{
    Layout = "_Layout";
}

Die vorangehende 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) abgelegt. Die Versionen dieser Dateien auf App-Ebene sollten direkt im Ordner /Pages (oder /Views) platziert werden.