屏蔽刷新提交后台(重复提交)

现象:当页面进行过数据提交(PostBack)后,如果通过点击【F5】或者浏览器的【刷新】按钮,

    此时页面会模拟浏览器的上次的提交事件,如果做的是数据插入操作,将有可能导致数据的多次插入。

原因:浏览器会模拟上次提交的数据在次提交,并在此触发上次提交的时间。

 

对策:

针对此,网上已经有各种各样的处理方法。大概有以下的两类:

1。通过在事件中,在插入数据之前做主键冲突判定。

2。在HttpHandler中添加票据处理,然后在事件处理中判断是否是刷新进行提交的。 

两种方法都需要对事件做特殊的处理,对于项目维护的复杂度有所增加,尤其是第一种需要做数据的逻辑判断,已经影响到了业务逻辑,这是很不好的方法。

 

  然而,我们是否可以让浏览器的刷新成为我们真正想要的刷新,即从新访问页面,而不是模拟上次的提交数据。

其实如果大家对第二种方式熟悉的话,他就是我们想要的方式,然而他需要每个页面的事件都做判断,因而维护程度较复杂,针对此本人做了一些改进。

 

具体修改方案如下:

 1.在页面中声明两个HiddenField,第一个存储前台页面的票据,第二存储后台Session票据的Key。

2.如果前台的票据和Session的票据不相同,则即为刷新,此时DeterminePostBackMode方法返回空,以使页面置为 非PostBack的状态。

3.在OnPreRenderComplete中同步HiddenField和Session中的票据。

为了让各个页面对此事不可见的,将上述逻辑完全封装到Basepage中,使页面完全不需做其他处理。

实例:

BasePage:

 

using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace DonkeyControl
 7 {
 8     public class BasePage : System.Web.UI.Page
 9     {
10         private static string PAGE_REFRESH_TICKET_KEY = "__PageRefreshTicketKey";
11         private string PAGE_SESSION_REFRESH_TICKET_KEY = "__PageSessionRefreshTicketKey";
12 
13         /// <summary>
14         /// 判断是否是PostBack
15         /// </summary>
16         /// <returns></returns>
17         protected override System.Collections.Specialized.NameValueCollection DeterminePostBackMode()
18         {
19             //如果是通过"刷新"提交的后台,将页面强行设置成非PostBack模式,以实现刷新以重新的访问页面的形式进行
20             if (IsRefreshed)
21             {
22                 return null;
23             }
24             return base.DeterminePostBackMode();
25         }
26 
27         protected override void OnPreRenderComplete(EventArgs e)
28         {
29             SynchroRefreshTicket();
30             base.OnPreRenderComplete(e);
31         }
32 
33         /// <summary>
34         /// 同步页面和后台Session的票据
35         /// </summary>
36         private void SynchroRefreshTicket()
37         {
38             if (!Page.IsPostBack)
39             {
40                 string strTicket = Guid.NewGuid().ToString();
41                 ClientScript.RegisterHiddenField(PAGE_REFRESH_TICKET_KEY, strTicket);
42                 ClientScript.RegisterHiddenField(PAGE_SESSION_REFRESH_TICKET_KEY, strTicket);
43                 Session[strTicket] = strTicket;
44             }
45             else
46             {
47                 string strTicket = Guid.NewGuid().ToString();
48                 ClientScript.RegisterHiddenField(PAGE_REFRESH_TICKET_KEY, strTicket);
49                 ClientScript.RegisterHiddenField(PAGE_SESSION_REFRESH_TICKET_KEY, Request.Form[PAGE_SESSION_REFRESH_TICKET_KEY]);
50                 Session[Request.Form[PAGE_SESSION_REFRESH_TICKET_KEY]] = strTicket;
51             }
52         }
53 
54 
55         /// <summary>
56         /// 比较HiddenField的票据和Session中存储的票据是否相同,如果不相同则为通过刷新的方式进行的提交
57         /// </summary>
58         protected bool IsRefreshed
59         {
60             get
61             {
62                 if(string.Equals(Request.Form.Get(PAGE_REFRESH_TICKET_KEY),Session[Request.Form.Get(PAGE_SESSION_REFRESH_TICKET_KEY)]))
63                 {
64                     return false;
65                 }
66                 else
67                 {
68                     return true;
69                 }
70             }
71         }
72     }
73 }
74 

 

 

测试页面:

Default.aspx
 1  <% @ Page Language = " C# "  AutoEventWireup = " true "  CodeBehind = " Default.aspx.cs "  Inherits = " WebTest._Default "   %>
 2 
 3  <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
 4  < html  xmlns ="http://www.w3.org/1999/xhtml" >
 5  < head  runat ="server" >
 6       < title > Untitled Page </ title >
 7  </ head >
 8  < body >
 9       < form  id ="form1"  runat ="server" >
10       < div >
11           < asp:Label  ID ="Label1"  runat ="server" ></ asp:Label >
12           < asp:Button  ID ="Button1"  runat ="server"  Text ="Button"   />
13       </ div >
14       </ form >
15  </ body >
16  </ html >
17 

 

 

Default.aspx.cs
 1  using  System;
 2  using  System.Collections;
 3  using  System.Configuration;
 4  using  System.Data;
 5  using  System.Linq;
 6  using  System.Web;
 7  using  System.Web.Security;
 8  using  System.Web.UI;
 9  using  System.Web.UI.HtmlControls;
10  using  System.Web.UI.WebControls;
11  using  System.Web.UI.WebControls.WebParts;
12  using  System.Xml.Linq;
13  using  DonkeyControl;
14 
15 
16  namespace  WebTest
17  {
18       public   partial   class  _Default : BasePage
19      {
20           protected   void  Page_Load( object  sender, EventArgs e)
21          {
22               if  ( this .IsRefreshed)
23              {
24                  Label1.Text  =   " 刷新 " ;
25              }
26               else
27              {
28                  Label1.Text  =   " 正常postback " ;
29              }
30          }
31      }
32  }
33 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值