Ansichten in ASP.NET Core MVC

Von Steve Smith und Dave Brock

In diesem Artikel werden die Ansichten erläutert, die in ASP.NET Core MVC-Anwendungen verwendet werden. Informationen zu Razor Pages finden Sie unter Einführung in Razor Pages in ASP.NET Core.

Im Muster Model-View-Controller (MVC) verarbeitet die Ansicht die Darstellung der App-Daten und der Benutzerinteraktion. Bei einer Ansicht handelt es sich um eine HTML-Vorlage mit eingebettetem Razor-Markup. Bei Razor-Markup handelt es sich um Code, der mit HTML-Markup interagiert, um eine Webseite zu generieren, die an den Client gesendet wird.

In ASP.NET Core MVC sind Ansichten .cshtml-Dateien, die die Programmiersprache C# in Razor-Markup verwenden. In der Regel werden Ansichtsdateien in Ordnern gruppiert, die für jeden Controller der App benannt werden. Die Ordner werden im Ordner Views im Stammverzeichnis der App gespeichert:

Views folder in Solution Explorer of Visual Studio is open with the Home folder open to show About.cshtml, Contact.cshtml, and Index.cshtml files

Der Home-Controller wird durch einen Home-Ordner innerhalb des Ordners Views dargestellt. Der Ordner Home enthält die Ansichten für die Webseiten About, Contact und Index (Homepage). Wenn ein*e Benutzer*in eine dieser drei Webseiten aufruft, legen Controlleraktionen im Home-Controller fest, welche der drei Ansichten verwendet werden, um Webseiten zu erstellen und diese an den oder die Benutzer*in zurückzugeben.

Verwenden Sie Layouts, damit die Abschnitte der Webseiten konsistent angezeigt werden und die Wiederholung von Code vermieden wird. Layouts bestehen in der Regel aus der Kopfzeile, der Navigation, Menüelementen und der Fußzeile. Die Kopf- und die Fußzeile enthalten in der Regel Markupbausteine für viele Metadatenelemente sowie Links zu Skripts und Stilelemente. Mithilfe von Layouts können Sie die Markupbausteine in Ihren Ansichten vermeiden.

Über Teilansichten wird weniger Code dupliziert, indem wiederverwendbare Bestandteile der Ansichten verwaltet werden. Sie sind z.B. nützlich für Autorenbiografien auf einem Blog, die in verschiedenen Ansichten angezeigt werden. Bei einer Autorenbiografie handelt es sich um gewöhnlichen Inhalt von Ansichten. Sie erfordern keinen Code, der ausgeführt werden muss, um den Inhalt für die Webseite herzustellen. Die Ansicht kann auf die Inhalte der Autorenbiografie über eine Modellbindung zugreifen. Daher sollten idealerweise Teilansichten für diese Art von Inhalt verwendet werden.

Über Ansichtskomponenten können Sie genauso wie über Teilansichten Wiederholungen von Code reduzieren. Sie sind besonders geeignet für Inhalt von Ansichten, für den Code auf dem Server ausgeführt werden muss, um die Webseite zu rendern. Ansichtskomponenten sind nützlich, wenn der gerenderte Inhalt Datenbankinformationen erfordert, z.B. bei einem Warenkorb auf einer Website. Ansichtskomponenten sind nicht auf Modellbindungen beschränkt, um Webseitenausgaben herzustellen.

Vorteile der Verwendung von Ansichten

Über Ansichten kann in einer MVC-App eine Trennung von Belangen erfolgen, indem das Markup der Benutzeroberfläche von anderen Bestandteilen der App getrennt wird. Das SoC-Design macht Ihre App modularer. Dies hat folgende Vorteile:

  • Die App kann einfacher verwaltet werden, da sie besser organisiert ist. Ansichten werden in der Regel nach App-Features gruppiert. Dadurch können Sie zugehörige Ansichten leichter finden, wenn Sie an einem Feature arbeiten.
  • Die Bestandteile der App sind lose miteinander verknüpft. Sie können die Ansichten der App getrennt von der Geschäftslogik und den Datenzugriffskomponenten erstellen und aktualisieren. Sie können die Ansichten der App verändern, müssen dafür aber nicht unbedingt andere Bestandteile der App aktualisieren.
  • Sie können die Bestandteile der Benutzeroberfläche der App leichter testen, da es sich bei den Ansichten um voneinander getrennte Einheiten handelt.
  • Durch die verbesserte Organisation sinkt die Wahrscheinlichkeit, dass Sie versehentlich Code für die Benutzeroberfläche wiederholt schreiben.

