How to avoid adding repeat submit the same data if you click the 'Refresh' button of Browser?
After reading this book(Programming Microsoft ASP.NET 2.0 Applications - Advanced Topics), I get some ideas about this issue.
Usually, we may need to avoid doing the repeat operation when the user click the 'Refresh' button of Browser. How to prevent it?
Actually, we can save the operation times for each request page in HashTable in Custom HttpModule.
//Page
using System;
using System.Web;
using System.Web.UI;
namespace ProAspNet20.Advanced.CS.Components
{
public class Page : System.Web.UI.Page
{
#region New Properties
public bool IsRefreshed
{
get
{
object o = HttpContext.Current.Items[RefreshAction.PageRefreshEntry];
if (o == null)
return false;
return (bool) o;
}
}
#endregion
#region Overrides
// **************************************************************
// Handle the PreRenderComplete event
protected override void OnPreRenderComplete(EventArgs e)
{
base.OnPreRenderComplete(e);
SaveRefreshState();
}
#endregion
#region Helpers
// **************************************************************
// Create the hidden field to store the current request ticket
private void SaveRefreshState()
{
int ticket = (int)HttpContext.Current.Items[RefreshAction.NextPageTicketEntry];
ClientScript.RegisterHiddenField(RefreshAction.CurrentRefreshTicketEntry,
ticket.ToString());
}
#endregion
}
}
using System.Web;
using System.Web.UI;
namespace ProAspNet20.Advanced.CS.Components
{
public class Page : System.Web.UI.Page
{
#region New Properties
public bool IsRefreshed
{
get
{
object o = HttpContext.Current.Items[RefreshAction.PageRefreshEntry];
if (o == null)
return false;
return (bool) o;
}
}
#endregion
#region Overrides
// **************************************************************
// Handle the PreRenderComplete event
protected override void OnPreRenderComplete(EventArgs e)
{
base.OnPreRenderComplete(e);
SaveRefreshState();
}
#endregion
#region Helpers
// **************************************************************
// Create the hidden field to store the current request ticket
private void SaveRefreshState()
{
int ticket = (int)HttpContext.Current.Items[RefreshAction.NextPageTicketEntry];
ClientScript.RegisterHiddenField(RefreshAction.CurrentRefreshTicketEntry,
ticket.ToString());
}
#endregion
}
}
//Reresh Action
using System;
using System.Web;
using System.Collections;
namespace ProAspNet20.Advanced.CS.Components
{
public class RefreshAction
{
#region Constants
// ***********************************************************
// Constants
public const string LastRefreshTicketEntry = "__LASTREFRESHTICKET";
public const string CurrentRefreshTicketEntry = "__CURRENTREFRESHTICKET";
public const string PageRefreshEntry = "IsRefreshed";
public const string NextPageTicketEntry = "__NEXTPAGETICKET";
#endregion
static Hashtable requestHistory = null;
// ***********************************************************
// Manage to check if the F5 button has been pressed
public static void Check(HttpContext ctx)
{
// Initialize the ticket slot
EnsureRefreshTicket(ctx);
// Read the last ticket served in the session (from Session)
int lastTicket = GetLastRefreshTicket(ctx);
// Read the ticket of the current request (from a hidden field)
int thisTicket = GetCurrentRefreshTicket(ctx, lastTicket);
// Compare tickets
if (thisTicket > lastTicket ||
(thisTicket==lastTicket && thisTicket==0))
{
UpdateLastRefreshTicket(ctx, thisTicket);
ctx.Items[PageRefreshEntry] = false;
}
else
{
ctx.Items[PageRefreshEntry] = true;
}
}
// ***********************************************************
// Initialize the internal data store
private static void EnsureRefreshTicket(HttpContext ctx)
{
// Initialize the session slots for the page (Ticket) and the module (LastTicketServed)
if (requestHistory == null)
requestHistory = new Hashtable();
}
// ***********************************************************
// Return the last-served ticket for the URL
private static int GetLastRefreshTicket(HttpContext ctx)
{
// Extract and return the last ticket
if (!requestHistory.ContainsKey(ctx.Request.Path))
return 0;
else
return (int) requestHistory[ctx.Request.Path];
}
// ***********************************************************
// Return the ticket associated with the page
private static int GetCurrentRefreshTicket(HttpContext ctx, int lastTicket)
{
int ticket;
object o = ctx.Request[CurrentRefreshTicketEntry];
if (o == null)
ticket = lastTicket;
else
ticket = Convert.ToInt32(o);
ctx.Items[RefreshAction.NextPageTicketEntry] = ticket + 1;
return ticket;
}
// ***********************************************************
// Store the last-served ticket for the URL
private static void UpdateLastRefreshTicket(HttpContext ctx, int ticket)
{
// Item overwrites, Add does not
requestHistory[ctx.Request.Path] = ticket;
}
}
}
using System.Web;
using System.Collections;
namespace ProAspNet20.Advanced.CS.Components
{
public class RefreshAction
{
#region Constants
// ***********************************************************
// Constants
public const string LastRefreshTicketEntry = "__LASTREFRESHTICKET";
public const string CurrentRefreshTicketEntry = "__CURRENTREFRESHTICKET";
public const string PageRefreshEntry = "IsRefreshed";
public const string NextPageTicketEntry = "__NEXTPAGETICKET";
#endregion
static Hashtable requestHistory = null;
// ***********************************************************
// Manage to check if the F5 button has been pressed
public static void Check(HttpContext ctx)
{
// Initialize the ticket slot
EnsureRefreshTicket(ctx);
// Read the last ticket served in the session (from Session)
int lastTicket = GetLastRefreshTicket(ctx);
// Read the ticket of the current request (from a hidden field)
int thisTicket = GetCurrentRefreshTicket(ctx, lastTicket);
// Compare tickets
if (thisTicket > lastTicket ||
(thisTicket==lastTicket && thisTicket==0))
{
UpdateLastRefreshTicket(ctx, thisTicket);
ctx.Items[PageRefreshEntry] = false;
}
else
{
ctx.Items[PageRefreshEntry] = true;
}
}
// ***********************************************************
// Initialize the internal data store
private static void EnsureRefreshTicket(HttpContext ctx)
{
// Initialize the session slots for the page (Ticket) and the module (LastTicketServed)
if (requestHistory == null)
requestHistory = new Hashtable();
}
// ***********************************************************
// Return the last-served ticket for the URL
private static int GetLastRefreshTicket(HttpContext ctx)
{
// Extract and return the last ticket
if (!requestHistory.ContainsKey(ctx.Request.Path))
return 0;
else
return (int) requestHistory[ctx.Request.Path];
}
// ***********************************************************
// Return the ticket associated with the page
private static int GetCurrentRefreshTicket(HttpContext ctx, int lastTicket)
{
int ticket;
object o = ctx.Request[CurrentRefreshTicketEntry];
if (o == null)
ticket = lastTicket;
else
ticket = Convert.ToInt32(o);
ctx.Items[RefreshAction.NextPageTicketEntry] = ticket + 1;
return ticket;
}
// ***********************************************************
// Store the last-served ticket for the URL
private static void UpdateLastRefreshTicket(HttpContext ctx, int ticket)
{
// Item overwrites, Add does not
requestHistory[ctx.Request.Path] = ticket;
}
}
}
//RereshModule
using System;
using System.Web;
using System.Web.SessionState;
namespace ProAspNet20.Advanced.CS.Components
{
public class RefreshModule : IHttpModule
{
#region IHttpModule
// ***********************************************************
// IHttpModule::Init
public void Init(HttpApplication app)
{
// Register for pipeline events
app.BeginRequest += new EventHandler(this.OnAcquireRequestState);
}
// ***********************************************************
// IHttpModule::Dispose
public void Dispose()
{
}
#endregion
#region Helpers
// ***********************************************************
// Determine if a F5 or back/fwd action is in course
private void OnAcquireRequestState(object sender, EventArgs e)
{
// Get access to the HTTP context
HttpApplication app = (HttpApplication)sender;
HttpContext ctx = app.Context;
// Check F5 action
RefreshAction.Check(ctx);
return;
}
#endregion
}
}
using System.Web;
using System.Web.SessionState;
namespace ProAspNet20.Advanced.CS.Components
{
public class RefreshModule : IHttpModule
{
#region IHttpModule
// ***********************************************************
// IHttpModule::Init
public void Init(HttpApplication app)
{
// Register for pipeline events
app.BeginRequest += new EventHandler(this.OnAcquireRequestState);
}
// ***********************************************************
// IHttpModule::Dispose
public void Dispose()
{
}
#endregion
#region Helpers
// ***********************************************************
// Determine if a F5 or back/fwd action is in course
private void OnAcquireRequestState(object sender, EventArgs e)
{
// Get access to the HTTP context
HttpApplication app = (HttpApplication)sender;
HttpContext ctx = app.Context;
// Check F5 action
RefreshAction.Check(ctx);
return;
}
#endregion
}
}
//TestRefresh
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="TestRefresh.aspx.cs" Inherits="TestRefresh" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Test Refresh</title>
</head>
<body>
<form id="Form1" method="post" runat="server">
<table border="2">
<tr>
<td bgcolor="yellow" rowspan="2">
<h1 id="Msg" runat="server"></h1>
</td>
</tr>
</table>
<hr>
<asp:textbox id="FName" runat="server" text="Dino" />
<asp:textbox id="LName" runat="server" text="Esposito" /><br>
<asp:button id="AddContactButton" runat="server" text="Add Contact" Font-Bold="True" OnClick="AddContactButton_Click"></asp:button><asp:button id="ResetButton" runat="server" text="Clear Contacts" Font-Bold="True" OnClick="ResetButton_Click"></asp:button>
<br>
<a target="_blank" href="TestRefresh.aspx">Display a copy of me</a>
<hr>
<asp:GridView ID="grid" runat="server">
</asp:GridView>
</form>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Test Refresh</title>
</head>
<body>
<form id="Form1" method="post" runat="server">
<table border="2">
<tr>
<td bgcolor="yellow" rowspan="2">
<h1 id="Msg" runat="server"></h1>
</td>
</tr>
</table>
<hr>
<asp:textbox id="FName" runat="server" text="Dino" />
<asp:textbox id="LName" runat="server" text="Esposito" /><br>
<asp:button id="AddContactButton" runat="server" text="Add Contact" Font-Bold="True" OnClick="AddContactButton_Click"></asp:button><asp:button id="ResetButton" runat="server" text="Clear Contacts" Font-Bold="True" OnClick="ResetButton_Click"></asp:button>
<br>
<a target="_blank" href="TestRefresh.aspx">Display a copy of me</a>
<hr>
<asp:GridView ID="grid" runat="server">
</asp:GridView>
</form>
</body>
</html>
//Code
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.OleDb;
public partial class TestRefresh : ProAspNet20.Advanced.CS.Components.Page
{
protected void AddContactButton_Click(object sender, EventArgs e)
{
Msg.InnerText = "Added";
if (!this.IsRefreshed)
AddRecord(FName.Text, LName.Text);
else
Msg.InnerText = "Page refreshed";
}
protected void ResetButton_Click(object sender, EventArgs e)
{
}
#region Helpers
private void AddRecord(string fname, string lname)
{
}
private void BindData()
{
}
#endregion
}
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.OleDb;
public partial class TestRefresh : ProAspNet20.Advanced.CS.Components.Page
{
protected void AddContactButton_Click(object sender, EventArgs e)
{
Msg.InnerText = "Added";
if (!this.IsRefreshed)
AddRecord(FName.Text, LName.Text);
else
Msg.InnerText = "Page refreshed";
}
protected void ResetButton_Click(object sender, EventArgs e)
{
}
#region Helpers
private void AddRecord(string fname, string lname)
{
}
private void BindData()
{
}
#endregion
}
//web.config
<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="Refresh" type="ProAspNet20.Advanced.CS.Components.RefreshModule,ProAspCompLib"/>
</httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="Refresh" type="ProAspNet20.Advanced.CS.Components.RefreshModule,ProAspCompLib"/>
</httpModules>
浙公网安备 33010602011771号