{"id":55000127,"date":"2018-04-01T00:00:00","date_gmt":"2020-03-27T19:31:25","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=127"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Markup_mit_Razor_Pages","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Markup_mit_Razor_Pages\/","title":{"rendered":"Markup mit Razor Pages"},"content":{"rendered":"<p><b>Wenn Sie Webseiten auf Basis von ASP.NET Core bauen, wollen Sie in den statischen HTML-Code gegebenenfalls auch dynamische Elemente einbauen. Dazu verwenden Sie eine sogenannte Server Side Markup Language. Eine solche Sprache ist das relativ neue Razor Pages. Dieser Artikel zeigt, wie Sie den Inhalt von HTML-Seiten &uuml;ber Razor Pages durch dynamische Inhalte erweitern.<\/b><\/p>\n<p>Wenn Sie schon einmal eine Seite mit PHP oder mit klassischen ASP programmiert haben, kennen Sie die Code-Schnipsel, die dort in den HTML-Code eingepflegt werden. Unter PHP etwa beginnen diese mit <b>&lt;php <\/b>und enden mit <b>&gt;<\/b>.  F&uuml;r ASP.NET Core gibt es mit Razor Pages eine neue Technologie, die wir uns im vorliegenden Artikel ansehen wollen. Voraussetzung daf&uuml;r ist, dass Sie ein einfaches Webprojekt auf Basis von ASP.NET Core angelegt haben &#8211; siehe auch im Beitrag <b>Einfache Web-Anwendung erstellen<\/b>. Die dort angelegte Anwendung nutzt eine statische Seite namens <b>index.html <\/b>als Startseite. Diese kann wegen ihrer Dateiendung keine dynamischen Elemente aufnehmen.<\/p>\n<h2>Model View Controller hinzuf&uuml;gen<\/h2>\n<p>Model View Controller ist ein Entwurfsmuster, mit dem eine Software in verschiedene Ebenen aufgeteilt wird. Das Model entspricht dem Datenmodell, die View ist die Pr&auml;sentation der Daten, also die Benutzeroberfl&auml;che und der Controller steuert die Anwendung. An dieser Stelle steigen wir noch nicht tiefer in dieses Entwurfsmuster ein (genau genommen verwenden wir MVC noch nicht einmal im eigentlichen Sinne), aber wir ben&ouml;tigen einen Service, der uns bei der Ausf&uuml;hrung sogenannter MVC-Aktionen unterst&uuml;tzt. In diesem Fall wird die MVC-Aktion eine HTML-Seite mit einigen Besonderheiten sein, mehr dazu weiter unten. Als Erstes schauen wir uns an, welche &Auml;nderungen im Quellcode der Klasse <b>Startup.cs <\/b>n&ouml;tig sind, um die Verarbeitung von MVC-Aktionen zu unterst&uuml;tzen. Wir f&uuml;gen also zun&auml;chst den Aufruf der Methode <b>AddMVC <\/b>zur Methode <b>ConfigureServices <\/b>hinzu. Danach erweitern wir die Methode <b>Configure <\/b>neben dem Aufruf der Methode <b>UseStaticFiles <\/b>um die Methode <b>UseMVC<\/b>:<\/p>\n<pre>public class Startup {\r\n     public void ConfigureServices(IServiceCollection services) {\r\n         services.AddMvc();\r\n     }\r\n     public void Configure(IApplicationBuilder app, IHostingEnvironment env) {\r\n         if (env.IsDevelopment()) {\r\n             app.UseDeveloperExceptionPage();\r\n         }\r\n         app.UseStaticFiles();\r\n         app.UseMvc();\r\n     }\r\n}<\/pre>\n<h2>Razor-Seite hinzuf&uuml;gen<\/h2>\n<p>Nun ben&ouml;tigen wir einen Ersatz f&uuml;r die bisher statisch verwendete Seite <b>index.html<\/b>. Dazu rufen wir wieder den Kontextmen&uuml;-Eintrag <b>Neues Element hinzuf&uuml;gen&#8230; <\/b>auf, diesmal aber f&uuml;r den noch hinzuzuf&uuml;genden Ordner <b>Pages<\/b>. Im Dialog <b>Neues Element <\/b>hinzuf&uuml;gen w&auml;hlen Sie unter der Kategorie <b>Web <\/b>den Eintrag <b>Razor Seite <\/b>aus und legen den Namen <b>index.cshtml<\/b> f&uuml;r die Seite fest (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_127_001.png\" alt=\"Hinzuf&uuml;gen einer Razor-Seite\" width=\"549,6265\" height=\"289,1742\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Hinzuf&uuml;gen einer Razor-Seite<\/span><\/b><\/p>\n<p>Die neue Seite namens <b>index.cshtml <\/b>sieht wie in Bild 2 aus. Hier ist zun&auml;chst kein HTML-Code in Sicht, was ein wenig irritiert. Stattdessen erwartet uns ein als Fehler markierter Ausdruck namens <b>indexModel<\/b>.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_127_002.png\" alt=\"Code der neuen Seite index.cshtml\" width=\"349,7625\" height=\"114,6644\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Code der neuen Seite index.cshtml<\/span><\/b><\/p>\n<p>Zus&auml;tzlich liefert der Projektmappen-Explorer noch eine der Seite <b>index.cshtml <\/b>untergeordnete Datei namens <b>index.cshtml.cs <\/b>(siehe Bild 3). Das Schema erinnert uns an die Code behind-Klassen von WPF-Seiten.  Der Fehler hinter dem Element <b>indexModel <\/b>in der Datei <b>index.cshtml <\/b>lautet &#8220;Der Typ- oder Namespacename &#8220;indexModel&#8221; wurde nicht gefunden (m&ouml;glicherweise fehlt eine using-Direktive oder ein Assemblyverweis).&#8221;. <\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_127_003.png\" alt=\"Die \"Code behind\"-Klasse von index.cshtml\" width=\"349,7625\" height=\"255,6235\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Die &#8220;Code behind&#8221;-Klasse von index.cshtml<\/span><\/b><\/p>\n<p>Wenn wir die Anwendung starten, erhalten wir auch tats&auml;chlich eine Fehlermeldung im Browser (siehe Bild 4). Das ist &uuml;brigens dem Umstand geschuldet, dass wir in der Methode <b>Configure<\/b> der Klasse <b>Startup <\/b>f&uuml;r den Entwicklungsmodus die Methode <b>UseDeveloperExceptionPage <\/b>aufgerufen haben. Der Fehler liegt darin, dass wir den Namespace zur Seite <b>index.cshtml <\/b>nicht angegeben haben. Das holen wir nun nach, indem wir den Code der Seite <b>index.cshtml<\/b> wie folgt &auml;ndern und den Namespace <b>RazorPages <\/b>sowie den Namen des Ordners <b>Pages <\/b>hinzuf&uuml;gen:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_127_004.png\" alt=\"Fehler beim Starten der Anwendung\" width=\"499,6607\" height=\"258,6479\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Fehler beim Starten der Anwendung<\/span><\/b><\/p>\n<pre>@page\r\n@model RazorPages.Pages.indexModel\r\n@{\r\n}<\/pre>\n<p>Danach k&ouml;nnen wir die Anwendung ohne Fehlermeldung starten, erhalten allerdings auch eine leere Seite &#8211; kein Wunder, denn wir haben ja noch keine Inhalte auf der Seite <b>index.cshtml <\/b>hinterlegt. Das &auml;ndern wir nun durch Hinzuf&uuml;gen der folgenden Zeile:<\/p>\n<pre>&lt;h1&gt;Hello index.cshtml!&lt;\/h1&gt;<\/pre>\n<p>Beim n&auml;chsten Start der Anwendung sehen wir dann auch den gew&uuml;nschten Text im Browser (siehe Bild 5).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_127_005.png\" alt=\"Die Seite l&auml;uft!\" width=\"349,7625\" height=\"154,647\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Die Seite l&auml;uft!<\/span><\/b><\/p>\n<h2>Dynamische Inhalte hinzuf&uuml;gen<\/h2>\n<p>Nun gehen wir einen Schritt weiter und wollen einen dynamischen Inhalt hinzuf&uuml;gen &#8211; was der eigentliche Sinn des Artikels ist. Dazu nutzen wir das <b>@<\/b>-Zeichen und die dadurch per IntelliSense eingeblendeten verf&uuml;gbaren Code-Elemente. In diesem Fall wollen wir das aktuelle Datum und die Uhrzeit ausgeben (siehe Bild 6). Das erledigen wir mit folgendem Code (die ersten Zeilen bleiben nat&uuml;rlich erhalten):<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_127_006.png\" alt=\"Anzeige von Datum und Uhrzeit\" width=\"349,7625\" height=\"171,1427\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Anzeige von Datum und Uhrzeit<\/span><\/b><\/p>\n<pre>&lt;h1&gt;Hello index.cshtml!&lt;\/h1&gt;\r\n&lt;p&gt;Es ist jetzt @DateTime.Now&lt;\/p&gt;<\/pre>\n<h2>Razor-Anweisungen<\/h2>\n<p>Schauen wir uns nun an, was die mit <b>@ <\/b>beginnenden Anweisungen in der Datei <b>index.cshtml <\/b>bedeuten.<\/p>\n<ul>\n<li><b>@page<\/b>: Diese Anweisung kennzeichnet die Seite als sogenannte MVC-Aktion. Dies ist immer die erste Anweisung auf der Seite.<\/li>\n<li><b>@model RazorPages.Pages.indexModel<\/b>: Diese Seite gibt an, wo sich das Model f&uuml;r diese Seite (View) befindet. Dabei handelt es sich um die Klasse <b>indexModel <\/b>im Ordner <b>Pages <\/b>des Namespaces <b>RazorPages<\/b>.<\/li>\n<li><b>@{&#8230;}<\/b>: Hier k&ouml;nnen Sie C#-Anweisungen eingeben, die zur Laufzeit auf dem Server ausgef&uuml;hrt werden.<\/li>\n<\/ul>\n<h2>M&ouml;glichkeiten, C#-Code und HTML in Razor Pages zu kombinieren<\/h2>\n<p>Wenn Sie HTML-Code und C#-Code so kombinieren wollen, dass der C#-Code zur Laufzeit auf dem Server ausgef&uuml;hrt wird und das Ergebnis mit dem bereits vorhandenen HTML-Code zusammengestellt wird, haben Sie verschiedene M&ouml;glichkeiten:<\/p>\n<ul>\n<li>Sie schreiben den C#-Code in <b>@{&#8230;}<\/b>-Bl&ouml;cke. Jede Anweisung muss dann mit einem Semikolon abgeschlossen werden.<\/li>\n<li>Sie f&uuml;gen Variablen oder Funktionsaufrufe mit f&uuml;hrendem <b>@ <\/b>in den HTML-Code ein.<\/li>\n<\/ul>\n<p>Die Dateien, die solche Kombinationen aus HTML- und C#-Code enthalten, m&uuml;ssen immer die Dateiendung <b>.cshtml <\/b>aufweisen. Auf diese Weise k&ouml;nnen Sie etwa in einem Razor Code-Block eine Variable deklarieren und f&uuml;llen und dann im HTML-Code &uuml;ber den <b>@<\/b>-Operator auf die Variable zugreifen. Hier ist gleich anzumerken, dass Variablen in Razor-Bl&ouml;cken immer als <b>var <\/b>deklariert werden. Anweisungen werden wie unter C# &uuml;blich mit dem Semikolon abgeschlossen (<b>;<\/b>). Zeichenketten werden in Anf&uuml;hrungszeichen eingefasst. Achtung: Razor Code unter C# ist case sensitive, <b>Vorname<\/b> ist also ungleich <b>vorname<\/b>. Ein Beispiel f&uuml;r sieht etwa wie folgt aus:<\/p>\n<pre>@page\r\n@model RazorPages.Pages.indexModel\r\n@{\r\n     var Seitentitel = \"Startseite\";\r\n}\r\n&lt;h1&gt;@Seitentitel&lt;\/h1&gt;<\/pre>\n<div class=\"rcp_restricted\"><p><span style=\"color: #ff0000;\">M&ouml;chten Sie weiterlesen? Dann l&ouml;sen Sie Ihr Ticket!<\/span><br \/>\n<span style=\"color: #ff0000;\">Hier geht es zur Bestellung des Jahresabonnements des Magazins <strong>Visual Basic Entwickler<\/strong>:<\/span><br \/>\n<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/shop.minhorst.com\/magazine\/363\/visual-basic-entwickler-jahresabonnement?c=77\">Zur Bestellung ...<\/a><\/span><br \/>\n<span style=\"color: #ff0000;\">Danach greifen Sie sofort auf <strong>alle rund 200 Artikel<\/strong> unseres Angebots zu - auch auf diesen hier!<\/span><br \/>\n<span style=\"color: #000000;\">Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:<\/span><\/p>\n<\/div>\n\n\t\n\t<form id=\"rcp_login_form\"  class=\"rcp_form\" method=\"POST\" action=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000127\/\">\n\n\t\t\n\t\t<fieldset class=\"rcp_login_data\">\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_login\">Username or Email<\/label>\n\t\t\t\t<input name=\"rcp_user_login\" id=\"rcp_user_login\" class=\"required\" type=\"text\"\/>\n\t\t\t<\/p>\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_pass\">Password<\/label>\n\t\t\t\t<input name=\"rcp_user_pass\" id=\"rcp_user_pass\" class=\"required\" type=\"password\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t\t<p>\n\t\t\t\t<input type=\"checkbox\" name=\"rcp_user_remember\" id=\"rcp_user_remember\" value=\"1\"\/>\n\t\t\t\t<label for=\"rcp_user_remember\">Remember me<\/label>\n\t\t\t<\/p>\n\t\t\t<p class=\"rcp_lost_password\"><a href=\"\/data\/wp\/v2\/posts\/55000127?rcp_action=lostpassword\"><\/a><\/p>\n\t\t\t<p>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_action\" value=\"login\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_redirect\" value=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000127\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"123b777de9\"\/>\n\t\t\t\t<input id=\"rcp_login_submit\" class=\"rcp-button\" type=\"submit\" value=\"Login\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t<\/fieldset>\n\n\t\t\n\t<\/form>\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wenn Sie Webseiten auf Basis von ASP.NET Core bauen, wollen Sie in den statischen HTML-Code gegebenenfalls auch dynamische Elemente einbauen. Dazu verwenden Sie eine sogenannte Server Side Markup Language. Eine solche Sprache ist das relativ neue Razor Pages. Dieser Artikel zeigt, wie Sie den Inhalt von HTML-Seiten &uuml;ber Razor Pages durch dynamische Inhalte erweitern.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[66022018,662018,44000018,44000004,44000017,44000028],"tags":[],"yst_prominent_words":[],"class_list":["post-55000127","post","type-post","status-publish","format-standard","hentry","category-66022018","category-662018","category-ASPNET_Core","category-Loesungen","category-WebApps_Razor_Pages","category-Word_programmieren"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000127","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000127"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000127\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000127"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000127"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000127"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000127"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}