Asp.Net防止刷新重複提交數據小記

在做項目的時候遇到這樣的問題,網上找了下,覺得還可以,分享給大家


1樓

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): 

//頁面加載 

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 

   { 

     //這裏是將數據提交到數據庫中,省略 

     /* 
string sql = "insert into tab...values(...)"; 

     MyConn.ExecQuery(sql); 

     */ 

     //提交成功後,設“Session["IsSubmit"]”爲true 

     Session["IsSubmit"] = true; 

     //強制轉換頁面(不可少,否則刷新仍會重複提交,仍轉到本頁), 

     通過頁面的轉換將緩存中的提交的數據都釋放了,即提交的標單數據不會被保存到緩存裏, 

     如果後退的話,將會出現該頁無法顯示 

     Response.Redirect("post.aspx"); 

  } 

上面這個方法非常簡單也很實用,推薦大家使用。 

下面是我自己研究出來的另一種方法,該方法不同於“不保存緩存的方法”,它是讓瀏覽器保存所有頁面

緩存的。該方法通過隨機碼的方式 來判斷是正常提交還是“刷新”或“後退”的。 

首先(提交頁面是post.aspx)在 Session 中 增加變量 Rnd 用來存放隨機碼,同時在提交表單數據

時不做處理,而是讓頁面轉到 post.aspx?r=x,這裏“x”等於Session["Rnd"],這個時候在頁面加載時,

通過判斷r的值和Session["Rnd"]的值是否相同,如果相同就處理提 交的數據,否則即可認爲是“刷新”

或者是“後退”操作了,最後再次付給Session["Rnd"]一個隨機碼。 

以下是該方法代碼(post.aspx): 

//獲取隨機碼 

public class MyRnd 

   public static string Rnd() 

   { 

     //隨機碼是由 0-9 a-z A-Z 之間的數字或字母組成的 

     //下面是生成的20位隨機碼 

     //0..9 A..Z a..z 

     //48-57 65-90 97-122 

     string rst = ""; 

     Random rr = new Random(); 

     for (int i = 0; i < 20; i++) 

     { 

       int ir = 0; 

       do 

       { 

         ir = rr.Next(123); 

         if((ir >= 48) && (ir <= 57)) break; 

         else if((ir >= 65) && (ir <= 90)) break; 

         else if ((ir >= 97) && (ir <= 122)) break; 
   } 

       while (true); 

       rst += ((char)ir).ToString(); 

       } 

     return rst; 

   } 

//頁面加載 

protected void Page_Load(object sender, EventArgs e) 

   //獲取URL中請求的“r”值,如果“r”不存在則 r="" 

   string r = ""; 

   if(Request.QueryString["r"] != null) 

     r = Request.QueryString["r"].ToString().Trim(); 

   string t; 

   //獲取 “Session” 中的 “Rnd” 值,用於和“r”比較 

   t = Session["Rnd"].ToString().Trim(); 

   //如果“r=t”則爲提交操作,即可對錶單的數據進行處理 

  if(r == t) 

  { 

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

       ShowMsg.Text = " * 標題不能爲空!"; 

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

       ShowMsg.Text = " * 內容不能爲空!"; 

     else      { 

       //這裏是將數據提交到數據庫中,省略 

       /* 

       string sql = "insert into tab...values(...)"; 

       MyConn.ExecQuery(sql); 

       */ 

       //提交成功後清空表單數據 

       txtTitle.Text = ""; 

       txtText.Text = ""; 

       //顯示提交成功信息 

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

     } 

  } 

   //否則可以認爲是“刷新”或者“後退”操作 

   else 

   { 

       txtTitle.Text = ""; 

       txtText.Text = ""; 

  } 

  //最後要重新獲得“Session["Rnd"]”的值,並將“btnOK.PostBackUrl”設爲“Session["Rnd"]”的值

 

  Session["Rnd"] = MyRnd.Rnd(); 

  btnOK.PostBackUrl ="post.aspx?r=" + Session["Rnd"].ToString().Trim(); 

//這裏提交按鈕(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
 
 
?
<SCRIPT LANGUAGE="javascript">
<!--
function input(ok)
{
var M1=ok.ReplyContent.value;
if (M1==''){
alert('回覆內容不可以爲空.');
return false;
}
ok.B1.disabled =true;
ok.B2.disabled =true;
return true;
}
//-->
</script>
<form οnsubmit="return input(this)">
<input type=text name=ReplyContent>
<input type="submit" value="發出回覆" border="0" name="B1">
<input name="B2" TYPE="reset"value="重 寫">
</form>

這樣就行了,提交後直接轉到另一頁面
 
 
 
1、讓提交後返回歷史記錄
Response.Write"<script>alert('OK!添加成功!');history.back();</script>"
2、提交後跳轉到本頁
response.redirect "index.asp"
 
 Response.Write"<script language=javascript>alert('提交成

功!');window.location.href='"&Request.ServerVariables("Http_Referer")&"';</script>"
===========================================

防止網頁後退

我們在進行數據庫添加操作的時候,如果允許後退,而正巧有刷新了頁面,就會再次執行添加操作,無疑

這不是我們需要的,像一般網上很多禁止緩存的代碼,有時並不可靠,這時你只要在操作的頁面加上<body

οnbefοreunlοad="window.location.replace('')">就可以了,在網頁的裏指定要定向的新頁,再點後退,

看是不是不會再退到剛纔的操作頁面了,實際上已經把這個歷史給刪除了
============================
Response.Buffer=true;
    Response.ExpiresAbsolute=DateTime.Now.AddSeconds(-1);
    Response.Expires=0;
    Response.CacheControl="no-cache";
==========
 

 

 

 

1。在asp.net頁面中的HTML處插入如下代碼:

    <input id="hiddenTest" type="hidden" value="<%= GetToken() %>" name="hiddenTestN"/>

2。在page_load裏寫上如下代碼:

    //*******防頁面刷新
            if (null == Session["Token"])
            {
                SetToken();
            }
            //***********

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

   public string GetToken()
        {
            if (null != Session["Token"])
            {
                return Session["Token"].ToString();
            }
            else
            {
                return string.Empty;
            }
        }

        private void SetToken()
        {
            Session.Add("Token", UserMd5(Session.SessionID + DateTime.Now.Ticks.ToString()));
        }

        protected string UserMd5(string str1)
        {
            string cl1 = str1;
            string pwd = "";
            MD5 md5 = MD5.Create();
            // 加密後是一個字節類型的數組
            byte[] s = md5.ComputeHash(Encoding.Unicode.GetBytes(cl1));
            // 通過使用循環,將字節類型的數組轉換爲字符串,此字符串是常規字符格式化所得
            for (int i = 0; i < s.Length; i++)
            {
                // 將得到的字符串使用十六進制類型格式。格式後的字符是小寫的字母,如果使用大寫

(X)則格式後的字符是大寫字符
                pwd = pwd + s[i].ToString("X");
            }
            return pwd;
        }

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

     //*******防頁面刷新
                if (!Request.Form.Get("hiddenTestN").Equals(GetToken()))
                {
                    return;
                }
                SetToken();
                //***********
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章