hnlyh

ASP.NET怎么防止重复提交!

如何防止用户连续点击多下BUTTON后将数据插入到数据库中

加一个hidden。生成表单时,生成一个唯一的之。 
在保存真实数据之前,看该hidden的值是归属的表单是否已经提交过。

禁止按钮也可以刷新,你可以在点击按钮禁卡按钮,设置页面过期,并后跳转到另外一个页面, 
可以使用令牌来达到功能。在服务器保存一布尔值在Session中,在提交是验证Session值。

第一次点击后,将Button.Enable = false;数据存储完后,在类似这样的语句后面 conn.Close(); 加上一句 Button.Enable=true;

类似这样 
Button1_Click(object sender,EventArgs e) 

  Button1.Enable =false; 
  SaveData();//假设这个方法是保存数据的,执行完保存,把Enable启用即可。 
  Button1.Enable = true; 

人家说的是如何防止多次单击Button,没说是 aspx 页面。

if your Button control doesn\'t need to set OnClientClick property, you can just do this: 

<asp:Button ID="SearchButton" runat="server" Text="查詢"                    OnClientClick="this.disabled=true;this.form.submit();" UseSubmitBehavior="false" /> 


else if your Button Control need to set OnClientClick property: 
OnClientClick="return confirm(\'您確定要修改嗎?\');" 

you should use JavaScript or jQuery to avoid dummy users\' double clicking, like this: 

<html xmlns="http://www.w3.org/1999/xhtml" > 
<head runat="server"> 
    <title>未命名頁面 </title> 
    
<%-- 以下可用 
    <style type="text/css"> 
    .disable 
    { 
        border-style:none; 
        border-width: thin; 
         
        color: #CCCCCC; 
        cursor:wait; 
    } 
    </style> 

    <script type="text/javascript" language="javascript"> 
    function DisableButton() 
    { 
        document.getElementById("Button1").className  = "disable"; 
        document.getElementById("Button1").value = \'正在提交.\'; 
        document.getElementById("Button1").onclick=Function("return false;"); 
        return true; 
    } 
    </script> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 
        <asp:Button ID="Button1" runat="server" Text="Button(JS,CSS)" /> 
    </form> 
</body> 
</html> 


xx.aspx.cs 

protected void Page_Load(object sender, EventArgs e) 

    if (!IsPostBack) 
    { 
          Button1.Attributes.Add("onclick", "return DisableButton();"); 
    } 


    }

----------------------------------------------------------------------------------------

Asp.Net防止刷新重复提交数据小记 
最近在用Asp.Net编写点东西时遇到个问题:即用户在提交表单后按刷新就会重复提交数据,即所谓的“刷

新重复提交”的问题。在网上搜 一下,可以找到很多关于这方面的资料,其中有一篇是来自MSDN上的一种

解决方法: http://msdn.microsoft.com/library/default.asp?url=/library/en-

us/dnvs05/html/BedrockASPNET.asp  它是通过重新定义 System.Web.UI.Page 类来实现加载页面时,是

“刷新”、“后退”请求,还是正常请求,其他的页面则继承了自定义的这 个Page类。感觉他这个方法比

较独特,有例子可以下载,有兴趣的可以研究研究。 

网上最多的解决此类问题的方法就是不保存缓存,即提交后表单上的数据不会被浏览器的缓存保存,如果

此时再遇到刷新或者后退请求时, 就会显示“网页已过期”,数据也就不会重复提交了,这就起到了阻止

刷新重复提交的效果。 

下面以简单的提交一篇帖子为例,介绍禁用缓存防止刷新重复提交的方法,表单数据包括“标题”和“正

文”两个部分。 

以下是该方法的代码(post.aspx): 

 

