2 Stimmen

Wiederauffüllen verschachtelter ViewModels nach fehlgeschlagener Validierung

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")

3voto

Darin Dimitrov Punkte 990883

Ich habe zum Beispiel ein Navigationsansichtsmodell unter so ziemlich jeder anderen View-Modellen, da jeder Bildschirm eine Navigation hat. Die Logik für Erstellung des Navigationsansichtsmodells befindet sich an einer Stelle.

Das scheint ein guter Kandidat für die Aufteilung Ihrer Ansichtsmodelle und die Verwendung der Html.Action-Helfer um Ihr Navigationsmenü über eine separate untergeordnete Aktion darzustellen.

Auf diese Weise müssen Sie sich nicht mehr um das Hauptaktions- und Ansichtsmodell kümmern.

Die Idee ist also, dass Sie einen Menü-Controller haben könnten, der für die Erstellung des Menüs verantwortlich ist:

public class MenuController: Controller
{
    private readonly IMenuRepository _repository;
    public MenuController(IMenuRepository repository)
    {
        _repository = repository;
    }

    [ChildActionOnly]
    public ActionResult Index()
    {
        var menu = _repository.GetMenu();
        var menuViewModel = Mapper.Map<Menu, MenuViewModel>(menu); // AutoMapper example
        return View(menuViewModel);
    }
}

dann die entsprechende Indexansicht, bei der es sich um eine Teilansicht handelt, die nur das Menü-Markup enthält:

@model MenuViewModel
@{
    Layout = null;
}
<ul>
   <li>....
   <li>....
</ul>

und dann können Sie das Menü innerhalb Ihres _Layouts an der definierten Stelle rendern:

@Html.Action("index", "menu")

Dann könnten Sie Controller und View-Modelle haben, die völlig losgelöst von diesem Menü-Rendering sind.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X