{"id":55000131,"date":"2018-04-01T00:00:00","date_gmt":"2020-03-27T19:31:58","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=131"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Kontaktformular_unter_ASPNET_Core","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Kontaktformular_unter_ASPNET_Core\/","title":{"rendered":"Kontaktformular unter ASP.NET Core"},"content":{"rendered":"<p><b>Wer Anwendungen f&uuml;r den Desktop entwickelt hat, kennt die Vorgehensweise: Bei einem Klick auf OK werden die eingegebenen Werte in einer Ereignisprozedur ausgewertet, gespeichert oder anderen Schritten unterzogen. Bei Internetanwendungen ist das aufgrund der Eigenarten der Browser etwas anders. Hier klicken Sie zwar nach der Eingabe von Daten auch auf eine Schaltfl&auml;che, um die Daten zu verarbeiten, aber es gibt dort keine Ereignisprozeduren im klassischen Sinne. Wie die Datenverarbeitung hier geschieht, zeigt der vorliegende Artikel.<\/b><\/p>\n<p>F&uuml;r die Beispiele dieses Artikels legen Sie wieder ein Projekt auf Basis der Vorlage <b>Visual C#|Web|ASP.NET Core-Webanwendung<\/b> an. W&auml;hlen Sie im Dialog <b>Neue ASP.NET Core Webanwendung <\/b>den Eintrag <b>Webanwendung <\/b>aus.<\/p>\n<p>Wir wollen zun&auml;chst nur eine Seite namens <b>Index.cshtml <\/b>nutzen, die wir allerdings mit eigenen Inhalten f&uuml;llen wollen. Also entfernen wir den aktuell in der Datei <b>\/Pages\/Index.cshtml <\/b>enthaltenen Code mit Ausnahme der Razor-Anweisungen zu Beginn des Codes (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_131_001.png\" alt=\"Basis unseres Formulars\" width=\"424,7115\" height=\"201,9547\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Basis unseres Formulars<\/span><\/b><\/p>\n<p>In unserem Beispiel wollen wir ein Formular erstellen, in das der Benutzer die Daten wie in einem Kontaktformular eingibt und dessen Inhalt dann an den Betreiber der Webseite geschickt wird. Als E-Mail-Provider wollen wir dann wie im Artikel <b>E-Mails per SendGrid verschicken <\/b>den Anbieter <b>Sendgrid <\/b>nutzen.<\/p>\n<h2>Model anlegen<\/h2>\n<p>Bevor wir mit der Programmierung des eigentlichen Formulars im HTML-Format beginnen, stellen wir ein Model zusammen, oder genauer: eine Klasse mit einem Model f&uuml;r die E-Mail-Daten. Diese Klasse soll wie folgt aussehen und kann der Einfachheit halber direkt in der Datei <b>Index.cshtml.cs <\/b>eingef&uuml;gt werden:<\/p>\n<pre>public class KontaktformularModel {\r\n     [Required]\r\n     public string Vorname { get; set; }\r\n     [Required]\r\n     public string Nachname { get; set; }\r\n     [Required]\r\n     public string Email { get; set; }\r\n     [Required]\r\n     public string Nachricht { get; set; }\r\n}<\/pre>\n<p>Hier sehen Sie neben den &uuml;blichen Elementen einer Klasse jeweils das Attribut <b>[Required]<\/b>. Damit dieses nicht als Fehler markiert wird, f&uuml;gen wir der Klassendatei mit der <b>using<\/b>-Anweisung den Namespace <b>System.ComponentModel.DataAnnotations <\/b>hinzu:<\/p>\n<pre>using System.ComponentModel.DataAnnotations;<\/pre>\n<p>Damit wir ein Objekt auf Basis der Klasse <b>KontaktformularModel<\/b> im HTML-Formular nutzen k&ouml;nnen, machen wir dieses &auml;hnlich wie unter WPF &ouml;ffentlich verf&uuml;gbar (siehe Bild 2):<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_131_002.png\" alt=\"Aktueller Stand der Klassendatei Index.cshtml.cs\" width=\"424,7115\" height=\"491,8976\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Aktueller Stand der Klassendatei Index.cshtml.cs<\/span><\/b><\/p>\n<pre>[BindProperty]\r\npublic KontaktformularModel Kontakt{ get; set; }<\/pre>\n<p>Damit kommen wir nun zum HTML-Code des Formulars. Die einfachste Form dieses Formulars sieht wie folgt aus &#8211; wenn wir das Projekt nun starten, erhalten wir das Formular aus Bild 3:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_02\/pic_131_003.png\" alt=\"Start des ersten Beispiels\" width=\"424,7115\" height=\"242,9192\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Start des ersten Beispiels<\/span><\/b><\/p>\n<pre>&lt;form method=\"post\"&gt;\r\n     &lt;table&gt;\r\n         &lt;tr&gt;\r\n             &lt;td&gt;Vorname:&lt;\/td&gt;\r\n             &lt;td&gt;&lt;input asp-for=\"Kontakt.Vorname\" \/&gt;&lt;\/td&gt;\r\n         &lt;\/tr&gt;\r\n         &lt;tr&gt;\r\n             &lt;td&gt;Nachname:&lt;\/td&gt;\r\n             &lt;td&gt;&lt;input asp-for=\"Kontakt.Nachname\" \/&gt;&lt;\/td&gt;\r\n         &lt;\/tr&gt;\r\n         &lt;tr&gt;\r\n             &lt;td&gt;E-Mail:&lt;\/td&gt;\r\n             &lt;td&gt;&lt;input asp-for=\"Kontakt.Email\" \/&gt;&lt;\/td&gt;\r\n         &lt;\/tr&gt;\r\n         &lt;tr&gt;\r\n             &lt;td&gt;Nachricht:&lt;\/td&gt;\r\n             &lt;td&gt;&lt;input asp-for=\"Kontakt.Nachricht\" \/&gt;&lt;\/td&gt;\r\n         &lt;\/tr&gt;\r\n         &lt;tr&gt;\r\n             &lt;td colspan=\"2\"&gt;&lt;button type=\"submit\"&gt;Absenden&lt;\/button&gt;&lt;\/td&gt;\r\n         &lt;\/tr&gt;\r\n     &lt;\/table&gt;\r\n&lt;\/form&gt; <\/pre>\n<p>Wenn wir nun auf Absenden klicken, geschieht allerdings noch nichts. Das liegt daran, dass wir nicht &#8211; wie fr&uuml;her &uuml;blich &#8211; die Zielseite angegeben haben, die nach dem Anklicken der <b>Submit<\/b>-Schaltfl&auml;che aufgerufen werden soll. Diese wurde sonst im Attribut <b>action <\/b>des <b>form<\/b>-Elements angegeben. Wir geben hingegen mit dem Attribut <b>method <\/b>nur die Art der &Uuml;bermittlung der Inhalte des Formulars an, und zwar als <b>post <\/b>(es gibt auch noch <b>get<\/b>). Wenn Sie hier <b>get <\/b>angeben, werden die in das Formular eingegebenen Daten an die durch das Formular aufgerufene  Seite &uuml;ber die URL &uuml;bermittelt, f&uuml;r eine PHP-Seite also etwa mit <b>\/index.phpvorname=andre&#038;nachname=minhorst&#038;email=andre@minhorst.com<\/b>. Der Nachteil dieser Version ist, dass die Anzahl der &uuml;bermittelbaren Zeichen je nach Browser begrenzt ist. Deshalb verwenden wir <b>post <\/b>als <b>action<\/b>.<\/p>\n<h2>Auswertung des Formulars<\/h2>\n<p>Wie aber wollen wir das Formular nun nach dem Senden auswerten Unter PHP beispielsweise gibt man eine Zielseite an, die dann den notwendigen Code enth&auml;lt, um die entweder in der Variablen <b>$_GET <\/b>oder <b>$_POST <\/b>&uuml;bermittelten Informationen zu verarbeiten. Unter ASP.NET Core l&auml;uft das ganz anders. Hier enth&auml;lt die Code behind-Datei der Seite mit dem Formular eine Ereignismethode, welche die Daten auswertet. Sie brauchen also keine Zielseite f&uuml;r das Formular anzugeben, die Verarbeitung erfolgt in der Seite selbst beziehungsweise in ihrem serverseitigen Code. Die einfachste Version dieser Methode, die lediglich zu der Seite mit dem Namen <b>About.cshtml <\/b>weiterleitet, sieht wie folgt aus:<\/p>\n<pre>public async Task&lt;IActionResult&gt; OnPostAsync() {\r\n     return RedirectToPage(\"About\");\r\n}<\/pre>\n<p>Wenn Sie die Anwendung nun starten, die Daten in das Formular eingeben und dann auf Absenden klicken, wird anschlie&szlig;end die Seite <b>About.cshtml <\/b>geladen.<\/p>\n<h2>Validieren<\/h2>\n<p>Und nun kommt ein wenig ASP.NET Core-Magie ins Spiel. Wir f&uuml;gen nun eine <b>if<\/b>-Bedingung ein, welche die Eigenschaft <b>IsValid <\/b>des Objekts <b>ModelState <\/b>pr&uuml;ft und erneut die aktuelle Seite aufruft, wenn <b>IsValid <\/b>nicht den Wert <b>true <\/b>liefert:<\/p>\n<pre>public async Task&lt;IActionResult&gt; OnPostAsync() {\r\n     if (!ModelState.IsValid) {\r\n         return Page();\r\n     }\r\n     return RedirectToPage(\"About\");\r\n}<\/pre>\n<p>Wie funktioniert das Nun: Wir haben ja mit dem <b>[Required]<\/b>-Element festgelegt, dass die Daten f&uuml;r die vier Felder der Klasse <b>KontaktformularModel <\/b>angegeben werden m&uuml;ssen. Diese werden bei der Pr&uuml;fung durch <b>ModelState.IsValid <\/b>untersucht. Ist eines der Felder leer, hat <b>IsValid <\/b>den Wert <b>False <\/b>und man landet wieder auf der ausl&ouml;senden Seite. Erst wenn alle Felder gef&uuml;llt sind, wird die Seite <b>About <\/b>mit der <b>RedirectToPage<\/b>-Methode aufgerufen.<\/p>\n<h2>Mail versenden<\/h2>\n<p>Um die Mail mit den Kontaktinformationen schlie&szlig;lich zu versenden, f&uuml;gen wir der Methode <b>OnPostAsync <\/b>noch den Aufruf einer weiteren Methode namens <b>SendMail <\/b>hinzu:<\/p>\n<pre>public async Task&lt;IActionResult&gt; OnPostAsync() {\r\n     if (!ModelState.IsValid) {\r\n         return Page();\r\n     }\r\n     SendMail();\r\n     return RedirectToPage(\"About\");\r\n}<\/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\/55000131\/\">\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\/55000131?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\/55000131\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"9fac6dd15a\"\/>\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>Wer Anwendungen f&uuml;r den Desktop entwickelt hat, kennt die Vorgehensweise: Bei einem Klick auf OK werden die eingegebenen Werte in einer Ereignisprozedur ausgewertet, gespeichert oder anderen Schritten unterzogen. Bei Internetanwendungen ist das aufgrund der Eigenarten der Browser etwas anders. Hier klicken Sie zwar nach der Eingabe von Daten auch auf eine Schaltfl&auml;che, um die Daten zu verarbeiten, aber es gibt dort keine Ereignisprozeduren im klassischen Sinne. Wie die Datenverarbeitung hier geschieht, zeigt der vorliegende Artikel.<\/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],"tags":[],"yst_prominent_words":[],"class_list":["post-55000131","post","type-post","status-publish","format-standard","hentry","category-66022018","category-662018","category-ASPNET_Core","category-Loesungen","category-WebApps_Razor_Pages"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000131","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=55000131"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000131\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000131"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000131"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000131"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000131"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}