ASP.NET MVC: perzistence formulářových dat a PRG

V jednom z předchozích článků jsem popsal, jak téměř bezpracně zajistit perzistenci dat při přesměrování. Řešení bylo postavené na tom, že se hodnoty z ModelState uložily před přesměrováním do TempData (což je v drtivé většině případů de facto session). Hodnoty z formulářových polí se do ModelState dostanou během model-bindingu, tzn. že typicky máme ViewModel, který použijeme jako parametr action method, nebo voláme metodu [Try]UpdateModel. V popsaném případě se nám do ModelState uloží všechny hodnoty, které se měly možnost se nabidnovat na properties ViewModelu.

Popsaný způsob je typický a myslím, že pokryje většinu aplikací, protože reflektuje stavění aplikace odspoda. Tedy business vrstva je závislá na tom, jak vypadá datová vrstva a prezentační vrstva je do jisté míry závislá na tom, jak vypadá business vrstva. Poslední větu si lze vyložit i tak, že děláme formuláře na míru business entitám, příp. jejich agregacím, nikoliv obráceně. Může se ale vyskytnout i taková situace, kdy pro formulář nemáme odpovídající ViewModel, tedy nedojde k uložení zadaných hodnot do ModelState, protože nemáme na co bindovat formulářová data. Ale přesto chceme ctít PRG, přičemž logickým požadavkem je nějak přenést ona zadaná formulářová data. Nejsnadnějším způsobem je převést problém na předchozí případ – tedy uložit formulářová data do ModelState.

I tuto funkcionalitu můžeme implementovat poměrně jednoduše. Stačí, abychom vytvořili model-binder pro třídu FormCollection, kterou uvádíme jako parametr action method. V tomto model-binderu jednoduše projdeme všechna formulářová pole a hodnoty uložíme do ModelState:

public class PersistingFormCollectionBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (controllerContext == null)
        {
            throw new ArgumentNullException("controllerContext");
        }
        var res = new FormCollection(controllerContext.HttpContext.Request.Form);
        foreach (var key in res.AllKeys)
        {
            if (!bindingContext.ModelState.ContainsKey(key))
            {
                var value = res[key];
                bindingContext.ModelState.Add(key, new ModelState { Value = new ValueProviderResult(value, value, System.Globalization.CultureInfo.CurrentCulture) });
            }
        }
        return res;
    }
} 

Pak už jen stačí tento náš model-binder zaregistrovat, typicky v metodě Application_Start v souboru global.asax.cs:

ModelBinders.Binders[typeof(FormCollection)] = new PersistingFormCollectionBinder(); 

Zanechat odpověď

Vyplňte detaily níže nebo klikněte na ikonu pro přihlášení:

Logo WordPress.com

Komentujete pomocí vašeho WordPress.com účtu. Odhlásit /  Změnit )

Google photo

Komentujete pomocí vašeho Google účtu. Odhlásit /  Změnit )

Twitter picture

Komentujete pomocí vašeho Twitter účtu. Odhlásit /  Změnit )

Facebook photo

Komentujete pomocí vašeho Facebook účtu. Odhlásit /  Změnit )

Připojování k %s

Tento web používá Akismet na redukci spamu. Zjistěte více o tom, jak jsou data z komentářů zpracovávána.