[c-sharp] view plaincopy
 
  1. //页面加载    
  2.   
  3. protected void Page_Load(object sender, EventArgs e)    
  4.   
  5. {    
  6.   
  7.    //可以在页面加载时设置页面的缓存为“SetNoStore()”,即无缓存    
  8.   
  9.    Response.Cache.SetNoStore();    
  10.   
  11.    //Session中存储的变量“IsSubmit”是标记是否提交成功的    
  12.   
  13.    if ((bool)Session["IsSubmit"])    
  14.   
  15.    {    
  16.   
  17.      //如果表单数据提交成功,就设“Session["IsSubmit"]”为false    
  18.   
  19.      Session["IsSubmit"] = false;    
  20.   
  21.      //显示提交成功信息    
  22.   
  23.      ShowMsg.Text = " * 提交成功!";    
  24.   
  25.    }    
  26.   
  27.    else    
  28.   
  29.      //否则的话(没有提交,或者是页面刷新),不显示任何信息    
  30.   
  31.      ShowMsg.Text = "";    
  32.   
  33. }    
  34.   
  35. //提交按钮(btnOK)单击事件    
  36.   
  37. protected void btnOK_Click(object sender, EventArgs e)    
  38.   
  39. {    
  40.   
  41.    if (txtTitle.Text.ToString().Trim() == "")    
  42.   
  43.      //ShowMsg是用来显示提示信息的    
  44.   
  45.      ShowMsg.Text = " * 标题不能为空!";    
  46.   
  47.   else if (txtText.Text.ToString().Trim() == "")    
  48.   
  49.      ShowMsg.Text = " * 内容不能为空!";    
  50.   
  51.   else    
  52.   
  53.    {    
  54.   
  55.      //这里是将数据提交到数据库中,省略    
  56.   
  57.      /*   
  58. string sql = "insert into tab...values(...)";   
  59.  
  60.      MyConn.ExecQuery(sql);   
  61.  
  62.      */    
  63.   
  64.      //提交成功后,设“Session["IsSubmit"]”为true    
  65.   
  66.      Session["IsSubmit"] = true;    
  67.   
  68.      //强制转换页面(不可少,否则刷新仍会重复提交,仍转到本页),    
  69.   
  70.      通过页面的转换将缓存中的提交的数据都释放了,即提交的标单数据不会被保存到缓存里,    
  71.   
  72.      如果后退的话,将会出现该页无法显示    
  73.   
  74.      Response.Redirect("post.aspx");    
  75.   
  76.   }    
  77.   
  78. }    

 

上面这个方法非常简单也很实用,推荐大家使用。 

下面是我自己研究出来的另一种方法,该方法不同于“不保存缓存的方法”,它是让浏览器保存所有页面

缓存的。该方法通过随机码的方式 来判断是正常提交还是“刷新”或“后退”的。 

首先(提交页面是post.aspx)在 Session 中 增加变量 Rnd 用来存放随机码,同时在提交表单数据

时不做处理,而是让页面转到 post.aspx?r=x,这里“x”等于Session["Rnd"],这个时候在页面加载时,

通过判断r的值和Session["Rnd"]的值是否相同,如果相同就处理提 交的数据,否则即可认为是“刷新”

或者是“后退”操作了,最后再次付给Session["Rnd"]一个随机码。 

以下是该方法代码(post.aspx): 

 

[c-sharp] view plaincopy
 
  1. //页面加载    
  2.   
  3. protected void Page_Load(object sender, EventArgs e)    
  4.   
  5. {    
  6.   
  7.    //获取URL中请求的“r”值,如果“r”不存在则 r=""    
  8.   
  9.    string r = "";    
  10.   
  11.    if(Request.QueryString["r"] != null)    
  12.   
  13.      r = Request.QueryString["r"].ToString().Trim();    
  14.   
  15.    string t;    
  16.   
  17.    //获取 “Session” 中的 “Rnd” 值,用于和“r”比较    
  18.   
  19.    t = Session["Rnd"].ToString().Trim();    
  20.   
  21.    //如果“r=t”则为提交操作,即可对表单的数据进行处理    
  22.   
  23.   if(r == t)    
  24.   
  25.   {    
  26.   
  27.      if (txtTitle.Text.ToString().Trim() == "")    
  28.   
  29.        ShowMsg.Text = " * 标题不能为空!";    
  30.   
  31.      else if (txtText.Text.ToString().Trim() == "")    
  32.   
  33.        ShowMsg.Text = " * 内容不能为空!";    
  34.   
  35.      else      {    
  36.   
  37.        //这里是将数据提交到数据库中,省略    
  38.   
  39.        /*   
  40.  
  41.        string sql = "insert into tab...values(...)";   
  42.  
  43.        MyConn.ExecQuery(sql);   
  44.  
  45.        */    
  46.   
  47.        //提交成功后清空表单数据    
  48.   
  49.        txtTitle.Text = "";    
  50.   
  51.        txtText.Text = "";    
  52.   
  53.        //显示提交成功信息    
  54.   
  55.        ShowMsg.Text = " * 提交成功!";    
  56.   
  57.      }    
  58.   
  59.   }    
  60.   
  61.    //否则可以认为是“刷新”或者“后退”操作    
  62.   
  63.    else    
  64.   
  65.    {    
  66.   
  67.        txtTitle.Text = "";    
  68.   
  69.        txtText.Text = "";    
  70.   
  71.   }    
  72.   
  73.   //最后要重新获得“Session["Rnd"]”的值,并将“btnOK.PostBackUrl”设为“Session["Rnd"]”的值   
  74.   
  75.   Session["Rnd"] = MyRnd.Rnd();    
  76.   
  77.   btnOK.PostBackUrl ="post.aspx?r=" + Session["Rnd"].ToString().Trim();    
  78.   
  79. }    
  80.   
  81. //这里提交按钮(btnOK)单击事件就不需要写任何代码了    

 