Erstellen einer Ansicht

Ansichten, die nur für bestimmte Controller gelten, werden im Ordner Views/[ControllerName] erstellt. Ansichten, die von mehreren Controllern verwendet werden können, werden im Ordner Views/Shared gespeichert. Wenn Sie eine Ansicht erstellen möchten, fügen Sie eine neue Datei hinzu, und geben Sie ihr denselben Namen wie der zugehörigen Controlleraktion mit der Erweiterung .cshtml. Wenn Sie eine Ansicht erstellen möchten, die mit der Aktion About im Home-Controller übereinstimmt, erstellen Sie eine About.cshtml-Datei im Ordner Views/Home:

@{
    ViewData["Title"] = "About";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p>Use this area to provide additional information.</p>

Das Razor-Markup beginnt mit dem Symbol @. Führen Sie C#-Anweisungen aus, indem Sie C#-Code in den Razor-Codeblöcken speichern, die von geschweiften Klammern ({ ... }) umgeben sind. Weitere Informationen finden Sie im obenstehenden Beispiel für die Zuweisung von „Hilfe“ zu ViewData["Title"]. Sie können Werte innerhalb von HTML-Code angeben, indem Sie auf den Wert mit dem Symbol @ verweisen. Weitere Informationen finden Sie in den Inhalten der obenstehenden Elemente <h2> und <h3>.

Der obenstehende Inhalt der Ansicht ist nur ein Teil der gesamten Webseite, die für den Benutzer gerendert wird. Der Rest des Seitenlayouts und andere häufig auftretende Aspekte werden in anderen Ansichtsdateien angegeben. Weitere Informationen dazu finden Sie im Artikel Layout.

Angeben von Ansichten durch Controller

Ansichten werden in der Regel von Aktionen als ViewResult zurückgegeben. Dabei handelt es sich um eine Art ActionResult. Über Ihre Aktionsmethode kann eine ViewResult-Klasse direkt erstellt und zurückgegeben werden. Diese Methode wird allerdings selten genutzt. Da die meisten Controller von Controller erben, können Sie einfach die View-Hilfsprogrammmethode verwenden, um ViewResult zurückzugeben:

HomeController.cs:

public IActionResult About()
{
    ViewData["Message"] = "Your application description page.";

    return View();
}

Wenn diese Aktion zurückgegeben wird, wird die im letzten Abschnitt angezeigte About.cshtml-Ansicht als folgende Webseite gerendert:

About page rendered in the Edge browser

Für die View-Hilfsprogrammmethode gibt es einige Überladungen. Sie können bei Bedarf folgende Elemente angeben:

  • Eine explizite Ansicht, die zurückgegeben werden soll:

    return View("Orders");
    
  • Ein Modell, das an die Ansicht übergeben werden soll:

    return View(Orders);
    
  • Sowohl eine Ansicht als auch ein Modell:

    return View("Orders", Orders);
    

Ansichtsermittlung

Wenn eine Aktion eine Ansicht zurückgibt, wird ein Prozess namens Ansichtsermittlung ausgelöst. Über diesen Prozess wird auf Grundlage des Ansichtsnamens festgelegt, welche Ansichtsdatei verwendet wird.

Standardmäßig gibt die View-Methode (return View();) eine Ansicht zurück, die denselben Namen wie die Aktionsmethode besitzt, über die diese aufgerufen wird. Der AboutActionResult-Methodenname Hilfe des Controllers wird verwendet, um nach einer Ansichtsdatei mit dem Namen About.cshtml zu suchen. Zuerst sucht die Runtime im Ordner Views/[ControllerName] nach der Ansicht. Wenn keine passende Ansicht gefunden wird, wird im Ordner Shared nach der Ansicht gesucht.

Es macht keinen Unterschied, ob Sie implizit ViewResult mit return View(); zurückgeben, oder den Ansichtsnamen mit return View("<ViewName>"); explizit an die View-Methode übergeben. In beiden Fällen sucht die Ansichtsermittlung nach einer passenden Ansichtsdatei in diesem Ordner:

  1. Views/\[ControllerName]/\[ViewName].cshtml
  2. Views/Shared/\[ViewName].cshtml

Anstelle eines Ansichtsnamens kann auch ein Pfad zu einer Ansichtsdatei verwendet werden. Wenn Sie einen absoluten Pfad im Stammverzeichnis der App verwenden (der mit „/“ oder „~/“ beginnt), muss die Erweiterung .cshtml angegeben sein:

return View("Views/Home/About.cshtml");

Sie können auch einen relativen Pfad verwenden, um Ansichten in verschiedenen Verzeichnissen ohne die Erweiterung .cshtml anzugeben. In der HomeController-Klasse können Sie die Ansicht Index in Ihrer Manage-Ansicht mit einem relativen Pfad angeben:

return View("../Manage/Index");

Genauso können Sie auch das aktuelle controllerspezifische Verzeichnis mit dem Präfix „./“ angeben:

return View("./About");

Teilansichten und Ansichtskomponenten verwenden ähnliche (aber nicht identische) Ermittlungsmechanismen.

Sie können die Standardkonvention zum Suchen von Ansichten in der App anpassen, indem Sie eine benutzerdefinierte IViewLocationExpander-Schnittstelle verwenden.

Die Ansichtsermittlung ist davon abhängig, ob Ansichtsdateien über Dateinamen gefunden werden. Wenn das zugrunde liegende Dateisystem die Groß-/Kleinschreibung beachtet, wird wahrscheinlich auch bei den Ansichtsnamen zwischen Groß- und Kleinschreibung unterschieden. Damit die Kompatibilität für alle Betriebssysteme eingehalten werden kann, müssen Sie Groß-/Kleinbuchstaben zwischen dem Controller und den Aktionsnamen sowie den zugeordneten Ansichtsordnern und Dateinamen aufeinander abstimmten. Wenn ein Fehler ausgelöst wird und eine Ansichtsdatei nicht gefunden werden kann, während Sie mit einem Dateisystem arbeiten, das zwischen Groß- und Kleinbuchstaben unterscheidet, bestätigen Sie, dass die Groß-/Kleinschreibung der gesuchten Ansichtsdatei mit dem tatsächlichen Dateinamen der Ansicht übereinstimmt.

Halten Sie sich an die bewährten Methoden zum Organisieren der Dateistruktur Ihrer Ansichten, um die Beziehungen zwischen Controllern, Aktionen und Ansichten auf die Verwaltbarkeit und Klarheit auszurichten.

Übergeben von Daten an Ansichten

Übergeben Sie Daten über verschiedene Ansätze an Ansichten:

  • Stark typisierte Daten: viewmodel
  • Schwach typisierte Daten
    • ViewData (ViewDataAttribute)
    • ViewBag

Stark typisierte Daten (viewmodel)

Wenn Sie Stabilität wünschen, sollten Sie einen Modell-Typen in der Ansicht angeben. Das Modell wird häufig als Ansichtsmodell bezeichnet. Übergeben Sie eine Instanz des Ansichtsmodelltyps an die Ansicht aus der Aktion.

Wenn Sie ein Ansichtsmodell verwenden, um eine Ansicht zu übergeben, kann die Ansicht die Vorteile der starken Typüberprüfung nutzen. Man spricht von starker Typisierung (oder stark typisiert als Adjektiv), wenn es für jede Variable und jede Konstante einen explizit definierten Typ gibt, z.B. string, int oder DateTime. Die Gültigkeit der in der Ansicht verwendeten Typen wird zur Kompilierzeit überprüft.

Visual Studio und Visual Studio Code erstellen Listen von stark typisierten Klassenmembern mithilfe des Features IntelliSense. Wenn Sie die Eigenschaften eines Ansichtsmodell anzeigen wollen, geben Sie den Namen der Variablen für dieses an, und setzen Sie einen Punkt (.). Dadurch können Sie Code schneller schreiben, und Sie machen weniger Fehler.

Geben Sie mithilfe der @model-Anweisung ein Modell an. Verwenden Sie das Modell mit @Model:

@model WebApplication1.ViewModels.Address

<h2>Contact</h2>
<address>
    @Model.Street<br>
    @Model.City, @Model.State @Model.PostalCode<br>
    <abbr title="Phone">P:</abbr> 425.555.0100
</address>

Der Controller übergibt das Modell als Parameter, um es für die Ansicht bereitzustellen:

public IActionResult Contact()
{
    ViewData["Message"] = "Your contact page.";

    var viewModel = new Address()
    {
        Name = "Microsoft",
        Street = "One Microsoft Way",
        City = "Redmond",
        State = "WA",
        PostalCode = "98052-6399"
    };

    return View(viewModel);
}

Es gibt keine Einschränkungen der Modelltypen, die in einer Ansicht enthalten sein sollten. Es wird empfohlen, Plain Old CLR Object-Ansichtsmodelle (POCO) mit wenigen oder gar keinen definierten Methoden zu verwenden. In der Regel werden Ansichtsmodellklassen weder im Ordner Models noch in einem separaten ViewModels-Ordner im Stammverzeichnis der App gespeichert. Bei dem im zuvor genannten Beispiel verwendeten Address-Ansichtsmodell handelt es sich um ein POCO-Ansichtsmodell, das in einer Datei mit dem Namen Address.cs gespeichert ist:

namespace WebApplication1.ViewModels
{
    public class Address
    {
        public string Name { get; set; }
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
    }
}

Es ist möglich, für die Ansichtsmodelltypen und Unternehmensmodelltypen dieselben Klassen zu verwenden. Wenn Sie allerdings unterschiedliche Modelle verwenden, können Ihre Ansichten unabhängig von der Geschäftslogik und den Bestandteilen zum Datenzugriff Ihrer App variieren. Wenn Sie Modelle und Ansichtsmodelle trennen, wird mehr Sicherheit geboten, wenn Modelle die Modellbindung und die Validierung von Daten verwenden, die vom Benutzer an die App gesendet werden.

Schwach typisierte Daten (ViewData, [ViewData]-Attribut und ViewBag)

ViewBag ist standardmäßig nicht für die Verwendung in Razor Pages-PageModel-Klassen verfügbar.

Ansichten haben nicht nur Zugriff auf stark typisierte Datensammlungen, sondern auch auf schwach typisierte (auch als lose typisiert bezeichnet). Im Gegensatz zu starken Typen werden bei schwachen Typen (oder losen Typen) nicht explizit die Datentypen deklariert, die Sie verwenden. Sie können die Sammlung schwach typisierter Daten verwenden, um kleinere Datenmengen an Controller und Ansichten zu übergeben oder sie ihnen zu entnehmen.

Übergeben von Daten zwischen... Beispiel
einem Controller und einer Ansicht Auffüllen einer Dropdownliste mit Daten
einer Ansicht und einer Layoutansicht Legt den <title>-Elementinhalt in der Layoutansicht über eine Ansichtsdatei fest
einer Teilansicht und einer Ansicht Ein Widget, das Daten anzeigt, die der Webseite zugrunde liegen, die der Benutzer angefordert hat.

Auf diese Sammlung kann entweder über die Eigenschaft ViewData oder über die Eigenschaft ViewBag auf Controller und Ansichten verwiesen werden. Die ViewData-Eigenschaft ist ein Wörterbuch, das aus schwach typisierten Objekten besteht. Bei der ViewBag-Eigenschaft handelt es sich um einen Wrapper um ViewData, der dynamische Eigenschaften für die zugrunde liegende ViewData-Sammlung bereitstellt. Hinweis: Bei Lookupvorgängen für Schlüssel wird für ViewData und ViewBag die Groß-/Kleinschreibung nicht beachtet.

ViewData und ViewBag werden zur Laufzeit dynamisch aufgelöst. Da in diesen Elementen keine Typüberprüfung zur Kompilierzeit enthalten sind, sind beide in der Regel fehleranfälliger als Ansichtsmodelle. Aus diesem Grund verwenden Entwickler ViewData und ViewBag selten oder nie.

ViewData

ViewData ist ein ViewDataDictionary-Objekt, auf das über string-Schlüssel zugegriffen wird. Zeichenfolgendaten können gespeichert und ohne Umwandlung direkt verwendet werden. Trotzdem müssen Sie für die Extraktion andere ViewData-Objektwerte in bestimmte Typen umwandeln. Sie können ViewData verwenden, um Daten von Controllern an Ansichten und innerhalb von Ansichten zu übergeben, einschließlich Teilansichten und Layouts.

Im Folgenden finden Sie ein Beispiel, über das Werte für eine Begrüßung und eine Anrede mithilfe von ViewData in einer Aktion festgelegt werden:

public IActionResult SomeAction()
{
    ViewData["Greeting"] = "Hello";
    ViewData["Address"]  = new Address()
    {
        Name = "Steve",
        Street = "123 Main St",
        City = "Hudson",
        State = "OH",
        PostalCode = "44236"
    };

    return View();
}

Arbeiten Sie mit den Daten in einer Ansicht:

@{
    // Since Address isn't a string, it requires a cast.
    var address = ViewData["Address"] as Address;
}

@ViewData["Greeting"] World!

<address>
    @address.Name<br>
    @address.Street<br>
    @address.City, @address.State @address.PostalCode
</address>

[ViewData]-Attribut

Ein anderer Ansatz, der ViewDataDictionary verwendet, ist ViewDataAttribute. Die Werte der Eigenschaften in Controllern oder Razor Pages-Modellen, die mit dem [ViewData]-Attribut gekennzeichnet sind, werden im Wörterbuch gespeichert und daraus geladen.

Im folgenden Beispiel enthält der Home-Controller eine Title-Eigenschaft, die mit [ViewData] gekennzeichnet ist. Die About-Methode legt den Titel der Infoansicht fest:

public class HomeController : Controller
{
    [ViewData]
    public string Title { get; set; }

    public IActionResult About()
    {
        Title = "About Us";
        ViewData["Message"] = "Your application description page.";

        return View();
    }
}

Im Layout wird der Titel aus dem ViewData-Wörterbuch gelesen:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"] - WebApplication</title>
    ...

ViewBag

ViewBag ist standardmäßig nicht für die Verwendung in Razor Pages-PageModel-Klassen verfügbar.

ViewBag ist ein Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.DynamicViewData-Objekt, das den dynamischen Zugriff auf die in ViewData gespeicherten Objekte ermöglicht. Es ist angenehmer, mit ViewBag zu arbeiten, da keine Umwandlung erforderlich ist. Im Folgenden finden Sie ein Beispiel, in dem dargestellt wird, wie Sie mit ViewBag das gleiche Ergebnis wie mit ViewData erzielen:

public IActionResult SomeAction()
{
    ViewBag.Greeting = "Hello";
    ViewBag.Address  = new Address()
    {
        Name = "Steve",
        Street = "123 Main St",
        City = "Hudson",
        State = "OH",
        PostalCode = "44236"
    };

    return View();
}
@ViewBag.Greeting World!

<address>
    @ViewBag.Address.Name<br>
    @ViewBag.Address.Street<br>
    @ViewBag.Address.City, @ViewBag.Address.State @ViewBag.Address.PostalCode
</address>

Gleichzeitiges Verwenden von ViewData und ViewBag

ViewBag ist standardmäßig nicht für die Verwendung in Razor Pages-PageModel-Klassen verfügbar.

Da ViewData und ViewBag beide auf dieselbe zugrunde liegende ViewData-Sammlung verweisen, können Sie sowohl ViewData als auch ViewBag verwenden, und zwischen beiden Elementen wechseln, wenn Sie Werte schreiben und lesen.

Legen Sie oben in einer ViewBag-Ansicht mithilfe von ViewData den Titel und mithilfe von About.cshtml die Beschreibung fest:

@{
    Layout = "/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "About Contoso";
    ViewData["Description"] = "Let us tell you about Contoso's philosophy and mission.";
}

Lesen Sie die Eigenschaften, aber verwenden Sie ViewData und ViewBag in umgekehrter Reihenfolge. Rufen Sie in der _Layout.cshtml-Datei mithilfe von ViewData den Titel und mithilfe von ViewBag die Beschreibung ab:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"]</title>
    <meta name="description" content="@ViewBag.Description">
    ...

Bedenken Sie, dass für Zeichenfolgen mit ViewData keine Umwandlung erforderlich ist. @ViewData["Title"] kann ohne Umwandlung verwendet werden.

Sie können ViewData und ViewBag gleichzeitig verwenden und zwischen dem Lesen und Schreiben der Eigenschaften abwechseln. Das folgende Markup wird gerendert:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>About Contoso</title>
    <meta name="description" content="Let us tell you about Contoso's philosophy and mission.">
    ...

Zusammenfassung der Unterschiede zwischen ViewData und ViewBag

ViewBag ist standardmäßig nicht für die Verwendung in Razor Pages-PageModel-Klassen verfügbar.

  • ViewData
    • Wird von ViewDataDictionary abgeleitet und verfügt daher über Wörterbucheigenschaften wie ContainsKey, Add, Remove und Clear, die nützlich sein können.
    • Schlüssel sind Zeichenfolgen im Wörterbuch. Daher sind Leerzeichen erlaubt. Beispiel: ViewData["Some Key With Whitespace"]
    • Jeder Typ, der von string abweicht, muss in der Ansicht umgewandelt werden, sodass ViewData verwendet werden kann.
  • ViewBag
    • Wird von Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.DynamicViewData abgeleitet und ermöglicht daher die Erstellung von dynamischen Eigenschaften über die Punktnotation (@ViewBag.SomeKey = <value or object>), und es ist keine Umwandlung erforderlich. Über die Syntax von ViewBag können Controller und Ansichten schneller hinzugefügt werden.
    • Es ist einfacher, nach NULL-Werten zu suchen. Beispiel: @ViewBag.Person?.Name

Verwendung von ViewData oder ViewBag

ViewData und ViewBag sind beides gültige Ansätze, wenn Sie kleinere Datenmengen zwischen Controllern und Ansichten übergeben möchten. Sie können beliebig entscheiden, welche Methode Sie verwenden möchten. Sie können zwar ViewData- und ViewBag-Objekte miteinander vermischen, jedoch ist es einfacher, den Code zu lesen und zu verwalten, wenn nur ein Ansatz verwendet wird. Beide Ansätze werden zur Laufzeit dynamisch aufgelöst, wodurch häufig Laufzeitfehler entstehen. Einige Entwicklerteams vermeiden diese Ansätze daher.

Dynamische Ansichten

Ansichten, die einen Modelltyp nicht mit @model deklarieren, an die aber eine Modellinstanz übergeben wird (z.B. return View(Address);), können dynamisch auf die Eigenschaften der Instanz verweisen:

<address>
    @Model.Street<br>
    @Model.City, @Model.State @Model.PostalCode<br>
    <abbr title="Phone">P:</abbr> 425.555.0100
</address>

Dieses Feature bietet zwar Flexibilität, jedoch weder Kompilierungsschutz noch IntelliSense. Wenn die Eigenschaft nicht vorhanden ist, löst die Webseitengenerierung zur Laufzeit einen Fehler aus.

Weitere Ansichtsfeatures

Mithilfe von Taghilfsprogrammen können Sie einfach serverseitiges Verhalten zu vorhandenen HTML-Tags hinzufügen. Wenn Sie Taghilfsprogramme verwenden, müssen Sie keinen benutzerdefinierten Code oder Hilfsprogramme in Ihren Ansichten schreiben. Taghilfsprogramme werden als Attribute für HTML-Elemente angewendet und werden von Editors ignoriert, da sie diese nicht verarbeiten können. Dadurch können Sie Ansichtsmarkups in verschiedenen Tools bearbeiten und rendern.

Sie können benutzerdefinierte HTML-Markups über verschiedene integrierte HTML-Hilfsprogramme generieren. Eine komplexere Logik von Benutzeroberflächen kann über Ansichtskomponenten verarbeitet werden. Ansichtskomponenten stellen dieselben SoC-Designs bereit, die Controller und Ansichten bereitstellen. Wenn diese verwendet werden, werden keine Aktionen und Ansichten benötigt, die Daten verarbeiten, die von häufig verwendeten Benutzeroberflächenelementen verwendet werden.

Wie viele andere Aspekte von ASP.NET Core unterstützen Ansichten Dependency Injection und lassen zu, dass Dienste in Ansichten eingefügt werden.

CSS-Isolation

Isolieren Sie zur Reduzierung oder Vermeidung CSS-Formatvorlagen auf einzelne Seiten, Ansichten und Komponenten:

  • Abhängigkeiten von globalen Stilen, die eine Herausforderung darstellen können
  • Formatkonflikte in geschachtelten Inhalten

Um eine bereichsbezogene CSS-Datei für eine Seite oder Ansicht hinzuzufügen, platzieren Sie die CSS-Stile in der Begleitdatei .cshtml.css, die dem Namen der .cshtml-Datei entspricht. Im folgenden Beispiel liefert eine Index.cshtml.css-Datei CSS-Stile, die nur auf die Index.cshtml-Seite oder -Ansicht angewendet werden.

Pages/Index.cshtml.css (Razor Pages) oder Views/Index.cshtml.css (MVC):

h1 {
    color: red;
}

Die CSS-Isolation erfolgt zum Zeitpunkt der Erstellung. Das Framework schreibt CSS-Selektoren so um, dass sie mit Markup übereinstimmen, das von den Seiten oder Ansichten der App gerendert wird. Die umgeschriebenen CSS-Stile werden gebündelt und als statisches Objekt ({APP ASSEMBLY}.styles.css) erzeugt. Der Platzhalter {APP ASSEMBLY} ist der Assemblyname des Projekts. Ein Link zu den gebündelten CSS-Stilen wird im Layout der App platziert.

Im Inhalt von <head> der Datei Pages/Shared/_Layout.cshtml (Razor Pages) oder Views/Shared/_Layout.cshtml (MVC) der App fügen Sie den Link zu den gebündelten CSS-Styles hinzu oder bestätigen ihn:

<link rel="stylesheet" href="~/{APP ASSEMBLY}.styles.css" />

Im folgenden Beispiel lautet der Assemblyname der App WebApp:

<link rel="stylesheet" href="WebApp.styles.css" />

Die in einer bereichsbezogenen CSS-Datei definierten Stile werden nur auf die gerenderte Ausgabe der entsprechenden Datei angewendet. Im vorherigen Beispiel stehen alle CSS-Deklarationen von h1, die an anderer Stelle in der App definiert sind, nicht in Konflikt mit dem Überschriftenstil von Index. CSS- und Vererbungsregeln bleiben für bereichsbezogene CSS-Dateien gültig. Beispielsweise überschreiben Stile, die direkt auf ein <h1>-Element in der Index.cshtml-Datei angewendet werden, die Stile der bereichsbezogenen CSS-Datei in Index.cshtml.css.

Hinweis

Um die Isolation des CSS-Stils beim Bündeln zu gewährleisten, wird der Import von CSS in Razor-Codeblöcken nicht unterstützt.

CSS-Isolation gilt nur für HTML-Elemente. CSS-Isolation wird für Taghilfsprogramme nicht unterstützt.

Innerhalb der gebündelten CSS-Datei ist jede Seite, Ansicht oder Razor-Komponente mit einem Bereichsbezeichner im Format b-{STRING} verknüpft, wobei der Platzhalter {STRING} eine zehnstellige Zeichenfolge ist, die vom Framework generiert wird. Das folgende Beispiel liefert den Stil für das vorherige <h1>-Element der Seite Index einer Razor Pages-App:

/* /Pages/Index.cshtml.rz.scp.css */
h1[b-3xxtam6d07] {
    color: red;
}

Auf der Seite Index, auf der der CSS-Stil aus der gebündelten Datei angewendet wird, wird der Bereichsbezeichner als HTML-Attribut angefügt:

<h1 b-3xxtam6d07>

Der Bezeichner ist für eine App eindeutig. Zum Zeitpunkt der Erstellung wird ein Projektbündel mit der Konvention {STATIC WEB ASSETS BASE PATH}/Project.lib.scp.css erstellt, wobei der Platzhalter {STATIC WEB ASSETS BASE PATH} der statische Basispfad für Webressourcen ist.

Wenn andere Projekte verwendet werden, z. B. NuGet-Pakete oder Razor-Klassenbibliotheken, gilt für die gebündelte Datei Folgendes:

  • Verweise auf Stile erfolgen mithilfe von CSS-Importen.
  • Sie wird nicht als statische Webressource der App veröffentlicht, die die Stile verwendet.

Unterstützung für CSS-Präprozessoren

CSS-Präprozessoren tragen zur Verbesserung der CSS-Entwicklung bei, indem sie Features wie Variablen, Schachtelung, Module, Mischung und Vererbung nutzen. CSS-Isolation unterstützt CSS-Präprozessoren wie Sass oder Less zwar nicht nativ, dennoch können CSS-Präprozessoren nahtlos integriert werden, sofern die Kompilierung des Präprozessors erfolgt, bevor das Framework die CSS-Selektoren während des Buildprozesses umschreibt. Konfigurieren Sie z. B. mithilfe von Visual Studio die vorhandene Präprozessorkompilierung als Aufgabe Vor Build im Aufgabenausführungs-Explorer von Visual Studio.

Viele NuGet-Pakete von Drittanbietern wie z. B. AspNetCore.SassCompiler, können die SASS-/SCSS-Dateien am Anfang des Buildprozesses – noch vor der CSS-Isolation – kompilieren, ohne dass eine Konfiguration erforderlich ist.

Konfiguration der CSS-Isolation

CSS-Isolation ermöglicht die Konfiguration einiger fortgeschrittener Szenarien, z. B. wenn Abhängigkeiten von vorhandenen Tools oder Workflows bestehen.

Anpassen des Formats von Bereichsbezeichnern

In diesem Abschnitt ist der Platzhalter {Pages|Views} entweder Pages für Razor Pages-Apps oder Views für MVC-Apps.

Standardmäßig verwenden Bereichsbezeichner das Format b-{STRING}, wobei der Platzhalter {STRING} eine vom Framework generierte Zeichenfolge mit zehn Zeichen ist. Um das Format der Bereichsbezeichner anzupassen, aktualisieren Sie die Projektdatei mit dem gewünschten Muster:

<ItemGroup>
  <None Update="{Pages|Views}/Index.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Im vorherigen Beispiel ändert der für Index.cshtml.css generierte CSS-Code seinen Bereichsbezeichner von b-{STRING} in custom-scope-identifier.

Verwenden Sie Bereichsbezeichner, um eine Vererbung mit bereichsbezogenen CSS-Dateien zu erzielen. Im folgenden Beispiel für eine Projektdatei enthält eine BaseView.cshtml.css-Datei allgemeine Stile für Ansichten. Eine DerivedView.cshtml.css-Datei erbt diese Stile.

<ItemGroup>
  <None Update="{Pages|Views}/BaseView.cshtml.css" CssScope="custom-scope-identifier" />
  <None Update="{Pages|Views}/DerivedView.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Verwenden Sie den Platzhalteroperator (*), um Bereichsbezeichner für mehrere Dateien freizugeben:

<ItemGroup>
  <None Update="{Pages|Views}/*.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Ändern des Basispfads für statische Webressourcen

Die bereichsbezogene CSS-Datei wird im Stammverzeichnis der App generiert. Verwenden Sie in der Projektdatei die StaticWebAssetBasePath-Eigenschaft, um den Standardpfad zu ändern. Im folgenden Beispiel werden die bereichsbezogene CSS-Datei und die restlichen Ressourcen der App unter dem Pfad _content gespeichert:

<PropertyGroup>
  <StaticWebAssetBasePath>_content/$(PackageId)</StaticWebAssetBasePath>
</PropertyGroup>

Deaktivieren der automatischen Bündelung

Wenn Sie das Verhalten des Frameworks beim Veröffentlichen und Laden bereichsbezogener Dateien zur Laufzeit ändern möchten, verwenden Sie die DisableScopedCssBundling-Eigenschaft. Die Verwendung dieser Eigenschaft bedeutet, dass die isolierten CSS-Dateien durch andere Tools oder Prozesse aus dem Verzeichnis obj übernommen und zur Laufzeit veröffentlicht und geladen werden:

<PropertyGroup>
  <DisableScopedCssBundling>true</DisableScopedCssBundling>
</PropertyGroup>

Unterstützung für Razor-Klassenbibliothek (RCL)

Wenn eine Razor-Klassenbibliothek (RCL) isolierte Stile bereitstellt, zeigt das href-Attribut des <link>-Tags auf {STATIC WEB ASSET BASE PATH}/{PACKAGE ID}.bundle.scp.css, wobei die Platzhalter für Folgendes stehen:

  • {STATIC WEB ASSET BASE PATH}: Basispfad der statischen Webressource
  • {PACKAGE ID}: Der Paketbezeichner der Bibliothek. Der Paketbezeichner ist standardmäßig der Assemblyname des Projekts, wenn der Paketbezeichner nicht in der Projektdatei angegeben ist.

Im folgenden Beispiel:

  • Der Basispfad der statischen Webressource lautet _content/ClassLib.
  • Der Assemblyname der Klassenbibliothek lautet ClassLib.

Pages/Shared/_Layout.cshtml (Razor Pages) oder Views/Shared/_Layout.cshtml (MVC):

<link href="_content/ClassLib/ClassLib.bundle.scp.css" rel="stylesheet">

Weitere Informationen zu RCLs finden Sie in den folgenden Artikeln:

Informationen zur CSS-Isolation in Blazor finden Sie unter CSS-Isolation in Blazor in ASP.NET Core.