解决因页面刷新而导致重复操作的问题

用过ASP.NET的都知道,按钮操作之后会得到一个新的页面,然后用户通过浏览器的回退按钮可以回到原来的页面时,或者点刷新按钮刷新当前页面时,会显示对话框"不重新发送信息,则无法刷新页面",然后就有个"重试","取消"按钮,通常用户为了刷新页面而点击"重试",这样一点问题就来了,那么页面就会重复发送信息,并且执行先前按钮的操作,比如按钮是添加一行数据,那么刷新之后就会添加重复的数据.好的程序或许会报个提示说什么不能重复添加,甚至出个异常,没有限制的程序可能就任由用户重复的添加数据.这样当然是开发人员不想发生的,除非有极端的用户需求.
最近学了下HttpModule的内容,可用来解决这个问题.
这里利用HttpModule在页面请求之前,做一些操作,用一些标记标识每个请求的页面,程序如下,相互学习下.
首先有个类继承IHttpModule
NoRepeatOperModule
 1public class NoRepeatOperModule : IHttpModule
 2    {
 3        /**//// <summary>
 4        /// 保存访问的页面记录,以页面路径为key, 标号为value
 5        /// </summary>

 6        static Hashtable historyRequest = null;
 7
 8        /**//// <summary>
 9        /// 请求路径
10        /// </summary>

11        private string RequestPath
12        {
13            get
14            {
15                return HttpContext.Current.Request.Path;
16            }

17        }

18
19        IHttpModule 成员#region IHttpModule 成员
20
21        public void Dispose()
22        {
23            //throw new Exception("The method or operation is not implemented.");
24        }

25
26        public void Init(HttpApplication context)
27        {
28            if (historyRequest == null)
29            {
30                historyRequest = new Hashtable();
31            }

32
33            context.BeginRequest += delegate(object sender, EventArgs e)
34            {
35                int lastTicket = GetLastTicket();
36                int currentTicket = GetCurrentTicket(lastTicket);
37
38                // 比较当前标号和上一个的标号,判断页面请求是否来源于刷新操作
39                // 当前标号大于上一个标号 或初次请求都属于新的页面
40                if (currentTicket > lastTicket || (lastTicket == currentTicket && currentTicket == 0))
41                {
42                    // 标记并保存页面请求是否来源于刷新的bool值
43                    HttpContext.Current.Items[RequestPath + "_IsRefreshed"= false;
44                    historyRequest[RequestPath] = currentTicket;
45                }

46                else
47                {
48                    HttpContext.Current.Items[RequestPath + "_IsRefreshed"= true;
49                }

50            }
;
51        }

52
53        #endregion

54
55        /**//// <summary>
56        /// 获取某页面的上一个标号
57        /// </summary>
58        /// <returns></returns>

59        private int GetLastTicket()
60        {
61            if (!historyRequest.ContainsKey(RequestPath))
62            {
63                return 0;
64            }

65
66            return int.Parse(historyRequest[RequestPath].ToString());
67        }

68
69        /**//// <summary>
70        /// 获取页面的当前标号
71        /// </summary>
72        /// <param name="lastTicket">上一个标号</param>
73        /// <returns></returns>

74        private int GetCurrentTicket(int lastTicket)
75        {
76            int ticket;
77            // CurrentTicket 为页面的隐藏域的内容
78            string currentTicket = HttpContext.Current.Request["CurrentTicket"];
79            if (currentTicket == null)
80            {
81                ticket = lastTicket;
82            }

83            else
84            {
85                ticket = int.Parse(currentTicket);
86            }

87
88            // 保存页面的下一个标号
89            HttpContext.Current.Items[RequestPath + "_NextTicket"= ticket + 1;
90            return ticket;
91        }

92    }

第二步,在web.config中配置自定义的HttpModule
Web.Config配置
1<system.web>
2      <httpModules>
3        <add name="NoRepeatOperModule" type="AspAdvance1.NoRepeatOperModule, AspAdvance1"/>
4      </httpModules>
5</system.web>

最后还要在asp.cs文件中处理如下,加个属性IsRefreshed,重写基类的 OnPreRenderComplete,最后调用在 btnTest_Click
其实可以吧以下作为自定义的Page类,其他页面继承即可
具体页面实现
 1public partial class _Default : System.Web.UI.Page
 2    {
 3        /**//// <summary>
 4        /// 页面请求是否来源于页面刷新
 5        /// </summary>

 6        private bool IsRefreshed
 7        {
 8            get
 9            {
10                string requestPath = HttpContext.Current.Request.Path;
11                return (bool)HttpContext.Current.Items[requestPath + "_IsRefreshed"];
12            }

13        }

14
15        /**//// <summary>
16        /// 重写OnPreRenderComplete,生成隐藏域CurrentTicket
17        /// </summary>
18        /// <param name="e"></param>

19        protected override void OnPreRenderComplete(EventArgs e)
20        {
21            base.OnPreRenderComplete(e);
22            string requestPath = HttpContext.Current.Request.Path;
23            int ticket = int.Parse(HttpContext.Current.Items[requestPath + "_NextTicket"].ToString());
24            ClientScript.RegisterHiddenField("CurrentTicket", ticket.ToString());
25        }

26
27        protected void btnTest_Click(object sender, EventArgs e)
28        {
29            // 根据IsRefreshed 判断页面请求是否来源于刷新来 判断是否进行操作
30            if (!IsRefreshed)
31            {
32                using (StreamWriter sw = new StreamWriter("E:\\test.txt"true))
33                {
34                    sw.WriteLine(DateTime.Now.ToString());
35                }

36            }

37        }

38    }

点击btnTest之后会写入一行,此时页面重新生成,点刷新或回退,再点"重试",将不会重复原来的操作.

转载于:https://www.cnblogs.com/shenba/archive/2007/10/16/926717.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值