通过这种方法,每次加载页面时“Session["Rnd"]”都将得到一个新的值,而在刷新或后退时就不会得到

相同的“r”和“t”值,数据也就 不会被重复提交,只有通过“btnOK”来提交的操作才会得到“r==t”

,数据才会被提交处理的,通过判断随机码的方式来阻止刷新重复提交就 可以实现了。 
 
 


1、提交后 禁用提交按钮(像CSDN这样)
2、数据处理成功马上跳转到另外一个页面!
 
操作后刷新的确是个问题,你可以使用跳转页面、关闭本页面,如果是有参数据条件来控制的,那就应该

好做了,可以直接修改window.location的值,把值的参数全部改掉,这样就可以了。我用的方法就是以上

的。
 document.all("save_"+idx).disabled=true;


刚才有位兄弟也这么问其实很简单
在提交的页面也就是数据库处理之前
if session("jy")=true then
response.write "错误,正在提交"
response.end
end if
在数据库处理完毕后,释放session("jy")
session("jy")=false
即可!


用SESSION 或者用个麻烦点的方法:

用window.open 弹出表单输入页面,点提交后关闭该页;

处理提交的ASP页也是用弹出,即先设定表单的target为"submit_form",点提交时window.open

("XXX.asp","submit_form"),然后用JS来提交表单,最后就是window.close();

对处理提交的ASP页,输入数据到数据库完成后,弹出对话框,“提交成功”什么的,最后也来个

window.close();

因为对于window.open()打开的窗口,用window.close()来关闭时不会弹出提示框,直接就关闭窗口了,这

样用户就根本没有机会做重复提交了。

不知道这样合不合你的意思
 
 
2、数据处理成功马上跳转到另外一个页面!
这个方法最简单
 
转:(原理借用)

首先,我们可以定义一个session变量用来保存一个表单的提交序列号。这里我定义为“$userLastAction

