Wir haben Ansichtsmodelle, die andere Ansichtsmodelle enthalten. Ich habe zum Beispiel ein Navigationsansichtsmodell unter fast jedem anderen Ansichtsmodell, da jeder Bildschirm eine Navigation hat. Die Logik für den Aufbau des Navigationsansichtsmodells befindet sich an einer Stelle.
Das Problem ist, dass Referenztypen, wie die Ansichtsmodelle, während des POST-Vorgangs gelöscht werden. Das ist zwar sinnvoll, aber es bedeutet, dass wir die Ansichtsmodelle teilweise neu erstellen müssen, wenn wir jemals wieder zur Ansicht zurückkehren müssen, z. B. wenn die Validierung fehlschlägt. Wir können die Ansichtsmodelle nicht einfach von Grund auf neu erstellen, da sie teilweise eingegebene Daten enthalten.
Im Moment überprüfen wir ModelState.IsValid manuell und bauen jedes untergeordnete Ansichtsmodell manuell neu auf. Wir eliminieren doppelte Logik, indem wir Typen namens Builders erstellen, die unsere View-Modelle konstruieren. Diese Builder haben derzeit drei Build-Methoden: eine für die Erstellung eines leeren View-Modells, eine für die Behandlung von Validierungsproblemen und eine für die Bearbeitung.
ViewModel Build(<params>) // create
void Build(ViewModel, <params>) // validation error
ViewModel Build(DBObject, <params>) // edit
Das scheint mir zu viel des Guten zu sein. In 90 % der Fälle, wenn eine Eigenschaft ein anderes Ansichtsmodell ist, sollte sie einfach neu erstellt werden. Es wäre schön, wenn es eine 3rd-Party-Bibliothek, die ein Ansichtsmodell zu einer Builder-Klasse zuordnen würde, nur konstruieren sie auf einer as-needed-Basis. Es wäre natürlich rekursiv und würde auch Child-View-Modelle erstellen. Anstelle von:
return View(viewModel)
oder
return RedirectToAction("index", "home", viewModel)
dann gäbe es einfach Helfer wie:
return View<ViewModel>()
oder
return RedirectToAction<ViewModel>("index", "home")