asp.net防止刷新重复提交数据解决方法的分析

在Asp.net开发中,浏览器刷新重复触发事件,导致重复提交的问题,下面有几种解决方法,我针对适用情况和利弊做一个简单的分析。

方法一:检测数据表,看是否有相同的数据。这种方法对插入数据可能意义更大些,不过如何定义是相同的数据,是个麻烦的事。同时,如果不是插入数据,是删除呢,就不适用了。

方法二:提交后,转向一个过渡页面,然后再从过渡页面返回到当前的页面。这就要求在提交后,要把当前页面的URL地址作为参数传过去,同时不能保存缓存,否则“后退”带来不良后果。不过,如果是简单的删除,似乎转来转去太麻烦了。

方法三:用JavaScript捕捉F5事件。比如有如下代码:

 代码如下 复制代码

window.document.onkeydown = KeyStroke;
function KeyStroke()
  {
   var key = event.keyCode;
   event.srcElement.releaseCapture();
   if(key == 116)
   {
   event.keyCode=0;
   event.returnValue=false;
   }
  }

似乎不错,禁用了F5,不过如果浏览器禁用了js咋办,如果用右键来刷新咋办?禁用右键么?不能为了实现一个功能来禁用这禁用那的,不合情理。

方法四:基于session和ViewState来处理。最好的例子见:

这个方法的原理是”在页面代码执行的末尾将当前的ViewState写到一个Session中,而在页面加载时则判断该Session值是否与当前ViewState相等(其实Session值恰好是ViewState的前一状态),若不等,则是正常的postback,若是相等则是浏览器刷新”.这个方法还不错,不过对session占用如此多的服务器资源,我有些担心。

代码如下

SubmitOncePage

    SubmitOncePage是针对上述分析写的一个继承自System.Web.UI.Page的基类,需要防止刷新重复提交数据的页面从该基类继承,源码如下:

 

 代码如下 复制代码

namespace myControl
{
    /**//// <summary>
    /// 名称:SubmitOncePage
    /// 父类:System.Web.UI.Page
    /// 描述:解决浏览器刷新造成的数据重复提交问题的page扩展类。
    /// 示例:    if (!this.IsRefreshed)
    ///            {
    ///                //具体代码
    ///            }
    ///    原创:丛兴滋(cncxz)    E-mail:cncxz@126.com
    /// </summary>
    public class SubmitOncePage:System.Web.UI.Page
        {
            private string _strSessionKey;
            private string _hiddenfieldName;
            private string _strLastViewstate;
          
            public SubmitOncePage()
            {
                _hiddenfieldName = "__LastVIEWSTATE_SessionKey";
                _strSessionKey = System.Guid.NewGuid().ToString();
                _strLastViewstate = string.Empty;
            }

            public bool IsRefreshed
            {
                get
                {
                    string str1 = GetSessinContent();
                    _strLastViewstate = str1;
                    string str2 = this.Session[GetSessinKey()] as string;
                    bool flag1 = (str1 != null) && (str2 != null) && (str1 == str2);
                    return flag1;
                }
            }

            protected override void Render(System.Web.UI.HtmlTextWriter writer)
            {
                string str = GetSessinKey();
                this.Session[str] = _strLastViewstate;
                this.RegisterHiddenField(_hiddenfieldName, str);
                base.Render(writer);
            }

            private string GetSessinKey()
            {
                string str = this.Request.Form[_hiddenfieldName];
                return (str == null) ? _strSessionKey : str;
            }

            private string GetSessinContent() {
                string str = this.Request.Form["__VIEWSTATE"];
                if (str == null) {
                    return null;
                }
                return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5");
            }
          
        }
}

测试项目

    首先将SubmitOncePage类的源码编译成一个单独的dll,然后进行测试,步骤如下:

    1、新建一个asp.net web应用程序;
    2、添加SubmitOncePage类对应的dll引用;
    3、给webform1添加一个Label控件(Label1)和一个Button控件(Button1);
    4、设置Label1的Text为0;
    5、双击Button1转到codebehind视图;
    6、修改类WebForm1的父类为SubmitOncePage并添加测试代码,结果如下:

 代码如下 复制代码

public class WebForm1 : myControl.SubmitOncePage
    {
        protected System.Web.UI.WebControls.Label Label1;
        protected System.Web.UI.WebControls.Button Button1;   
       

        Web 窗体设计器生成的代码#region Web 窗体设计器生成的代码
        override protected void OnInit(EventArgs e)
        {
            //
            // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
            //
            InitializeComponent();
            base.OnInit(e);
        }
       
        /**//// <summary>
        /// 设计器支持所需的方法 - 不要使用代码编辑器修改
        /// 此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {   
            this.Button1.Click += new System.EventHandler(this.Button1_Click);
        }
        #endregion

        private void Button1_Click(object sender, System.EventArgs e)
        {
            int i=int.Parse(Label1.Text)+1;
            Label1.Text = i.ToString();
            if (!this.IsRefreshed)
            {
                WriteFile("a.txt", i.ToString());
            }
            WriteFile("b.txt", i.ToString()); 
       
           
        }

        private void WriteFile(string strFileName,string strContent)
        {
            string str = this.Server.MapPath(strFileName);      
            System.IO.StreamWriter sw = System.IO.File.AppendText(str);
            sw.WriteLine(strContent);
            sw.Flush();
            sw.Close(); 
        }
    }

    7、按F5运行,在浏览器窗口中连续点击几次Button1,然后刷新几次页面,再点击几次Button1;
    8、转到测试项目对应目录下,打开a.txt和b.txt文件,可看到if (!this.IsRefreshed) 的具体效果

