Hinzufügen von Razor Pages

Für die Erstellung von dynamischen Webseiten in ASP.NET Core wird Razor verwendet. Razor ist eine leistungsstarke Template-Sprache, die es ermöglicht, C#-Code in HTML-Dateien einzubetten.

Die erste Razor-Seite

Gegeben sei ein einfaches Beispiel einer HTML-Datei:

HTMLindex.html
<!DOCTYPE html>
<html>
<head>
    <title>Meine HTML-Seite</title>
    <meta charset="utf-8">
</head>
<body>
    <h1>Hallo, Welt!</h1>
</body>
</html>

Auf Basis dieses HTML-Dokuments lässt sich nun eine einfache Razor-Seite erstellen. Dafür wird zunächst die Datei umbenannt, sodass der Dateiname das Suffix .cshtml ausweist und in der PascalCase-Schreibweise benannt wird. Nach Konvention befinden sich alle Razor-Seiten in einem Ordner Pages/.

Mit der Anweisung @page, welche die erste Razor-Anweisung einer Seite sein muss, wird die Datei zu einer MVC-Aktion, sodass diese Anforderungen direkt verarbeitet, ohne über einen Controller gehen zu müssen. Bei der Anweisung kann außerdem eine Zeichenfolge für eine benutzerdefinierte Route angegeben werden. Standardmäßig wird die Route auf den Dateinamen basierend generiert. Beispielsweise verarbeitet eine Razor-Seite namens About.cshtml die Anforderungen an /About. Eine Razor-Seite Index.cshtml verarbeitet zusätzlich neben Anforderungen an /Index auch Anfragen an /.

Das folgende Beispiel zeigt eine einfache Razor-Seite:

CSHTMLIndex.cshtml
@page
@namespace MeineRazorDemo.Pages
<!DOCTYPE html>
<html>
<head>
    <title>Meine Seite</title>
    <meta charset="utf-8">
</head>
<body>
    <h1>Hallo, Welt!</h1>
    <p>Aktuell ist es @DateTime.Now.</p>
</body>
</html>

Wie im obigen Beispiel zu sehen, beginnt die Razor-Seite mit der @page-Anweisung. Darauf folgt eine @namespace-Anweisung, um den Namespace für die Razor-Seite zu definieren. Im p-Element wird der aktuelle Zeitpunkt mit der @DateTime.Now-Eigenschaft angezeigt. Wie zu sehen ist, wird ein Wechsel von HTML zu Razor-Syntax durch das @-Symbol gekennzeichnet.

Razor Pages hinzufügen

Um Razor Pages in der ASP.NET Core-Anwendung zu verwenden, müssen die Razor Pages-Dienste in der Program.cs-Datei registriert werden. Dies geschieht durch den Aufruf der AddRazorPages()-Methode auf der IServiceCollection vom WebApplicationBuilder. Die Methode MapRazorPages() fügt Endpunkte für Razor Seiten zu IEndpointRouteBuilder hinzu:

C#Program.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();

var app = builder.Build();

app.MapRazorPages();

app.Run();

Hinzufügen von einem PageModel

Das PageModel kapselt als Codebehind auf Razor-Seite begrenzte Dateneigenschaften und Logikvorgänge sowie die Definition von Seitenhandlern für HTTP-Anforderungen. Jeder Modelltyp erbt von der PageModel-Klasse aus dem Namensraum Microsoft.AspNetCore.Mvc.RazorPages.

Nach Konvention wird für ein PageModel einer Razor-Seite einfach ein Suffix .cs angehängt. Für eine Razor-Seite namens Index.cshtml wäre das entsprechende Codebehind Index.cshtml.cs, teilweise auch IndexModel.cs.

Seitenhandler sind die Methoden, die Browseranforderungen verarbeiten und weisen die Struktur On<Verb> auf. Um also eine einfache GET-Anforderung zu verarbeiten wird ein Seitenhandler OnGet verwendet.

Im folgenden nun ein einfaches Beispiel von einem PageModel mit Logging-Fähigkeiten:

C#Index.cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace MeineRazorDemo.Pages;

public class IndexModel : PageModel
{
    private readonly ILogger _logger;

    public IndexModel(ILogger logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
        _logger.LogInformation("Hello from {page}", nameof(IndexModel));
    }

}

Die Klasse IndexModel erbt von PageModel und stellt über Abhängigkeitsinjektion einen einfachen Logger bereit. Bei jeder GET-Anforderung wird eine Information mit dem Namen des Modelltyps protokolliert.

Jetzt kann das PageModel mit einer @model-Anweisung an die zugehörige Razor-Seite gebunden werden.

CSHTMLIndex.cshtml
@page
@model IndexModel
@namespace MeineRazorDemo.Pages
<!DOCTYPE html>
<html>
<head>
    <title>Meine Seite</title>
    <meta charset="utf-8">
</head>
<body>
    <h1>Hallo, Welt!</h1>
    <p>Aktuell ist es @DateTime.Now.</p>
</body>
</html>

Hinzufügen von einem Layout

In der Regel haben unterschiedliche Seiten einer Website eine gemeinsame Struktur. Um diese nicht in jeder Seite wiederholen zu müssen, kann ein Layout verwendet werden. Dabei wird nach Konvention eine Datei namens _Layout.cshtml in einem Unterordner Shared/ des zugehörigen Pages/-Verzeichnisses angelegt. An der Stelle, an welcher die Methode @RenderBody() aufgerufen wird, wird der Inhalt der Razor-Seite eingefügt, welche das Layout verwendet.

CSHTML_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
    <title>Meine Seite</title>
    <meta charset="utf-8">
</head>
<body>
    @RenderBody()
</body>
</html>

Um das Layout für eine Razor-Seite zu verwenden, wird die Eigenschaft Layout in der Razor-Seite entsprechend gesetzt:

CSHTMLIndex.cshtml
@page
@{
    Layout = "_Layout";
}
@namespace MeineRazorDemo.Pages
<!DOCTYPE html>
<html>
<head>
    <title>Meine Seite</title>
    <meta charset="utf-8">
</head>
<body>
    <h1>Hallo, Welt!</h1>
    <p>Aktuell ist es @DateTime.Now.</p>
</body>
</html>

ViewStart und ViewImports