ASP.NET Razor View Engine (Razor)

Eintrag zuletzt aktualisiert am: 12.09.2019


ASP.NET Razor View Engine (Razor) ist die in ASP.NET verwendete Vorlagensprache für Webseiten, bei der man C# oder Visual Basic .NET-Fragmente in HTML-Seiten einbetten kann. Programmcodeblöcke werden dabei mit dem Zeichen @ eingeleitet (im Konstrast zur klassischen ASP.NET View Engige, die die Codeblöcke in <% %> einrahmen musste).

Es ist erstmal im Januar 2011 erschienen als Teil von ASP.NET MVC und ASP.NET Webpages/Webmatrix.
Mittlerweile verwendet auch in ASP.NET Core MVC, ASP.NET Core Razor Pages und ASP.NET Blazor.

In einigen Fällen ist eine Klammerung @(…) notwendig, z.B.
Text für den @(i).Absatz.
<a href="detailseite@(i).cshtml">Mehr…</a>

Beispiele
@{

Layout = "~/_SiteLayout.cshtml";
Page.Title = "Startseite";
string name = "Holger";
var Icons = new List<string> { "one", "two", "three" };
}

@section featured {
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1>Willkommen!</h1>
<h2>@Page.Title.</h2>
</hgroup>
<p>
<p>Hallo @name, es ist jetzt @DateTime.Now.ToShortTimeString()!</p>
</p>
</div>
</section>
}

<h3>Das sind die aktuellen Themen:</h3>

<ol class="round">

@for (int i = 1; i < 4; i++)
{
<li class="@Icons[i-1]">
<h5>Überschrift @i</h5>
Text für den @(i).Absatz.
<a href="detailseite@(i).cshtml">Mehr…</a>
</li>
}

</ol>


Razor-Ausdrücke
Ausgabe ist HTML Encoded
@ausgabe
Ausgabe ist nicht Encoded
@Html.Raw(ausgabe)
Durch das Leerzeichen ist der Punkt reiner Text.
Dies ist die @anz. Seite!
Hier werden jeweils Klammern @(…) gebraucht!
Dies ist die @(anz).Seite!
Ergebnis: @(anz * 10 + 2)
@(new Autor().GetInfo<string>())
Escape für @
Die Variable @@anz enthält @anz.
Variablendeklaration
@{int gesamt = ViewBag.GesamtAnzahl; }

Razor-Ausdrücke in HTML-Attributen
Wenn cssklasse null ist, verschwindet das class-Attribut:
@{ string cssklasse = "intro"; }
<div class="@cssklasse">Text</div>
Aber nicht, wenn es weitere Werte gibt:
<div class="@cssklasse kursiv">Text</div>
Aus true wird hier checked="checked":
@{ var aktiv = true; }
<input type="checkbox" checked="@aktiv" />

Razor-Blöcke
@* Dies ist ein
Kommentarblock *@

@{ // Codeblock
int anz = 5; string ausgabe = "<i>kursiv</i>";
var orte = new List<string>() { "Essen","Dortmund","Bochum" };
}

@{ // Codeblock mit Markup-Inhalt
int schrittweite = 2;
for (int i = 0; i < anz; i += schrittweite)
{ <div>@start.AddDays(i)</div> }
}

@{ // Reiner Text im Codeblock
for (int i = 0; i < anz; i += schrittweite)
{ <text> Seite @i
noch mehr reiner Text
</text> }
}

@{ // Reiner Text im Codeblock (Alternative Schreibweise)
for (int i = 0; i < anz; i += schrittweite)
{ @: Seite @i
@: noch mehr reiner Text
} // Klammer muss in diesem Fall in getrennte Zeile!
}

Razor-Schleifen
for-Schleife
@for (int i = 0; i < anz; i++)
{ <div>@start.AddDays(i)</div> }

while-Schleife
@while (anz*10 < 100)
{ anz++;
<div>@(anz*10)% erledigt</div> }

foreach-Schleife
@foreach (var ort in orte)
{ <a href="/flug/@ort/0/10">@ort</a> }

Razor-Bedingungen
@if (anz > 100)
{ <text>reiner Text</text> }
else
{ <div>Tag und Ausdruck @anz</div> }

Razor-Funktionen
@functions
{
string GetProzent(int anz)
{ return anz.ToString() + "%"; }
}
Erledigt sind @GetProzent(10);

Razor-Helper (nicht in ASP.NET Core!)
@helper GetProzent(int anz)
{ <i>@anz%</i> }
Erledigt sind @GetProzent(10)

HTML-Helper für Formulare
@{ var orteItems = orte.Select(x => new SelectListItem { Text = x, Value = x }) .ToList(); }
@using (Html.BeginForm("Neu", "Flug", FormMethod.Post)){
@Html.ValidationSummary("Fehleingaben:")
<div> FlugNr @Html.TextBoxFor(x => x.FlugNr, new { @class = "form-control", disabled="disabled" })
@Html.ValidationMessageFor(x => x.FlugNr, "", new { @class = "text-danger" })
}
Abflugort: @Html.DropDownListFor(x => x.Abflugort, orteItems,
"offen", new { @class = "form-control" }) <br />
Nichtraucherflug: @Html.CheckBoxFor(x => x.NichtRaucherFlug,
new { @class = "form-control" }) <br />
<button type="submit">Speichern</button></div> }

Weitere: @Html.ActionLink(), @Html.Hidden(), @Html.ListBox(), @Html.Password(), @Html.RadioButton(), @Html.TextArea() Modellgetrieben: @Html.EditorFor(), @Html.ValueFor(), @Html.DisplayFor(), @Html.LabeFor()