”。然后在表单里加入一个hidden变量,把值设为$userLastAction+1:
<input type=Hidden name=lastAction value=<? =$userLastAction+1 ?>>
最后,在处理提交之前判断表单是否已被提交过:
if($lastAction>$userLastAction and inputIsValid(...)){
$userLastAction++; // 序列号加1
// 处理表单数据
}
我一直使用这个
你的后台处理页面,也就是数据接收页面,执行完相关的操作后,使用下面的语句:
response.write("<script>alert(\'数据提交成功******\');window.location.href=\'你想要转向的页面的

地址\';</script>")
这样随便他返回后怎么刷新,显示的始终是“数据提交成功******”的对话框
 
 
Top
 
 回复人:arcow(冲星) ( ) 信誉:100 2004-10-24 17:09:40 得分:0
 

[c-sharp] view plaincopy
 
  1. <SCRIPT LANGUAGE="javascript">  
  2. <!--  
  3. function input(ok)  
  4. {  
  5. var M1=ok.ReplyContent.value;  
  6. if (M1==\'\'){  
  7. alert(\'回复内容不可以为空.\');  
  8. return false;  
  9. }  
  10. ok.B1.disabled =true;  
  11. ok.B2.disabled =true;  
  12. return true;  
  13. }  
  14. //-->  
  15. </script>  
  16. <form onsubmit="return input(this)">  
  17. <input type=text name=ReplyContent>  
  18. <input type="submit" value="发出回复" border="0" name="B1">  
  19. <input name="B2" TYPE="reset"value="重 写">  
  20. </form>  

 

这样就行了,提交后直接转到另一页面
 
 
 
1、让提交后返回历史记录

[c-sharp] view plaincopy
 
  1. Response.Write"<mce:script type="text/javascript"><!--  
  2. alert(\'OK!添加成功!\');history.back();  
  3. // --></mce:script>"  

 

2、提交后跳转到本页

[c-sharp] view plaincopy
 
  1. response.redirect "index.asp"  
  2.    
  3.  Response.Write"<mce:script language=javascript><!--  
  4. alert(\'提交成  
  5.   
  6. 功!\');window.location.href=\'"&Request.ServerVariables("Http_Referer")&"\';  
  7. // --></mce:script>"  

 

===========================================

防止网页后退

我们在进行数据库添加操作的时候,如果允许后退,而正巧有刷新了页面,就会再次执行添加操作,无疑

这不是我们需要的,像一般网上很多禁止缓存的代码,有时并不可靠,这时你只要在操作的页面加上<body

onbeforeunload="window.location.replace(\'\')">就可以了,在网页的里指定要定向的新页,再点后退,

看是不是不会再退到刚才的操作页面了,实际上已经把这个历史给删除了

[c-sharp] view plaincopy
 
  1. ============================  
  2. Response.Buffer=true;  
  3.     Response.ExpiresAbsolute=DateTime.Now.AddSeconds(-1);  
  4.     Response.Expires=0;  
  5.     Response.CacheControl="no-cache";  
  6. ==========  

  

 

1。在asp.net页面中的HTML处插入如下代码:

   

[c-sharp] view plaincopy
 
  1. <input id="hiddenTest" type="hidden" value="<%= GetToken() %>" name="hiddenTestN"/>  

 

2。在page_load里写上如下代码:

   

[c-sharp] view plaincopy
 
  1. //*******防页面刷新  
  2.             if (null == Session["Token"])  
  3.             {  
  4.                 SetToken();  
  5.             }  
  6.             //***********  

 

3。CS页面里加上如下方法

  

[c-sharp] view plaincopy
 
  1. public string GetToken()  
  2.         {  
  3.             if (null != Session["Token"])  
  4.             {  
  5.                 return Session["Token"].ToString();  
  6.             }  
  7.             else  
  8.             {  
  9.                 return string.Empty;  
  10.             }  
  11.         }  
  12.   
  13.         private void SetToken()  
  14.         {  
  15.             Session.Add("Token", UserMd5(Session.SessionID + DateTime.Now.Ticks.ToString()));  
  16.         }  
  17.   
  18.         protected string UserMd5(string str1)  
  19.         {  
  20.             string cl1 = str1;  
  21.             string pwd = "";  
  22.             MD5 md5 = MD5.Create();  
  23.             // 加密后是一个字节类型的数组   
  24.             byte[] s = md5.ComputeHash(Encoding.Unicode.GetBytes(cl1));  
  25.             // 通过使用循环,将字节类型的数组转换为字符串,此字符串是常规字符格式化所得   
  26.             for (int i = 0; i < s.Length; i++)  
  27.             {  
  28.                 // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母,如果使用大写  
  29.   
  30. (X)则格式后的字符是大写字符   
  31.                 pwd = pwd + s[i].ToString("X");  
  32.             }  
  33.             return pwd;  
  34.         }  

 

4。在要防刷新的地方写上:

    

[c-sharp] view plaincopy
 
  1. //*******防页面刷新  
  2.                 if (!Request.Form.Get("hiddenTestN").Equals(GetToken()))  
  3.                 {  
  4.                     return;  
  5.                 }  
  6.                 SetToken();  
  7.                 //***********  
  8.    

 --------------------------------------------------------

如果简单的在刷新时重新加载画面,通过window.location.href="url"可以很容易的实现,但是需求是要求在刷新时什么都不做,保留画面的状态,这下子可就复杂化了。

asp.net中分辨请求是重新请求还是通过刷新按钮再次请求不是很方便,为了实现这个效果,试过了很多的方式,一下面的两种为例。
1.

private bool pageRefreshed = false; //页面是否刷新提交
private bool refreshState = false; //ViewState中暂存的状态

然后重写Page的LoadViewState与SaveViewState方法:

protected override void LoadViewState(object savedState)
{
object[] states = (object[])savedState;
base.LoadViewState(states[0]);
refreshState = (bool)states[1];
if(Session["__PAGE_REFRESHED"] == null)
pageRefreshed = false;
else
pageRefreshed = refreshState != (bool)Session["__PAGE_REFRESHED"];
}

protected override object SaveViewState()
{
Session["__PAGE_REFRESHED"] = !refreshState;
object[] states = new object[2];
states[0] = base.SaveViewState();
states[1] = !refreshState;
return states;
}
private void Button1_Click(object sender, EventArgs e)
{
if (pageRefreshed )
{
label.Text="this is refreshed function";
}
else
{
label.Text="this is new request function";
}
}

这种方法虽然能够实现,但是在某些请款下不适应。如果画面上同时存在文本框和按钮式,设置按钮的autopostback="True"时,在修改完文本框的值,直接点击按钮(在文本框没有失去焦点时,直接点击按钮),这时的执行顺序是textchanged→textchanged→buttonclick,在第一次textchanged时,就把状态已经变成了true,按钮的不能执行。

2.codeproject找到了另外一种解决方法 原文地址:http://www.codeproject.com/Articles/18841/Refresh-Module

这种方式能够准确的判断是否是通过浏览器的刷新按钮进行的请求,而且使用起来也非常简单!

1.引用dll,修改配置文件

在配置文件中添加modules

<system.web>
<httpModules>
<add name="RefreshModule"
type="RefreshModule.Module, RefreshModule"/>
</httpModules>
</system.web>

wbapplication的情况下需要改成在system.webServer的modules的节点下追加modules

2.定义刷新时的行为

RefereshHelper.IsPageRefreshed这个参数就是用来判断是否是通过浏览器的书刷新按钮进行的请求。
其他的行为行为控制参照原文。

-------------------------------------------

网上最多的解决此类问题的方法就是不保存缓存,即提交后表单上的数据不会被浏览器的缓存保存,如果此时再遇到刷新或者后退请求时, 就会显示“网页已过期”,数据也就不会重复提交了,这就起到了阻止刷新重复提交的效果。

下面以简单的提交一篇帖子为例,介绍禁用缓存防止刷新重复提交的方法,表单数据包括“标题”和“正文”两个部分。

以下是该方法的代码(post.aspx):

//页面加载

protected void Page_Load(object sender, EventArgs e)

{

   //可以在页面加载时设置页面的缓存为“SetNoStore()”,即无缓存

   Response.Cache.SetNoStore();

   //Session中存储的变量“IsSubmit”是标记是否提交成功的

   if ((bool)Session["IsSubmit"])

   {

     //如果表单数据提交成功,就设“Session["IsSubmit"]”为false

     Session["IsSubmit"] = false;

     //显示提交成功信息

     ShowMsg.Text = " * 提交成功!";

   }

   else

     //否则的话(没有提交,或者是页面刷新),不显示任何信息

     ShowMsg.Text = "";

}

//提交按钮(btnOK)单击事件

protected void btnOK_Click(object sender, EventArgs e)

{

   if (txtTitle.Text.ToString().Trim() == "")

     //ShowMsg是用来显示提示信息的

     ShowMsg.Text = " * 标题不能为空!";

   else if (txtText.Text.ToString().Trim() == "")

     ShowMsg.Text = " * 内容不能为空!";

   else

   {

     //这里是将数据提交到数据库中,省略

    

     //提交成功后,设“Session["IsSubmit"]”为true

     Session["IsSubmit"] = true;

     //强制转换页面(不可少,否则刷新仍会重复提交,仍转到本页),

     通过页面的转换将缓存中的提交的数据都释放了,即提交的标单数据不会被保存到缓存里,

     如果后退的话,将会出现该页无法显示

     Response.Redirect("post.aspx");

   }

}

 

分类:

技术点:

相关文章: