Click here to Skip to main content
Click here to Skip to main content

PRG Pattern - Post Redirect Get

, 7 Aug 2012
Rate this:
Please Sign up or sign in to vote.
PRG or Post Redirect Get pattern focuses on solving the typical problem where the user presses F5 or refresh button and causes duplicate database transactions.

Introduction

Patterns do help developers solve a typical problem. This problem can be anything. For example, MVC pattern solves the problem of separation of concerns. Here in this tip, I am going to discuss about the PRG pattern. This pattern solves the typical problem where the user presses F5 key and causes duplicate transactions.

Background

Most of the web applications built with any kind of technology, be it ASP.NET, PHP, JSP, etc. have to handle some or the other code to prevent insertion of duplicate records when user presses F5 (or the Refresh key). Some people simply try to disable the F5 key which is a wrong way (also has less success rates) because the user has the full right to press F5 and most of the users hate it when they see such prompts which say that he/she cannot press the F5 key!

Problem

Most of the users are unaware of the side effects of F5. It has a bad effect when the last request was a POST request – because it may or may not cause duplicate records in your database. Even browsers prompt such tasks. The screenshot below warns the user that the process might cause some problems.


Even if the prompt has all its details, most of the users would not even read it, i.e., it’s ignored completely. The side effects of this has to be borne on the developer; usually coding too much just to avoid such duplications.

Solution

The solution to such a problem can be solved by the pattern called PRG or Post Redirect Get. In simple terms, this pattern asks us to follow simple steps mentioned below and get our problem solved.

  1. Submit the form via POST.
  2. Submit the changes in database.
  3. Redirect the user to another page or the same page with optionally displaying the success.

Code Sample

Let us look at a practical example where we can actually see how the pattern can be accomplished via coding with ASP.NET.

The scenario is there is an Add Employee form available which submits the entry of the new employee as shown in the figure below:

The radio button list is just for demonstration purposes that we have three options right now for submitting the form. Let us get to them one by one.

  1. No Redirection - This is the default functionality of the POST. The data is stored in the database and if the user presses F5 or Refresh button, duplicate transaction occurs.
  2. Same Page - This will show a success message and redirect the page to itself. One can press F5 and see that there are actually no duplicate transactions.
  3. Different Page - This will cause the page to redirect to another page after the data is saved.

In the sample I have included, to make things simple, I have avoided a database. And one more point I would like to tell you is that I am not a designer but I have styled the app a little bit. It is not interesting what is in the ASPX code. What is interesting is the code behind .cs file which causes different result.

The .cs file looks like the following:

protected void btnSaveRecord_Click(object sender, EventArgs e)
{
    var firstName = txtBxFirstName.Text;
    var lastName = txtBxLastName.Text;

    SaveAndRedirect(firstName, lastName);
}

private void SaveAndRedirect(string firstName, string lastName)
{
    bool isSaved = true; // this will actually be a database transaction.

    if (isSaved)
    {
        switch (RadioButtonList1.SelectedIndex)
        {
            //No need to handle case 0 as we have already saved the data and it has no redirection.
            case 1: //Redirection to the same page.
            ScriptManager.RegisterClientScriptBlock
            (
                this,
                this.GetType(),
                "success",
                "alert('Data saved successfully!');window.location.assign('"
                + ResolveUrl("AddEmployee.aspx") + "');",
                true
            ); //Show success message and redirect to the same page.
            break;
            case 2: //Redirection to different page.
            Response.Redirect(@"~\Success.aspx");
            break;
            default:
            break;
        }
    }
    else
    {
        ScriptManager.RegisterClientScriptBlock
        (
            this,
            this.GetType(),
            "failure",
            "alert('There was an error saving your data!');",
            true
         );
    }
}

In the code above, I have used a simple switch case where I check the option. I have simulated a database transaction which returns a boolean value. I check the result and redirect the user.

If the option first was selected, then I do not redirect the user. In this case, if the user refreshes the page, duplicate transactions happen. This is because of the default behaviour of the POST request.

In the second option, I use JavaScript to show an alert that the data was saved and use JavaScript based redirection to the same page. In this way, if the user requests a refresh, the user is sent to the same page as the JavaScript redirection to the page caused a GET request. This is perfect when we have a scenario like adding multiple records where we show a grid of the records just below the page. The user can see the updated records right below the add window.

In the third option, I redirect the user to a different page. This is so obvious that we can redirect the user to another page and cause no duplicate transactions. This is perfect for certain scenarios where we just want the user to add some details and navigate to the different page.

Points of Interest

The most interesting thing I learnt while working with PRG is that it is really very simple and requires a lot less code. First I thought that it is very difficult to implement but later it turned out to be very simple. I thought it would be great to share a simple yet useful pattern which will certainly help you out in the real world.

History

  • Version 1.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Pankaj Nikam
Software Developer
India India
Currently a .NET Developer. Passionate about Microsoft .NET Technologies.
Follow on   Twitter   Google+   LinkedIn

Comments and Discussions

 
GeneralMy vote of 3 PinmemberCraigWagner8-Aug-12 5:13 
GeneralRe: My vote of 3 PinmemberPankaj Nikam8-Aug-12 7:20 
QuestionConversion tracking PinmemberDavid Kemp8-Aug-12 4:10 
AnswerRe: Conversion tracking PinmemberPankaj Nikam8-Aug-12 7:04 
GeneralRe: Conversion tracking PinmemberDavid Kemp10-Aug-12 5:32 
AnswerRe: Conversion tracking PinmemberPankaj Nikam10-Aug-12 6:27 
GeneralMy vote of 4 Pinmembergauravpandey7-Aug-12 9:28 
GeneralRe: My vote of 4 PinmemberPankaj Nikam7-Aug-12 15:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140821.2 | Last Updated 7 Aug 2012
Article Copyright 2012 by Pankaj Nikam
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid