Kurs:Täglich Model Binding Übungen

Aus ahrensburg.city
Version vom 24. Juni 2025, 04:23 Uhr von Thorsten (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „= Model Binding & Validation – ASP.NET Core MVC (Spickzettel) = == Standard-Model-Binding (Query, Route, Form) == <syntaxhighlight lang="csharp"> // Route mit optionalen Parametern (aus Query oder Route gebunden) [Route("buchladen/{buchid?}/{eingeloggt?}")] public IActionResult Index(int? buchid, bool? eingeloggt) { return Content($"Buch-ID: {buchid}, Eingeloggt: {eingeloggt}", "text/plain"); } // Route mit festem (required) Parameter (aus Route…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Model Binding & Validation – ASP.NET Core MVC (Spickzettel)

Standard-Model-Binding (Query, Route, Form)

// Route mit optionalen Parametern (aus Query oder Route gebunden)
[Route("buchladen/{buchid?}/{eingeloggt?}")]
public IActionResult Index(int? buchid, bool? eingeloggt)
{
    return Content($"Buch-ID: {buchid}, Eingeloggt: {eingeloggt}", "text/plain");
}

// Route mit festem (required) Parameter (aus Route gebunden)
[Route("shop/buecher/{id}")]
public IActionResult Buch()
{
    int id = Convert.ToInt32(Request.RouteValues["id"]);
    return Content($"<h1>Buch-Shop {id}</h1>", "text/html");
}

[FromQuery] und [FromRoute] verwenden

[Route("buchladen/{buchid?}/{eingeloggt?}")]
public IActionResult Index([FromQuery] int? buchid, [FromRoute] bool? eingeloggt)
{
    // Explizites Binding: buchid nur aus Query, eingeloggt nur aus Route
    return Content($"Buch-ID: {buchid}, Eingeloggt: {eingeloggt}");
}

Model Binding mit Modelklassen

// Modelklasse
public class Buch
{
    public int? BuchId { get; set; }
    public string? Autor { get; set; }
    public override string ToString() => $"Buch: {BuchId}, Autor: {Autor}";
}

// Controller
[Route("buchladen/{buchid?}/{eingeloggt?}")]
public IActionResult Index([FromQuery] int? buchid, [FromRoute] bool? eingeloggt, Buch buch)
{
    return Content($"Buch-ID: {buchid}, Buch: {buch}", "text/plain");
}

Model Validation mit DataAnnotations

using System.ComponentModel.DataAnnotations;

public class Person
{
    [Required(ErrorMessage = "{0} darf nicht leer sein")]
    public string? Name { get; set; }

    [EmailAddress]
    public string? Email { get; set; }

    [Compare("Passwort", ErrorMessage = "Passwörter stimmen nicht überein")]
    public string? PasswortBestätigung { get; set; }
}

// Controller
public IActionResult Erstellen(Person person)
{
    if (!ModelState.IsValid)
        return View(person);
    // Speicherung etc.
}

Custom Validation Attribute Beispiel

// Validator: ToDate >= FromDate
public class DatumsbereichValidatorAttribute : ValidationAttribute
{
    public string VonProperty { get; }
    public DatumsbereichValidatorAttribute(string vonProperty) => VonProperty = vonProperty;
    protected override ValidationResult? IsValid(object? value, ValidationContext context)
    {
        if (value is DateTime toDate)
        {
            var fromProp = context.ObjectType.GetProperty(VonProperty);
            if (fromProp?.GetValue(context.ObjectInstance) is DateTime fromDate && fromDate > toDate)
                return new ValidationResult(ErrorMessage, new[] { VonProperty, context.MemberName! });
        }
        return ValidationResult.Success;
    }
}

Model-Level Validation mit IValidatableObject

public class Person : IValidatableObject
{
    public DateTime? Geburtsdatum { get; set; }
    public int? Alter { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext context)
    {
        if (!Geburtsdatum.HasValue && !Alter.HasValue)
            yield return new ValidationResult("Geburtsdatum ODER Alter muss angegeben werden", new[] { nameof(Alter) });
    }
}

[Bind] und [BindNever] Attribute

// Nur bestimmte Felder binden
[HttpPost]
public IActionResult Erstellen([Bind("Titel", "Beschreibung")] Produkt produkt) { ... }

// Niemals aus Request binden
public class Produkt
{
    [BindNever]
    public DateTime ErstelltAm { get; set; }
}

[FromBody]: JSON/XML Body-Parameter binden

[Route("registrieren")]
public IActionResult Index([FromBody] Person person)
{
    if (!ModelState.IsValid) { ... }
    return Content($"{person}");
}

Collection Binding (Listen/Arrays binden)

public class Person
{
    public List<string?> Interessen { get; set; } = new();
}

// JSON: { "Name": "Anna", "Interessen": ["Musik", "Lesen", "Coding"] }
public IActionResult Index(Person person)
{
    return Content($"Person: {person.Name}, Interessen: {string.Join(",", person.Interessen)}");
}

[FromHeader]: Parameter aus HTTP-Header

[Route("registrieren")]
public IActionResult Index(Person person, [FromHeader(Name = "User-Agent")] string userAgent)
{
    return Content($"{person}, {userAgent}");
}

Input Formatters registrieren (z.B. XML)

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers().AddXmlSerializerFormatters();

Custom Model Binder registrieren

// Custom Binder implementieren
public class PersonModelBinder : IModelBinder { ... }

// BinderProvider registrieren (Startup/Program.cs)
builder.Services.AddControllers(options => {
    options.ModelBinderProviders.Insert(0, new PersonBinderProvider());
});

Übungen / Mini-Aufgaben

  • Schreibe eine Controller-Methode, die einen Parameter aus der Query und einen aus der Route bindet.
  • Erstelle ein Model mit mindestens drei Properties und validiere sie mit DataAnnotations.
  • Schreibe ein Custom ValidationAttribute, das prüft, ob ein Datum in der Zukunft liegt.
  • Nutze [FromBody], um ein komplettes Model aus JSON im Request-Body zu binden.
  • Verwende [BindNever], um eine Eigenschaft vor Overposting zu schützen.
  • Binde eine Liste von Strings im Model und fülle sie über ein Array im Request.
  • Hole den User-Agent per [FromHeader] und gib ihn in der Response aus.