【ASP.NET基础】.net 防止页面刷新重复提交(转载自----->Warren专栏)
在客户端保存一个标志,在服务端也保存一个标志,在提交时对比两个标志的值,来判断是否是重复提交。
先看下面代码,首先是一个RefreshAction静态类,这个类主要是用来初始化服务端Session保存上一次票证的值并且对比客户端和服务端票证的值,当检测到刷新不是重复刷新时,将要把客户端的票证值更新到服务端
[c-sharp] view plaincopy public static class RefreshAction { // 常量 //服务端票证key public const string LastRefreshTicketEntry = "__LASTREFRESHTICKET"; //客户端票证key public const string CurrentRefreshTicketEntry = "__CURRENTREFRESHTICKET"; //用来保存是否是重复刷新的属性的key public const string PageRefreshEntry = "IsPageRefresh"; private static Hashtable requestHistory = null; //存储请求历史 // 检测F5按钮是否被按下 public static void Check(HttpContext ctx) { //初始化服务端票证 EnsureRefreshTicket(ctx); //从Session里读取上一次提供的票证 int lastTicket = GetLastRefreshTicket(ctx); //从请求里的隐藏域里读取当前页面的票证 int thisTicket = GetCurrentRefreshTicket(ctx); // 对比两个票证 if (thisTicket > lastTicket || (thisTicket == lastTicket && thisTicket == 0)) { //如果当前的票证值大于上一次的票证值 或者 //当前票证值等于上一次票证值,并且当前票证值为0(这是第一次刷新) //那么更新Session里上一次的票证值为当前票证值 UpdateLastRefreshTicket(ctx, thisTicket); //设置当前页是否重复刷新属性为false ctx.Items[PageRefreshEntry] = false; } else { //设置当前页是否重复刷新属性为true; ctx.Items[PageRefreshEntry] = true; } } //确认上一次的票证不为空值 static void EnsureRefreshTicket(HttpContext ctx) { if (requestHistory == null) requestHistory = new Hashtable(); } //得到上一次请求的票证值 static int GetLastRefreshTicket(HttpContext ctx) { if (!requestHistory.ContainsKey(ctx.Request.Path)) return 0; else return (int) requestHistory[ctx.Request.Path]; } //从当前请求里的到隐藏域里保存的当前票证值 static int GetCurrentRefreshTicket(HttpContext ctx) { return Convert.ToInt32(ctx.Request[CurrentRefreshTicketEntry]); } // 将当前的票证值保存到Session里的上一次刷新的票证值 private static void UpdateLastRefreshTicket(HttpContext ctx, int ticket) { requestHistory[ctx.Request.Path] = ticket; } }//end class
下面是一个HttpModule类,在请求开始时就来检测双方的票证值
[c-sharp] view plaincopy public class RefreshModule : IHttpModule { public RefreshModule() { // // TODO: Add constructor logic here // } #region IHttpModule Members public void Dispose() { throw new NotImplementedException(); } public void Init(HttpApplication app) { //注册请求关联状态时的事件处理器,就是说当一个请求到达服务器, //那么首先触发这个事件,由OnAcquireRqeustState事件处理 app.AcquireRequestState += new EventHandler(this.OnAcquireRequestState); } #endregion private void OnAcquireRequestState(object sender, EventArgs e) { HttpApplication app = sender as HttpApplication; HttpContext ctx = app.Context; RefreshAction.Check(ctx); //RefreshAction类来检查当前请求的上下文 Rey return; } }//end class
- public class RefreshModule : IHttpModule
- {
- public RefreshModule()
- {
- //
- // TODO: Add constructor logic here
- //
- }
- #region IHttpModule Members
- public void Dispose()
- {
- throw new NotImplementedException();
- }
- public void Init(HttpApplication app)
- {
- //注册请求关联状态时的事件处理器,就是说当一个请求到达服务器,
- //那么首先触发这个事件,由OnAcquireRqeustState事件处理
- app.AcquireRequestState += new EventHandler(this.OnAcquireRequestState);
- }
- #endregion
- private void OnAcquireRequestState(object sender, EventArgs e)
- {
- HttpApplication app = sender as HttpApplication;
- HttpContext ctx = app.Context;
- RefreshAction.Check(ctx); //RefreshAction类来检查当前请求的上下文 Rey
- return;
- }
- }//end class