Jak jinak na widgety v ASP.NET MVC

V předchozím článku jsem ukázal jednu možnost, jak implementovat v ASP.NET MVC (libovolné verze!) „sidebar widgety“. V tomto článku bych rád ukázal další možnosti realizace widgetů, na které nebyl v předchozím článku prostor. Ale ani tento článek není kompletním výčtem všech možností…

SuperModel

V předchozím řešení jsme od ViewModelu, který reprezentuje stránku s widgety, požadovali, aby implementoval rozhraní IViewModelWithWidgets. Pokud ale v našem projektu widgety podporuje drtivá většina stránek, nemusí být toto řešení nejvhodnější. Nechceme totiž v zájmu DRY opakovat definici property Widgets v každém ViewModelu, takže nakonec stejně skončíme u nějakého bázového ViewModelu (který jako jediný tuto property implementuje) a to se nám už nemusí líbit a můžeme začít šilhat po jiném řešení. Přitom ale nemusíme nutně slevovat z našeho požadavku, aby byla celá stránka reprezentována jedním „ViewModelem“.

Data pro celou stránku jsou totiž ve skutečnosti reprezentována třídou ViewDataDictionary, která je v Controlleru i v šabloně dostupná jako property ViewData. Jak již název napovídá, ViewDataDictionary není (zjednodušeně řečeno) nic jiného než Dictionary ze stringu na object, který má ale navíc další properties – a nejvíce na očích je právě property Model, ve které máme typicky instanci našeho ViewModelu.

Vhodnějším řešením, které nás už nebude nabádat k vytváření super-ViewModelu, je tak ukládání dat pro widgety pod nějakým klíčem přímo do ViewData. Kód v akčním filteru (metoda OnActionExecuted) se nám tak ztenčí na pouhé přímé přiřazení do ViewData. I kód v šabloně bude jednodušší – omezí se na zjištění, zda je ve ViewData obsažen požadovaný klíč.

Úplně nám tak odpadne potřeba zavádět nějaká infrastrukturní rozhraní jako v řešení z předchozího článku…

Ajaxizace

Uživatele našeho webu bude asi typicky zajímat především hlavní obsah stránky a nechce být zdržován tím, že bude muset čekat o chvilku déle než se načte nějaký zpropadený widget, který ho třeba v danou chvíli vůbec nezajímá. Jaké máme možnosti, když se vzdáme řešení s použitím Action Filterů?

Od ASP.NET MVC 2 máme k dispozici helper metody Html.Action a Html.RenderAction, pomocí kterých můžeme provést jakýsi Sub-Request. Dojde tedy k zavolání dané akční metody a spuštění vráceného ActionResultu (jako v případě běžného requestu). Výsledek můžeme získat buď ve formě stringu (Html.RenderAction) nebo je výsledek vyrenderován přímo na místo, kde voláme Html.Action. Toto je velmi silná zbraň a díky ní můžeme prezentační logiku koncipovat zcela jinak.

Ideální mi přijde situace, kdy máme pro každý widget jednu akční metodu a k ní odpovídající šablonu (~ascx~Partial View). Mohli bychom mít jeden „velký“ Controller jen pro akční metody widgetů, ale bude lepší mít pro každý widget samostatný Controller – widgety totiž mohou být interaktivní (tj. potřebovat další akční metody pro dodatečnou funkcionalitu) a pravděpodobně budou mít zcela rozdílné závislosti.

Pokud máme pro widget samostaný Controller a samostatnou šablonu, máme ho krásně separovaný. Úkolem hlavní stránky pak bude pouze zajistit volání Html.[Render]Action pro každý widget.

Separace nám přináší i další výhodu – volání akční metody je skvělý kandidát na kešování – můžeme využít standardní atribut OutputCache.

Nyní jsme ale stále v situaci, kdy se celá stránka načítá během jednoho requestu – ajaxizace je ale velmi jednoduchá! Pokud totiž akční metodu neoznačíme atributem ChildActionOnly, můžeme ji volat i samostatně v rámci normálního requestu (samozřejmě musíme zajistit, aby se k ní dalo doroutovat).
V hlavní stránce, která dosud volala Html.[Render]Action, se bude nyní generovat kód, který zajistí, že se widgety dotáhnou pomocí samostatných Ajax requestů (např. s využitím data atributů).

Pokud chceme minimalizovat počet Ajax requestů, můžeme udělat jednu pomocnou akční metodu, která spustí akční metody požadovaných widgetů – tím se dostaneme na jeden request pro hlavní stránku a druhý request pro widgety.

Závěr

V předchozím článku jsem nastínil způsob implementace widgetů, který byl oblíbený v době první verze ASP.NET MVC. V první části toho článku jsem ukázal jeho vylepšení, které nás nenutí používat bázové třídy pro ViewModely a nejen díky tomu je flexibilnější a méně invazivní.

Za nejlepší řešení v současné době ale považuji variantu s Html.[Render]Action, která přináší mnohem větší míru modularity a jako (příjemný) důsledek snadné kešování a podporu pro asynchronní načítání widgetů v samostatném requestu.

Každý projekt si ale žádá svoje a tyto dva články rozhodně nepopisují všechny možnosti, jak je možné widgety v ASP.NET MVC implementovat. Věřím ale, že články mohou posloužit jako inspirace při implementaci widgetů ve vašem projektu…

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 )

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.