Čvc
24
PRG, neboli post-redirect-get, se obvykle používá k zamezení
vícenásobného odeslání formuláře, který mění data. Také se ale
používá jako náhrada GET formulářů, pokud chcete mít kontrolu nad URL
různých filtrovaných výpisů, vyhledávání (/search/fráze
místo /search?query=fráze) apod.
Prostě se formuláři nastaví metoda POST a po odeslání se přesměruje metodou GET na správně sestavené URL.
V nejjednodušších případech se to dá realizovat nějak takto:
public class HomeController : Controller
{
/// <summary>
/// GET: /Log
/// </summary>
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult List(ListViewModel model)
{
return View(model);
}
/// <summary>
/// POST: /Log
/// </summary>
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult List(ListViewModel model)
{
return RedirectToAction("List", model);
}
Potíže mohou nastat ve složitějších případech. Například pokud viewmodel obsahuje nějaké veřejné properties, které se nebindují. Tomu se ale z několika důvodů vyhýbám. Pro úplnost:
public class HomeController : Controller
{
/// <summary>
/// GET: /Log
/// </summary>
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult List([Bind(Include = "CategoryFilter,YearFilter")]ListViewModel model)
{
return View(model);
}
/// <summary>
/// POST: /Log
/// </summary>
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult List([Bind(Include = "CategoryFilter,YearFilter")]ListViewModel model)
{
return RedirectToAction("List", new {
CategoryFilter = model.CategoryFilter,
YearFilter = model.YearFilter
});
}
Snad chápete, proč (mimo jiné) se tomu vyhýbám. Uplatňuju zásadu, že pouze vstup může být u viewmodelu veřejnou property.
Další nepříjemnost nastává, když výchozí hodnota některé property
není null, třeba číslo stránky u stránkovaných výpisů.
Nepříjemnost tkví v tom, že se nám tyto výchozí hodnoty dostávají do
URL a to nepůsobí nejlepším dojmem (?page=1).
Tento problém se ale týká tvorby odkazů obecně (a nejen v ASP.NET MVC). Myslím, že mám takové polovičaté řešení (jestli mi zase nedojde, že to je blbost), ale je třeba na tom ještě trochu zapracovat, takže si to nechám pro příště.
