02 June 2015

PRG (post-redirect-get) pattern in web application development

Today let’s learn Post-Redirect-Get pattern in web app development by applying it to an ASP.NET MVC application.

Problem statement

Assume that you are developing an e-commerce web app and you need to process the customer credit card information while checking out an order. In ASP.NET MVC web development technology, the action method to process payment would something like below:

[HttpPost]
public ActionResult ProcessPayment(string cardNumber, 
string cvv, string customerName)
  {
     //Step1: Validate credit card details
     //Step2: Charge the customer credit card
     //Step3: Send payment confirmation view
     return View("Confirmation");
 }

With above controller action method, everything works expect one bug. After successful order placement while viewing the Confirmation page, if customer presses F5 button, the browser will show the duplicate transaction warning dialog.

Duplicate transaction submission warning message

If you click Retry button, the ProcessPayment () action method will be called and depending the logic written in the method, the customer might get charged again. Definitely this is not good customer experience and should be prevented.

Why duplicate transaction warning

Let’s first understand why browser is displaying the duplicate transaction warning and what is happening under the wood.

Sequence diagram showing Request/Response flow causing the issue

UML sequence diagram showing duplicate form submit issue

Browser resends the last request to web application on pressing F5 (Refresh) key. In this case the last request is HTTP post submitting the form details. So the same HTTP post request will be submitted once again. The browser will detect this and display a duplicate transaction message to user.

Applying PRG pattern to prevent duplicate form submission issue

The PRG pattern will be implemented as below:

  1. POST the form details.
  2. Send REDIRECT response to browser with URL location where to look for the response.

  3. Browser sends GET request to obtain the response from URL location present in the HTTP 302 redirect result.

Code changes to implement PRG pattern:

  1. Update the POST action method to Send RedirectToRouteResult specifying the Confirmation action
    [HttpPost]
    public ActionResult ProcessPayment(string cardNumber, 
    string cvv, string customerName)
     {
      //Step1: Validate credit card details
      //Step2: Charge the customer credit card
      //Step3: Send RedirectToRouteResult specifying
      //       the Confirmation action
      return RedirectToAction("Confirmation");
     }
  2. Add Confirmation GET action method to send the Confirmation view
    [HttpGet]
    public ActionResult Confirmation()
     {
       return View();
     }

Now upon successful submission of credit card details and you will see the confirmation page. While viewing the confirmation page, if you press the REFRESH button, you will get to see confirmation page but without the duplicate form submission warning.

Request/response flow with PRG pattern

UML sequence diagram showing post-redirect-get(PRG) pattern

With PRG pattern we can prevent browser showing the duplicate transaction dialog to user. Make sure you implement PRG pattern with every POST request.

Caveat with PRG pattern

With PRG pattern, there is an extra request/response cycle between client and server. This additional request/response cycle will impact your application performance. But that said, don’t put aside the pattern implementation instead look for other ways to improve application performance.

No comments:

Post a Comment