Click here to Skip to main content
15,884,298 members
Articles / Web Development / ASP.NET
Alternative
Tip/Trick

How to prevent Re-Post action caused by pressing browser's Refresh button

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
10 Feb 2012CPOL1 min read 10.5K   1  
I did something similar with a PageToken class, but I put it in the Master Page so that I could implement it on any page that uses the Master Page. In our code we wrapped the session variables in their own class called Session variables.We needed a little more functionality for complex pages...

I did something similar with a PageToken class, but I put it in the Master Page so that I could implement it on any page that uses the Master Page. In our code we wrapped the session variables in their own class called Session variables.


We needed a little more functionality for complex pages where postbacks were fine for some actions, but not good for others. Once I identified the action buttons/events/links I then mapped out where the page token should be checked and where it should be generated. I then added code to either generate a new timestamp/key or check existing page tokens. For instance, there could be a list with items to review and the users would click an item and be sent to another page. If they clicked the back button and then tried to click an action button again there was a risk that the data could be modified again. So I would compare the page token and if it didn't match I would requery the data generate a new page token and let the user know that the page was refreshed. If they clicked back two times the hidden field page token still wouldn't match so they'd get the same message.


I made an interface IPageTokenView because we are using the MVP pattern and this allows our presenter classes access to the page tokens as well.


So for pages that involve transactions we can implement IPageTokenView. In the code-behind, I wrapped the master page methods. Then I identify transaction events and code it accordingly.


IPageTokenView:

C#
public interface IPageTokenView
{
    /// <summary>
    /// (removed to save space see Master Page comments below)
    /// </summary>
    void GeneratePageToken();

    /// <summary>
    /// (removed to save space see Master Page comments below)
    /// </summary>
    /// <returns>A timestamp value</returns>
    string GetLastPageToken { get;}

    /// <summary>
    /// (removed to save space see Master Page comments below)
    /// </summary>
    bool TokensMatch { get;}

}

Master Page:

C#
#region Tokens

/// <summary>
/// Used to change the value of hidden field and session variable so that they
/// can be compared at a later time when the user performs a subsequent action.
/// This is a hopeful workaround to the user's back button and browser cache.
/// Since the cache token (timestamp) won't match the session variable if this
/// method is implemented properly after presenter action(s)
/// It is based on a timestamp, but it can be changed to GUID or other
/// unique identifier.
/// </summary>
/// <seealso cref="TokensMatch" />
public void GeneratePageToken()
{
    SessionVariables currSession = new SessionVariables();
    hfMasterPageToken.Value = System.DateTime.Now.ToString();
    currSession.PageToken = hfMasterPageToken.Value;
}

/// <summary>
/// The last token from a successful operation.
/// Allows us to deal with the Back button to prevent an accidental posting
/// after a successful posting.  May not be needed.
/// </summary>
/// <returns>A timestamp value</returns>
public string GetLastPageToken
{
    get
    {
        SessionVariables currSession = new SessionVariables();
        return currSession.PageToken;
    }
}

/// <summary>
/// Determines whether or not the user is looking at a cached page,
/// i.e. used the back
/// button to prevent accidental postings or actions due to a client's
/// browser cache.
/// </summary>
public bool TokensMatch
{
    get
    {
        SessionVariables currSession = new SessionVariables();
        return (currSession.PageToken != null
            && currSession.PageToken == hfMasterPageToken.Value);
    }
}
#endregion Tokens

Sample page:

C#
public void btnGetLatest_Click(object sender, EventArgs e)
{
    //Code calls presenter class to get data and presenter
    //generates page token but snippet here
    this.GeneratePageToken();
}

protected void DoUpdate(object sender, DataGridCommandEventArgs e)
{
    DataGrid dg = sender as DataGrid;
    int pos = dg.EditItemIndex;
    string ID;
    ID = dg.Items[pos].Cells[1].Text;

    this.ResultsMessage = "";

    if (pos &lt; 0 || this.TokensMatch == false)
    {
        //Reload the data.
        btnGetLatest_Click(sender, e);
        this.MessageToUser =
         "Data reloaded.  Click Edit or Insert button to change.";
        this.MessageType = MessageToUserType.Success;
        this.DisplayMessageToUser = true;
        return;
    }

License

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


Written By
Software Developer Florida Department of Education
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --