This pattern is used to solve the double submit problem. When a user tries to refresh the result page of a post request, The page is resubmitted again resulting in undesirable results like double withdrawal of account, multiple orders etc.
If a post request is supposed to return a page, instead it should does its side effect operation(e.g. saving order) and redirect to a get request that returns the page. Thus result of the get request could be bookmarked and can be requested as needed with out a side effect(undesired additional orders).
The double submit problem is explained in depth in this article by Michael Jouravlev.
Using the ASP.Net MVC framework it is simple to implement the PRG pattern, below you will find a small
code snipnet that uses the RPG pattern.
Step1(POST) Controller action will make a redirect to Step 1(GET request) on error or if successful it will make a GET request to the next step 2(GET). Step 1(POST) doesn't build and return pages it self.
[HttpGet]
[ImportModelStateFromTempData]
public ActionResult Step1(int id)
{
var m = _orderService.GetOrder(id);
return View(m);
}
[HttpPost]
[ExportModelStateToTempData]
public ActionResult Step1(Order m)
{
//If the model is valid(satisfies all the validation requirements set for it)
//persist it and make a get request to the next step
//else make a redirect to GET request page
if (ModelState.IsValid)
{
// save
-orderService.Save(m);
// Go to the next step (Step 2 here is a HttpGet ActionResult)
return RedirectToAction("Step2", new { id = m.OrderId });
}
//redirect to the Get Request
return RedirectToAction("Step1",new {id =m.OrderId});
}
[HttpGet]
[ImportModelStateFromTempData]
public ActionResult Step2(int id)
{
var m = _orderService.GetOrder(id);
return View(m);
}