2017-10-16 4 views
1

Ich habe ein Problem beim Erstellen einer benutzerdefinierten Modell-Binder in asp.net Core 2. Ich lese dies Tutorial, aber das ist nicht was ich brauche.asp.net Core 2 Custom Model Binder mit komplexem Modell

Ich habe einen Build ein Beispiel und auf github

Ich habe eine einfache Person-Klasse wie folgt aus:

public class Person 
{ 
    public int ID { get; set; } 

    [Required] 
    public string Firstname { get; set; } 

    [Required] 
    public string Surename { get; set; } 

    [Required] 
    [DisplayFormat(DataFormatString = "{0:dd.MMM.yyyy}")] 
    public DateTime DateOfBirth {get;set;} 

    [Required] 
    public Country Country { get; set; } 
} 

public class Country 
{ 
    public int ID { get; set; } 

    public string Name { get; set; } 

    public string Code { get; set; } 
} 

Wenn ich eine neue Person hinzufügen kann ich das Land mit einem HTML-select-Tag wählen . Aber der Wert des Select-Tags ist die Länder-ID, und ich möchte, dass der Binder in der Datenbank nachschlägt und das richtige Land zum Modell hinzufügt.

Die create-Methode im Controller sieht wie folgt aus:

[HttpPost] 
    [ValidateAntiForgeryToken] 
    public async Task<IActionResult> Create([Bind("ID,Firstname,Surename,DateOfBirth")] Person person, int Country) 
    { 
     ViewData["Countries"] = _context.Countries.ToList(); 

     if (ModelState.IsValid) 
     { 
      _context.Add(person); 
      await _context.SaveChangesAsync(); 
      return RedirectToAction(nameof(Index)); 
     } 
     return View(person); 
    } 

ich die Daten auch eine IModelBinder implementieren zu binden:

public class PersonEntityBinder : IModelBinder 
{ 
    public Task BindModelAsync(ModelBindingContext bindingContext) 
    { 
     if (bindingContext == null) 
     { 
      throw new ArgumentNullException(nameof(bindingContext)); 
     } 

     // here goes the fun 

     // looking for the countryId in the bindingContext 

     // binding everything else except the CountryID 

     // search the Country by countryID and put it to the model 


     return Task.CompletedTask; 
    } 
} 

Die Frage ist, wie kann ich dies tun, wie ich schrieb in den Kommentaren in der Mappe? Wer ist eine Idee oder eine Best-Practice-Lösung?

Bezug auf Chris

+0

Warum möchten Sie etwas komplexes für eine grundlegende Aktion tun? Fügen Sie einfach die Eigenschaft public int CountryId {get; Stellen Sie;} zu Ihrem Modell und setzen Sie die Landesidentifikation darauf.Entitätsframework erledigt den Rest für Sie – OrcusZ

Antwort

2

Erstens ist dies eine schlechte Verwendung eines Bindemittels benutzerdefinierten Modells. Der Datenzugriff sollte im Controller erfolgen, da dies in der Verantwortung des Controllers liegt. Zweitens, don't use [Bind]. Wie ernst. Tu es einfach nicht. Es ist schrecklich, und es tötet Kätzchen.

Erstellen Sie eine Ansicht Modell wie:

public class PersonViewModel 
{ 
    public string FirstName { get; set; } 
    public string Surname { get; set; } 
    public DateTime DateOfBirth { get; set; } 
    public int CountryID { get; set; } 
} 

Dann haben Sie diese stattdessen Aktion akzeptieren (keine Notwendigkeit mehr für [Bind]):

public async Task<IActionResult> Create(PersonViewModel model) 

Dann in Ihrer Aktion, zeichnen sie die gebuchten Werte zu einer neuen Instanz Person und füllen Sie die Country Eigenschaft, indem Sie aus der Datenbank suchen:

var person = new Person 
{ 
    FirstName = model.FirstName, 
    Surname = model.Surname, 
    DateOfBirth = model.DateOfBirth, 
    Country = db.Countries.Find(model.CountryID) 
} 

Speichern Sie dann person wie gewohnt.

+0

Ok, das weiß ich aus einigen Java-Frameworks, und meiner Meinung nach ist es der beste Weg. Es sieht so aus, als könnte ich dem Scaffold-Code von Visual Studio nicht vertrauen. Danke –

+0

Nun, ein Gerüst kann nur so viel tun. Wo Menschen falsch liegen, ist die Annahme, dass das Gerüst dort ist, wo es beginnt und endet. Der Punkt ist, Ihnen einen Ausgangspunkt zu geben. Es wird davon ausgegangen, dass Sie den Code anpassen und zu Ihrem eigenen machen werden. –

Verwandte Themen