方法五:用ajax提交操作。当然,这是从源头上就没有刷新的问题,因为postback都没有了,不存在防止刷新提交问题。有些偏题。

方法六:通过 HttpContext 对象传递给页面处理。这个方法是msdn给的一个方法,原理我就不赘述了,详见http://msdn.microsoft.com/zh-cn/library/ms379557(VS.80).aspx。我觉得这个方法不错,根据asp.net的运行机制来处理此问题,就比较游刃有余了。所以这个方法我推荐使用,虽然是msdn的这篇文章是2004年的老文了,现在看来依然很不错。

时间: 2024-04-20 04:28:43

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类.感觉他这个方法比较独特,有例子

JSP防止网页刷新重复提交数据的几种方法_javascript技巧

本篇文章主要介绍了网页如何防止刷新重复提交与如何防止后退的解决方法,具体如下: 提交后禁用提交按钮(大部分人都是这样做的) 如果客户提交后,按F5刷新怎么办? 使用Session 在提交的页面也就是数据库处理之前: if session("ok")=true then response.write "错误,正在提交" response.end end if 数据处理完后,修改session("ok")=false. 数据处理成功马上Redirec

asp防止重复提交数据实现方法

 代码如下 复制代码 session("time")=now() const a=#0:0:4# '定义相隔之间的秒数 if session("time2") >0 then '如果有值 if session("time2")+a > session("time") then ' session("time2")=now() response.redirect "look.asp&qu

ASP模拟POST请求异步提交数据的方法_应用技巧

有时需要获取远程网站的某些信息,而服务器又限制了GET方式,只能通过POST数据提交,这个时候我们可以通过asp来实现模拟提交post数据,网上有挺多这样的例子的.下面的是我自己写的比较简洁易懂的函数. 首先,需要一个编码设置的函数,因为asp一般为gbk的,而标准的网站现在大都使用utf-8的.所以需要转换. 复制代码 代码如下: function BytesToBstr(body,Cset) dim objstream set objstream = Server.CreateObject(

ASP模拟POST请求异步提交数据的方法

有时需要获取远程网站的某些信息,而服务器又限制了GET方式,只能通过POST数据提交,这个时候我们可以通过asp来实现模拟提交post数据,网上有挺多这样的例子的.下面的是我自己写的比较简洁易懂的函数. 首先,需要一个编码设置的函数,因为asp一般为gbk的,而标准的网站现在大都使用utf-8的.所以需要转换. 复制代码 代码如下: function BytesToBstr(body,Cset) dim objstream set objstream = Server.CreateObject(

ASP.NET防止页面刷新的两种解决方法

 本篇文章主要是对ASP.NET防止页面刷新的两种解决方法进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助 方法有二,总结如下:    第一方法:  直接在CS代码里敲:  Response.Buffer = true;  Response.ExpiresAbsolute = DateTime.Now.AddSeconds(-1);  Response.Expires = 0;  Response.CacheControl = "no-cache";    当有人想按

ASP.NET防止页面刷新的两种解决方法小结_实用技巧

方法有二,总结如下: 第一方法: 直接在CS代码里敲: Response.Buffer = true; Response.ExpiresAbsolute = DateTime.Now.AddSeconds(-1); Response.Expires = 0; Response.CacheControl = "no-cache"; 当有人想按后退时页面已过期,效果就达到了 第二方法: SubmitOncePage:解决刷新页面造成的数据重复提交问题(网上资料) 执行过postback操作

防止用户将表单重复提交四种方法(实例教程)

表单重复提交是在多用户Web应用中最常见.带来很多麻烦的一个问题.有很多的应用场景都会遇到重复提交问题,比如: 点击提交按钮两次. 点击刷新按钮. 使用浏览器后退按钮重复之前的操作,导致重复提交表单. 使用浏览器历史记录重复提交表单. 浏览器重复的HTTP请求. 禁掉提交按钮. 表单提交后使用Javascript使提交按钮disable.这种方法防止心急的用户多次点击按钮.但有个问题,如果客户端把Javascript给禁止掉,这种方法就无效了. 例  代码如下 复制代码 <script type

php模拟post提交数据的方法

 这篇文章主要介绍了php模拟post提交数据的方法,实例分析了socket方法模拟post提交数据的技巧,具有一定参考借鉴价值,需要的朋友可以参考下     本文实例讲述了php模拟post提交数据的方法.分享给大家供大家参考.具体如下: php模拟post提交数据,用处很多,可用来网站的采集,登陆等等 这里以我项目中的论坛登录为例加以说明: 代码如下: function A_bbslogin($user_login,$password,$host,$port="80"){ //需要