Click here to Skip to main content
Click here to Skip to main content
Alternative Tip/Trick

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

, 10 Feb 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
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:
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:
#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:
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)

Share

About the Author

clbyrne
Software Developer Florida Department of Education
United States United States
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141220.1 | Last Updated 10 Feb 2012
Article Copyright 2012 by clbyrne
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid