The Post Redirect Get (PRG) pattern is used in web applications to prevent duplicate form submissions. If you are not using the PRG pattern, you might find your web application producing multiple business transactions. This is definitely something you don’t want happening in e-commerce or banking applications.
The PRG pattern is really simple to use in ASP.NET MVC, and you’re probably already using it without realising. Let’s take a look at an example that uses the PRG pattern.
ASP.NET MVC example using the PRG pattern
[HttpGet]
public ActionResult MakePayment()
{
// display the form
return View();
}
[HttpPost]
public ActionResult MakePayment(MakePaymentViewModel input)
{
// do business transaction
if (success)
return RedirectToAction("MakePaymentSuccess");
else
return View(input);
}
[HttpGet]
public ActionResult MakePaymentSuccess()
{
// return the view displaying
return View();
}
The above pseudo code shows the 3 step process in the PRG pattern.
- First the form is displayed that asks the user for some input.
- When the user submits the form, the POST action is called and either redirects on success, or returns the form again.
- The call to
RedirectToAction
calls the MakePaymentSuccess GET action.
Now if you were to refresh the browser or press back you would not be able to process a duplicate transaction. Let’s take a look at a slight change that would violate the PRG pattern.
Violating the PRG Pattern
If we were to return a view instead of calling the RedirectToAction method like shown below, we would violate the PRG pattern.
[HttpPost]
public ActionResult MakePayment(MakePaymentViewModel input)
{
// do business transaction
if (success)
return View("MakePaymentSuccess");
else
return View(input);
}
The above code is bad because although it displays the payment success page, if you refresh the page you will process the same transaction again. Users that tried to bookmark the payment success page, would really be bookmarking the make payment page.
As you can see, ASP.NET MVC makes it easy to use the PRG pattern, just make sure you remember to call RedirectToAction
from inside a POST request, unless you are returning the form for the user to correct invalid input.