Details zu Razor (von Manfred Steyer)

Die View-Engine, welche seit ASP.NET MVC 3 zum Rendern von Views standardmäßig zum Einsatz kommt und den Namen Razor trägt, verwendet das Symbol @, um serverseitige Anweisungen einzuleiten. Es wird dabei entweder einer Kontrollstruktur oder eine Variable bzw. Eigenschaft oder Methode vorangestellt, deren (Rückgabe-)Wert an Ort und Stelle in die View zu übernehmen ist. Mit @Html können zahlreiche Hilfsfunktionen aufgerufen werden.

Das Schöne ist, dass Razor alle Werte, die es auf diese Weise ausgibt, automatisch HTML-codiert, was Sicherheitslücken und anderen ungewollten Effekten vorbeugt. Möchte der Entwickler einen Text ohne HTML-Codierung ausgeben, muss er auf die Funktion @Html.Raw zurückgreifen:
@Html.Raw("<b>Html-formatierter Text</b>")
Anweisungen, die keinen Wert liefern, können auf diese Weise nicht aufgerufen werden. Allerdings können diese in Blöcken, die der Entwickler zur serverseitigen Ausführung markiert, platziert werden:
@{
ViewBag.Title = "Hotels";
RenderAction("MyAction")
int i = 7;
}
Das Symbol @ wird auch zum Einleiten von Direktiven verwendet, die in der Regel am Beginn einer Datei platziert werden. Die Direktive @model wurde bereits in der Einführung verwendet. Sie legt fest, von welchem Typ das Modell ist. Mit
@model FirstSteps.Models.Hotel
legt der Entwickler zum Beispiel fest, dass das Modell der aktuellen View vom Typ FirstSteps.Models.Hotel ist. Eine weitere nützliche Direktive ist die Direktive @using. Sie erlaubt es die benötigten Namensräume zu referenzieren und kann somit mit dem gleichnamigen Schlüsselwort in C# verglichen werden. Die Angabe von
@using FirstSteps.Models
bindet zum Beispiel den Namensraum FirstSteps.Models ein. Mit Vorsicht zu genießen ist die Direktive @functions. Sie erlaubt es, innerhalb eines Blocks beliebige Methoden zu definieren:
@functions {
private bool HaveLuck(bool needLuck) { return !needLuck; }
}
<b>Lucky:</b> @HaveLuck(true)
Bei ihrer Verwendung in Views darf man sich zu Recht fragen, ob dadurch nicht zu viel Logik in die View verlagert wird bzw. ob diese Logik nicht woanders besser aufgehoben wäre. In Razor-Helper oder in Vorlagen (siehe unten) kann sie hingegen schon zur Lesbarkeit beitragen.
Möchte der Entwickler tatsächlich das Symbol @ ausgeben, muss er es doppelt angeben. Die Anweisung
h.schwichtenberg@@it-visions.de
würde demnach zur Ausgabe der Email-Adresse H.Schwichtenberg@it-visions.de führen. In einigen wenigen Fällen tut sich Razor schwer damit, das Ende eines Methodennamens zu entdecken. Dies ist beispielsweise bei
@Model.Vorname.Schwichtenberg@@it-visions.de
der Fall. Hier kann Razor nicht entdecken, dass Schwichtenberg keine Eigenschaft von Vorname ist sondern lediglich ein Text, den es auszugeben gilt. Abhilfe schafft hier das Setzen von Klammern:
@(Model.Vorname).Schwichtenberg@@it-visions.de
Razor erkennt an den meisten Stellen automatisch den Übergang zwischen serverseitigen Code und clientseitigem Markup. Bei der Anweisung
@for(int i=0; i<10; i++) { <b>@i</b> }
wird zum Beispiel erkannt, dass die schließende geschweifte Klammer zur serverseitigen Schleife gehört sowie, dass es sich beim b-Tag um Markup handelt, der auszugeben ist. Die Logik dahinter ist vom Prinzip her einfach: Immer dann, wenn ein Tag beginnt, geht Razor davon aus, dass nun ein clientseitiger Block folgt. Dies ist auch der Grund, warum
@for(int i=0; i<10; i++) { Hallo Welt! }
nicht korrekt ausgeführt werden kann, denn »Hallo Welt« befindet sich nicht in einem Tag und wird somit als serverseitiger Befehl wahrgenommen. Um dieses Problem zu umgehen, müsste der Entwickler diesen Text in einem beliebigen Tag kapseln. Bietet sich kein Tag an, kann er auf das von Razor vorgegebene Tag text zurückgreifen:
@for(int i=0; i<10; i++) { <text>Hallo Welt!</text> }
Dieses Tag erlaubt es Razor, den Beginn von clientseitigen Elementen zu erkennen. Darüber hinaus filtert Razor das Tag, sodass es sich nicht in der Ausgabe wiederfindet.
Eine sehr angenehme Eigenschaft von Razor ist die Tatsache, dass die Tilde (~) in Pfadangaben durch den Pfad des Roots der aktuellen Webanwendung ersetzt wird. Ist das Root der Webanwendung zum Beispiel /myApp, so wird eine Angabe von
<img src="~/img/myImage.png">
durch
<img src="/myApp/img/myImage.png">
ersetzt.
Zu guter Letzt erlaubt Razor auch die Definition von serverseitigen Kommentaren. Diese werden durch die Sequenz @* eingeleitet sowie mit *@ beendet:
@* Das ist ist ein Kommentar *@