String
Konfigurationen des String-EditorTemplates. Jedes Beispiel zeigt in Tabs die
cshtml, das ViewModel und den Controller (GET/POST);
darunter das funktionierende Formular zum Ausprobieren.
Eindeutige Id (UniqueId)
Die gerenderte HTML-Id wird um einen Zufallswert ergänzt, damit mehrfach gerenderte Formulare kollisionsfrei bleiben.
@model UniqueIdBeispielViewModel
<form asp-area="Basis" asp-controller="UniqueId" asp-action="Index" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
@Html.EditorFor(m => m.Kommentar)
@Html.Fmh(Fmh.Button()
.Text("Absenden")
.Size(ButtonSize.Sm)
.Attributes(new { @class = "mt-2" }))
</form>
using System.ComponentModel.DataAnnotations;
using FMH.Komponente.Basis.Ui.Validation.DataAnnotation;
namespace FMH.Komponente.WebUI.Areas.Basis.Models
{
public class UniqueIdBeispielViewModel
{
[Display(Name = "Kommentar")]
[UniqueId]
public string Kommentar { get; set; }
}
}
using FMH.Komponente.Basis.Erweiterungen;
using FMH.Komponente.Basis.Ui.Feedback.Alert;
using FMH.Komponente.WebUI.Areas.Basis.Models;
using Microsoft.AspNetCore.Mvc;
namespace FMH.Komponente.WebUI.Areas.Basis.Controllers.Beispiele
{
[Area("Basis")]
public class UniqueIdController : Controller
{
[HttpGet]
public IActionResult Index()
{
return this.View(new UniqueIdBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(UniqueIdBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Erfolgsfall: hier würden die eigentlichen Aktionen ausgeführt (z. B. Speichern).
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
// PRG-Pattern (Post-Redirect-Get): nach erfolgreichem POST per Redirect auf die
// GET-Action weiterleiten, damit ein erneutes Laden/Aktualisieren das Formular nicht
// nochmals abschickt (verhindert doppeltes Speichern).
return this.RedirectToAction(nameof(this.Index));
}
// Ungültige Eingabe: dieselbe Seite erneut anzeigen, damit die Validierungsfehler erscheinen.
return this.View(modell);
}
[HttpGet]
public IActionResult Validierung()
{
return this.View(new UniqueIdValidierungBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Validierung(UniqueIdValidierungBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Das Model-Binding läuft über den name des Feldes – der bleibt trotz [UniqueId]
// der Eigenschaftsname, nur die HTML-Id trägt den Zufallswert.
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Validierung));
}
// Beim erneuten Rendern findet das EditorTemplate den ModelState-Eintrag nicht, weil es
// ihn über die (zufällige) Id sucht – die Meldung erscheint deshalb nur in der
// Validierungs-Zusammenfassung, nicht am Feld selbst.
return this.View(modell);
}
}
}
Darstellung
[UniqueId] ist ein Marker-Attribut: Die gerenderte HTML-Id wird um einen Zufallswert ergänzt, damit mehrfach gerenderte Formulare (Nachlade-Szenarien, Modals) kollisionsfrei bleiben.
[UniqueId]
public string Kommentar { get; set; }
Konsequenzen
- Erschwertes Arbeiten mit Selenium/UI-Tests, da sich die Ids pro Rendering ändern.
- Die direkte Zuordnung der MVC-Validierungsmeldung zur Eigenschaft über die Id entfällt.
Ausführlich — mit dem Vergleich «zweimal gerendert» und dem Zusammenspiel mit der Validierung — auf der Demoseite Validierung › UniqueId.
Pflichtfeld abhängig von einem Feld (RequiredIf)
"Firmenname" wird nur zur Pflicht, wenn "Anmeldeart" den Wert "Firma" hat.
@model RequiredIfBeispielViewModel
<form asp-area="Basis" asp-controller="RequiredIf" asp-action="Index" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
@Html.EditorFor(m => m.AnmeldeArt)
@Html.EditorFor(m => m.Firmenname)
@Html.Fmh(Fmh.Button()
.Text("Absenden")
.Size(ButtonSize.Sm)
.Attributes(new { @class = "mt-2" }))
</form>
using System.ComponentModel.DataAnnotations;
using FMH.Komponente.Basis.Ui.Validation.DataAnnotation;
namespace FMH.Komponente.WebUI.Areas.Basis.Models
{
public class RequiredIfBeispielViewModel
{
[Display(Name = "Anmeldeart")]
public string AnmeldeArt { get; set; }
[Display(Name = "Firmenname")]
[RequiredIf(nameof(AnmeldeArt), "Firma", ErrorMessage = "Bitte geben Sie den Firmennamen an, wenn die Anmeldeart „Firma“ gewählt ist.")]
public string Firmenname { get; set; }
}
}
using FMH.Komponente.Basis.Erweiterungen;
using FMH.Komponente.Basis.Ui.Feedback.Alert;
using FMH.Komponente.WebUI.Areas.Basis.Models;
using Microsoft.AspNetCore.Mvc;
namespace FMH.Komponente.WebUI.Areas.Basis.Controllers.Beispiele
{
// Ein Controller pro Attribut (RequiredIf); je eine Action/View pro EditorTemplate.
// Die POST-Actions illustrieren die Validierungslogik: trifft die Bedingung zu und ist das
// Feld leer, ist ModelState.IsValid false.
[Area("Basis")]
public class RequiredIfController : Controller
{
[HttpGet]
public IActionResult Index()
{
return this.View(new RequiredIfBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(RequiredIfBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Erfolgsfall: hier würden die eigentlichen Aktionen ausgeführt (z. B. Speichern).
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
// PRG-Pattern (Post-Redirect-Get): nach erfolgreichem POST per Redirect auf die
// GET-Action weiterleiten, damit ein erneutes Laden/Aktualisieren das Formular nicht
// nochmals abschickt (verhindert doppeltes Speichern).
return this.RedirectToAction(nameof(this.Index));
}
// Ungültige Eingabe: dieselbe Seite erneut anzeigen, damit die Validierungsfehler erscheinen.
return this.View(modell);
}
[HttpGet]
public IActionResult Textbox()
{
return this.View(new RequiredIfTextboxBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Textbox(RequiredIfTextboxBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Gültig: entweder trifft die Bedingung nicht zu oder das Feld ist ausgefüllt.
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Textbox));
}
// Ungültig: Bedingung trifft zu und das Feld ist leer -> View mit den Fehlern.
return this.View(modell);
}
[HttpGet]
public IActionResult Textarea()
{
return this.View(new RequiredIfTextareaBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Textarea(RequiredIfTextareaBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Textarea));
}
return this.View(modell);
}
[HttpGet]
public IActionResult Password()
{
return this.View(new RequiredIfPasswordBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Password(RequiredIfPasswordBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Password));
}
return this.View(modell);
}
[HttpGet]
public IActionResult Datum()
{
return this.View(new RequiredIfDatumBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Datum(RequiredIfDatumBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Datum));
}
return this.View(modell);
}
[HttpGet]
public IActionResult Dropdown()
{
return this.View(new RequiredIfDropdownBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Dropdown(RequiredIfDropdownBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Dropdown));
}
return this.View(modell);
}
[HttpGet]
public IActionResult Combobox()
{
return this.View(new RequiredIfComboboxBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Combobox(RequiredIfComboboxBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Combobox));
}
return this.View(modell);
}
[HttpGet]
public IActionResult Multiselect()
{
return this.View(new RequiredIfMultiselectBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Multiselect(RequiredIfMultiselectBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Bei einer Collection prüft das Attribut zusätzlich auf Count > 0.
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Multiselect));
}
return this.View(modell);
}
[HttpGet]
public IActionResult RadioList()
{
return this.View(new RequiredIfRadioListBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult RadioList(RequiredIfRadioListBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Hier liefert die Bedingung eine Radio-Gruppe: gültig, solange „Vor Ort“ gewählt ist
// oder bei „Online“ eine E-Mail-Adresse erfasst wurde.
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.RadioList));
}
return this.View(modell);
}
}
}
Darstellung
[RequiredIf] macht ein Feld nur dann zur Pflicht, wenn eine abhängige Eigenschaft einen bestimmten Zielwert hat. Verglichen wird über ToString().
[RequiredIf(nameof(AnmeldeArt), "Firma", ErrorMessage = "Bitte erfassen Sie den Firmennamen")]
public string Firmenname { get; set; }
Weitere Konfigurationen
| Option | Wirkung |
|---|---|
| Zweite Bedingung | Überladung mit zwei Eigenschaft/Zielwert-Paaren — beide Bedingungen müssen erfüllt sein |
DisableIfNotRequired = true |
Deaktiviert das Feld, solange es nicht erforderlich ist |
HideIfNotRequired = true |
Blendet das Feld aus, solange es nicht erforderlich ist |
Clientseitig rendert das Attribut data-val-requiredif-*; das zugehörige Skript jquery.validate.unobtrusive.requiredif.js muss im JS-Bundle enthalten sein. Leere Collections zählen serverseitig wie kein Wert.
Dieselbe Bedingung auf den übrigen EditorTemplates (Textarea, Password, DateTime, DropdownList, ComboboxList, MultiselectList) zeigt die Demoseite Validierung › RequiredIf.
Pflichtfeld abhängig von einer Werteliste (RequiredIfContains)
"Referenznummer" wird nur zur Pflicht, wenn "Zahlungsart" "Rechnung" oder "Kreditkarte" ist.
@model RequiredIfContainsBeispielViewModel
<form asp-area="Basis" asp-controller="RequiredIfContains" asp-action="Index" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
@Html.EditorFor(m => m.Zahlungsart)
@Html.EditorFor(m => m.Referenznummer)
@Html.Fmh(Fmh.Button()
.Text("Absenden")
.Size(ButtonSize.Sm)
.Attributes(new { @class = "mt-2" }))
</form>
using System.ComponentModel.DataAnnotations;
using FMH.Komponente.Basis.Ui.Validation.DataAnnotation;
namespace FMH.Komponente.WebUI.Areas.Basis.Models
{
public class RequiredIfContainsBeispielViewModel
{
[Display(Name = "Zahlungsart")]
public string Zahlungsart { get; set; }
[Display(Name = "Referenznummer")]
[RequiredIfContains(nameof(Zahlungsart), "Rechnung", "Kreditkarte", ErrorMessage = "Bitte geben Sie die Referenznummer an, wenn als Zahlungsart „Rechnung“ oder „Kreditkarte“ gewählt ist.")]
public string Referenznummer { get; set; }
}
}
using System.Collections.Generic;
using FMH.Komponente.Basis.Erweiterungen;
using FMH.Komponente.Basis.Ui.Feedback.Alert;
using FMH.Komponente.WebUI.Areas.Basis.Models;
using Microsoft.AspNetCore.Mvc;
namespace FMH.Komponente.WebUI.Areas.Basis.Controllers.Beispiele
{
[Area("Basis")]
public class RequiredIfContainsController : Controller
{
[HttpGet]
public IActionResult Index()
{
return this.View(new RequiredIfContainsBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(RequiredIfContainsBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Erfolgsfall: hier würden die eigentlichen Aktionen ausgeführt (z. B. Speichern).
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
// PRG-Pattern (Post-Redirect-Get): nach erfolgreichem POST per Redirect auf die
// GET-Action weiterleiten, damit ein erneutes Laden/Aktualisieren das Formular nicht
// nochmals abschickt (verhindert doppeltes Speichern).
return this.RedirectToAction(nameof(this.Index));
}
// Ungültige Eingabe: dieselbe Seite erneut anzeigen, damit die Validierungsfehler erscheinen.
return this.View(modell);
}
[HttpGet]
public IActionResult CheckboxList()
{
return this.View(new RequiredIfContainsCheckboxListBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult CheckboxList(RequiredIfContainsCheckboxListBeispielViewModel modell)
{
// Sicherheitsnetz für den Fehlerfall: Wird die View mit den Validierungsfehlern erneut
// gerendert, muss die Collection gesetzt sein – das CheckboxList-Template prüft nicht auf null.
// Ohne Häkchen schickt der Browser gar keinen Wert für die Liste mit.
modell.Verpflegung ??= new List<int>();
if (this.ModelState.IsValid)
{
// Gültig: es ist weder Allergiker- noch Sonderkost angehakt oder die Angaben zur Kost
// sind erfasst. Die Bedingung greift, sobald *ein* angehakter Wert ein Zielwert ist.
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.CheckboxList));
}
return this.View(modell);
}
[HttpGet]
public IActionResult Textbox()
{
return this.View(new RequiredIfContainsTextboxBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Textbox(RequiredIfContainsTextboxBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Gültig: die Zahlungsart steht auf keinem der Zielwerte oder die Referenznummer ist erfasst.
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Textbox));
}
return this.View(modell);
}
[HttpGet]
public IActionResult Dropdown()
{
return this.View(new RequiredIfContainsDropdownBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Dropdown(RequiredIfContainsDropdownBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Dropdown));
}
return this.View(modell);
}
[HttpGet]
public IActionResult Zielwerte()
{
return this.View(new RequiredIfContainsZielwerteBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Zielwerte(RequiredIfContainsZielwerteBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Die Zielwerte liest das Attribut bei der Prüfung aus LaenderMitMwstNummer –
// das gebundene Modell trägt die Liste also mit in die Validierung.
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Zielwerte));
}
return this.View(modell);
}
[HttpGet]
public IActionResult Ausblenden()
{
return this.View(new RequiredIfContainsAusblendenBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Ausblenden(RequiredIfContainsAusblendenBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// HideIfNotRequired wirkt nur clientseitig: das Feld wird trotzdem mitgeschickt
// und serverseitig geprüft.
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
return this.RedirectToAction(nameof(this.Ausblenden));
}
return this.View(modell);
}
}
}
Darstellung
[RequiredIfContains] macht ein Feld zur Pflicht, wenn der Wert der abhängigen Eigenschaft in einer Werteliste enthalten ist.
[RequiredIfContains(nameof(Zahlungsart), "Rechnung", "Kreditkarte", ErrorMessage = "Bitte erfassen Sie die Referenznummer")]
public string Referenznummer { get; set; }
Weitere Konfigurationen
| Option | Wirkung |
|---|---|
TargetValuesProperty |
Liest die Zielwerte zur Validierungszeit aus einer Eigenschaft des Modells (Array oder Liste) statt aus der Annotation — dazu die Überladung nur mit dependentProperty verwenden |
DisableIfNotRequired / HideIfNotRequired |
Wie bei [RequiredIf] |
Clientseitig rendert das Attribut data-val-requiredifcontains-* (Skript jquery.validate.unobtrusive.requiredifcontains.js).
Text
Einfache Textbox für string ohne Validierung.
@model TextBeispielViewModel
<form asp-area="Basis" asp-controller="Text" asp-action="Index" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
@Html.EditorFor(m => m.Vorname)
@Html.Fmh(Fmh.Button()
.Text("Absenden")
.Size(ButtonSize.Sm)
.Attributes(new { @class = "mt-2" }))
</form>
using System.ComponentModel.DataAnnotations;
namespace FMH.Komponente.WebUI.Areas.Basis.Models
{
public class TextBeispielViewModel
{
[Display(Name = "Vorname")]
public string Vorname { get; set; }
}
}
using FMH.Komponente.Basis.Erweiterungen;
using FMH.Komponente.Basis.Ui.Feedback.Alert;
using FMH.Komponente.WebUI.Areas.Basis.Models;
using Microsoft.AspNetCore.Mvc;
namespace FMH.Komponente.WebUI.Areas.Basis.Controllers.Beispiele
{
[Area("Basis")]
public class TextController : Controller
{
[HttpGet]
public IActionResult Index()
{
return this.View(new TextBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(TextBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Erfolgsfall: hier würden die eigentlichen Aktionen ausgeführt (z. B. Speichern).
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
// PRG-Pattern (Post-Redirect-Get): nach erfolgreichem POST per Redirect auf die
// GET-Action weiterleiten, damit ein erneutes Laden/Aktualisieren das Formular nicht
// nochmals abschickt (verhindert doppeltes Speichern).
return this.RedirectToAction(nameof(this.Index));
}
// Ungültige Eingabe: dieselbe Seite erneut anzeigen, damit die Validierungsfehler erscheinen.
return this.View(modell);
}
}
}
Darstellung
Das String-EditorTemplate (Views/Shared/EditorTemplates/String.cshtml aus FMH.Komponente.Basis) wird über den ASP.NET-Core-Standardmechanismus eingebunden — nicht über Html.Fmh(...):
@Html.EditorFor(m => m.Vorname)
Es rendert ein Bootstrap-Floating-Label-Textfeld mit Slots für Hilfetext und Validierungsmeldung. Der Anzeigename kommt aus den Model-Metadaten.
Weitere Konfigurationen (FMH)
| Attribut | Wirkung |
|---|---|
[Display(Name = "…")] |
Setzt den Anzeigenamen des Floating Labels |
[HelpText(Name = "…")] |
Ergänzender Hilfetext unter dem Feld (siehe Beispiel «Text mit Hilfetext») |
[Required] / [RequiredIf] |
Pflichtfeld-Verhalten (siehe die weiteren Beispiele auf dieser Seite) |
[UniqueId] |
Kollisionsfreie HTML-Ids bei mehrfach gerenderten Formularen |
Häufige Standard-DataAnnotations
Aus System.ComponentModel.DataAnnotations — server- und clientseitig (unobtrusive) wirksam. Alle unterstützen ErrorMessage bzw. ErrorMessageResourceType/-Name für lokalisierte Meldungen.
| Attribut | Wirkung |
|---|---|
[StringLength(50, MinimumLength = 3)] |
Begrenzt die Zeichenlänge (max. und optional min.); rendert maxlength und data-val-length |
[MaxLength(50)] / [MinLength(3)] |
Nur Ober- bzw. Untergrenze der Länge |
[RegularExpression(@"^[A-Z]{2}\d+$")] |
Erzwingt ein Muster; rendert data-val-regex |
[Range(1, 100)] |
Wertebereich (typischer bei Zahlenfeldern, funktioniert aber auch auf konvertierten Werten) |
[Compare(nameof(Passwort))] |
Wert muss mit einer anderen Eigenschaft übereinstimmen (z. B. Passwort-Bestätigung) |
[EmailAddress] |
Prüft ein E-Mail-Format (Framework-Standard; FMH-Variante siehe eigene Email-Demo) |
[Phone] |
Prüft ein Telefonnummern-Format |
[Url] |
Prüft ein URL-Format |
[CreditCard] |
Prüft eine Kreditkartennummer (Luhn) |
[DataType(DataType.Password)] |
Semantik-Hinweis fürs Rendering (z. B. type="password", type="email"), keine Validierung |
Text mit erforderlicher Eingabe
Pflichtfeld über [Required] – Absenden mit leerem Feld zeigt die Validierung.
@model TextErforderlichBeispielViewModel
<form asp-area="Basis" asp-controller="TextErforderlich" asp-action="Index" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
@Html.EditorFor(m => m.Nachname)
@Html.Fmh(Fmh.Button()
.Text("Absenden")
.Size(ButtonSize.Sm)
.Attributes(new { @class = "mt-2" }))
</form>
using System.ComponentModel.DataAnnotations;
namespace FMH.Komponente.WebUI.Areas.Basis.Models
{
public class TextErforderlichBeispielViewModel
{
[Display(Name = "Nachname")]
[Required(ErrorMessage = "Bitte Nachnamen eingeben")]
public string Nachname { get; set; }
}
}
using FMH.Komponente.Basis.Erweiterungen;
using FMH.Komponente.Basis.Ui.Feedback.Alert;
using FMH.Komponente.WebUI.Areas.Basis.Models;
using Microsoft.AspNetCore.Mvc;
namespace FMH.Komponente.WebUI.Areas.Basis.Controllers.Beispiele
{
[Area("Basis")]
public class TextErforderlichController : Controller
{
[HttpGet]
public IActionResult Index()
{
return this.View(new TextErforderlichBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(TextErforderlichBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Erfolgsfall: hier würden die eigentlichen Aktionen ausgeführt (z. B. Speichern).
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
// PRG-Pattern (Post-Redirect-Get): nach erfolgreichem POST per Redirect auf die
// GET-Action weiterleiten, damit ein erneutes Laden/Aktualisieren das Formular nicht
// nochmals abschickt (verhindert doppeltes Speichern).
return this.RedirectToAction(nameof(this.Index));
}
// Ungültige Eingabe: dieselbe Seite erneut anzeigen, damit die Validierungsfehler erscheinen.
return this.View(modell);
}
}
}
Darstellung
Pflichtfeld über das Standard-Attribut [Required]. Das EditorTemplate erkennt die Pflicht über die Model-Metadaten und kennzeichnet das Feld; die Validierung läuft server- und clientseitig (unobtrusive Validation).
[Required(ErrorMessage = "Bitte erfassen Sie den Nachnamen")]
public string Nachname { get; set; }
Weitere Konfigurationen
| Option | Wirkung |
|---|---|
ErrorMessage |
Eigene Fehlermeldung statt der Framework-Standardmeldung |
ErrorMessageResourceType / -Name |
Lokalisierte Meldung aus einer Ressourcenklasse |
Text mit Hilfetext
Ergänzender Hilfetext beim Eingabefeld über [HelpText].
@model TextHilfetextBeispielViewModel
<form asp-area="Basis" asp-controller="TextHilfetext" asp-action="Index" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
@Html.EditorFor(m => m.Raum)
@Html.Fmh(Fmh.Button()
.Text("Absenden")
.Size(ButtonSize.Sm)
.Attributes(new { @class = "mt-2" }))
</form>
using System.ComponentModel.DataAnnotations;
using FMH.Komponente.Basis.Ui.Validation.DataAnnotation;
namespace FMH.Komponente.WebUI.Areas.Basis.Models
{
public class TextHilfetextBeispielViewModel
{
[Display(Name = "Raum")]
[HelpText(Name = "Geben Sie den bevorzugten Raum für die Tätigkeiten an.")]
public string Raum { get; set; }
}
}
using FMH.Komponente.Basis.Erweiterungen;
using FMH.Komponente.Basis.Ui.Feedback.Alert;
using FMH.Komponente.WebUI.Areas.Basis.Models;
using Microsoft.AspNetCore.Mvc;
namespace FMH.Komponente.WebUI.Areas.Basis.Controllers.Beispiele
{
[Area("Basis")]
public class TextHilfetextController : Controller
{
[HttpGet]
public IActionResult Index()
{
return this.View(new TextHilfetextBeispielViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(TextHilfetextBeispielViewModel modell)
{
if (this.ModelState.IsValid)
{
// Erfolgsfall: hier würden die eigentlichen Aktionen ausgeführt (z. B. Speichern).
this.AddAlert("Formular ist gültig – Validierung erfolgreich.", AlertType.Success, autoHide: true);
// PRG-Pattern (Post-Redirect-Get): nach erfolgreichem POST per Redirect auf die
// GET-Action weiterleiten, damit ein erneutes Laden/Aktualisieren das Formular nicht
// nochmals abschickt (verhindert doppeltes Speichern).
return this.RedirectToAction(nameof(this.Index));
}
// Ungültige Eingabe: dieselbe Seite erneut anzeigen, damit die Validierungsfehler erscheinen.
return this.View(modell);
}
}
}
Darstellung
Ergänzender Hilfetext über [HelpText]. Der Text erscheint beim Eingabefeld und wird über GetName() aufgelöst.
[HelpText(Name = "Gebäude und Raumnummer, z. B. A 2.17")]
public string Raum { get; set; }
Weitere Konfigurationen
| Option | Wirkung |
|---|---|
Name |
Der Hilfetext direkt — oder der Ressourcen-Schlüssel, falls ResourceType gesetzt ist |
ResourceType |
Ressourcenklasse für lokalisierte Hilfetexte; unbekannter Schlüssel ergibt einen leeren Text |