首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > asp.net >

ASP.NET如何防止重复提交!

2012-03-06 
ASP.NET怎么防止重复提交!!如何防止用户连续点击多下BUTTON后将数据插入到数据库中[解决办法]C# codepubli

ASP.NET怎么防止重复提交!!
如何防止用户连续点击多下BUTTON后将数据插入到数据库中

[解决办法]

C# code
public class RefreshServe : System.Web.UI.Page    {        private static ILog log = LogManager.GetLogger(typeof(RefreshServe));        private readonly string REFRESH_TICKET_NAME = "__RefreshTicketArray";        private readonly string HIDDEN_FIELD_NAME = "__RefreshHiddenField";        private readonly string HIDDEN_PAGE_GUID = "__RefreshPageGuid";        /// <summary>        /// 为True表示页面刷新,False为正常提交        /// </summary>        public bool IsPageRefreshed        {            get            {                if (IsPostBack && !CheckRefreshFlag())                {                    log.Debug("刷新了页面");                    return true;                }                else                {                    log.Debug("正常提交");                    return false;                }            }        }        /// <summary>        /// 呈现前更新标识        /// </summary>        /// <param name="e"></param>        protected override void OnPreRender(EventArgs e)        {            log.Debug("执行OnPreRender");            base.OnPreRender(e);            UpdateRefreshFlag();        }        /// <summary>        /// 更新标识,正常提交都删除该次提交的时间,并生产当前新的时间        /// </summary>        private void UpdateRefreshFlag()        {            #region Cookie模式            //注册页面唯一标识并返回            string pageGuid = SetCurPageGuid();            HttpCookie cookie = GetRefreshTicket();                       if (cookie.Values.Count > 0)            {                cookie.Values.Remove(pageGuid);                log.Debug("当前清除的cookie变是:" + pageGuid);            }            string submitTime = DateTime.Now.ToString("hhmmss.fffff");            //当前提交时间保存到隐藏域            ClientScript.RegisterHiddenField(HIDDEN_FIELD_NAME, submitTime);            log.Debug("即将要新增的时间:submitTime:" + submitTime + "  Guid:" + pageGuid.ToString());            cookie.Values.Add(pageGuid, submitTime);            log.Debug("UpdateRefreshFlag中当前Cookie中存在的记录数为:" + cookie.Values.Count);            for (int i = 0; i < cookie.Values.Count; i++)                log.Info("cookie[" + cookie.Values.GetKey(i) + "]:" + cookie.Values[i]);            Response.AppendCookie(cookie);            #endregion        }        /// <summary>        /// 验证是否刷新        /// </summary>        /// <returns></returns>        private bool CheckRefreshFlag()        {            HttpCookie cookie = GetRefreshTicket();            string pageGuid = GetCurPageGuid();            if (cookie.Values.Count > 0)            {                bool flag;                if (cookie.Values[pageGuid] != null)                    flag = cookie.Values[pageGuid].IndexOf(GetCurSubmitTime()) > -1;                else                    flag = true;//防止出现异常,总是可以提交                if (flag)                    log.Debug("提交时间存在,可以提交");                else                    log.Debug("无效的提交时间");                return flag;            }            return true;        }        /// <summary>        /// 得到已保存的提交时间,没有新建,有返回        /// </summary>        /// <returns></returns>        private HttpCookie GetRefreshTicket()        {                        #region Cookie模式,返回值为Cookie            HttpCookie cookie;            if (Request.Cookies[REFRESH_TICKET_NAME] == null)            {                cookie = new HttpCookie(REFRESH_TICKET_NAME);                Response.AppendCookie(cookie);                log.Debug("Cookie不存在,初始化");            }            else            {                cookie = Request.Cookies[REFRESH_TICKET_NAME];                log.Debug("读取已存在的Cookie,当前Cookie中存在的记录数为:" + cookie.Values.Count + "具体有如下几条:");                for (int i = 0; i < cookie.Values.Count; i++)                    log.Info("cookie[" + cookie.Values.GetKey(i) + "]:" + cookie.Values[i]);            }            return cookie;            #endregion        }        /// <summary>        /// 获取当前提交时间        /// </summary>        /// <returns></returns>        private string GetCurSubmitTime()        {            string submitTime = Request.Params[HIDDEN_FIELD_NAME] == null ? "" : Request.Params[HIDDEN_FIELD_NAME].ToString();            log.Debug("执行GetCurSubmitTime:submitTime为:" + submitTime);            return submitTime;        }        /// <summary>        /// 设置页面唯一标识,通过Guid标识来区分每个页面自己的提交时间        /// </summary>        private string SetCurPageGuid()        {            string guid;            if (!IsPostBack)            {                if (Request.Params[HIDDEN_PAGE_GUID] == null)                {                    guid = System.Guid.NewGuid().ToString();                    log.Debug("SetCurPageGuid注册了一个新的标识:" + guid);                }                else                    guid = GetCurPageGuid();            }            else            {                guid = GetCurPageGuid();                           }            ClientScript.RegisterHiddenField(HIDDEN_PAGE_GUID, guid);            return guid;        }         /// <summary>        /// 得到当前页面的唯一标识        /// </summary>        /// <returns></returns>        private string GetCurPageGuid()        {            string pageGuid = Request.Params[HIDDEN_PAGE_GUID] == null ? "none" : Request.Params[HIDDEN_PAGE_GUID].ToString();            log.Debug("执行GetCurPageGuid()后Page_GUID为:" + pageGuid);            return pageGuid;        }需要刷新判断功能时新页面只需继承该类就可,通过引用属性IsPageRefreshed识别"为真表示刷新,假则是正常提交",将数据库的操作写在if(!IsPageRefreshed){   数据库操作}即可,如果是刷新不会执行,代码中注释部分使用的是Session方式保存票证,因为session比较容易丢失且占内存,所以使用cookie, 


[解决办法]
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; 
background-color:Transparent; 
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();");
}
}

}
[解决办法]
防止表单重复提交的实现方法! 
  我们做添加信息页面的时候经常会遇到这样的问题,用户有时候会重复的点击提交按钮(实际上测试人员经常这样干),会导致多次提交,产生重复数据,我们总是要写一段代码要在表单提交后把提交按钮设置disibled=true,这样的代码写了好几处。 
  
  初步想法是通过attachEvent在form的onsubmit事件中挂一个方法,每次触发该事件的时候都调用我们定义的方法,我们可以给form增加一个submited属性,每次判断这个属性,为false的时候继续提交表单并且设置form.submited=true,反之说明表单已经提交,就不再表单。

接下来,遇到了一些麻烦: 
提交表单有三种方式(我目前用过的,就这三种)
<form action=test.aspx onsubmit="return false;" name=form1>
1.<input type=submit >submit按钮
2.<input type=text>当form中只有一个文本本框按回车的时候
3.<input type=button onclick=javascript:form1.submit()>自己写脚本提交
</form>
前两种是可以触发 onsubmit事件的,但是第三种不会。

显然,仅仅捕获onsubmit事件时不行的,还必须在form的submit方法执行前,判断表单是否在提交。
看看下面的代码,我们就明白了。

//修改当前页面所有表单的提交事件
function $setFormCheckSubmited()
{
var frms=document.forms;
for(var i=0;i<document.forms.length;i++)
{
frms[i].baseSubmit = frms[i].submit;//保存表单原来的submit 方法
frms[i].submited = false;//添加一个submited属性,并且设置其为false
frms[i].submit = new Function("$submitForm(this)");//
$addElementEventHandler(frms[i],"onsubmit","$submitForm(document.forms["+i+"])");
}
}

//提交一个表单,如果当前表单已经提交,按么就不会继续提交该表单
function $submitForm(frm)
{
if (frm.submited) return false;
frm.submited=true;
frm.baseSubmit();
}
 
 
//下面是addElementEventHandler的实现
 
/*
添加一个方法到到一个对象的一个的一个事件中
element 要设置的对象
eventName 事件名称, 字符串类型的。
methodName表示函数名称,字符串类型的。
*/
function $addElementEventHandler(element,eventName,methodName)


{
if (document.all)
{
element.attachEvent(eventName,new Function(methodName));
}
else
{
if (eventName.substring(0,2)=="on") eventName=eventName.substring(2);//firefox中所有的事件名称前面是没有on的。
element.addEventListener(eventName,new Function(methodName));
}
}


[解决办法]
附上源码,自己编译成类库吧


C# code
using System;using System.Collections.Generic;using System.ComponentModel;using System.Text;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace BlogLan.Web.Controls{    /// <summary>    /// 表示一个防止重复提交的按钮。当用户单击按钮以后,该按钮变灰,不能再次单击,直到重新加载页面或者跳转。    /// </summary>    [DefaultProperty("Text")]    [ToolboxData("<{0}:ClickOnceButton runat=server></{0}:ClickOnceButton>")]    public class ClickOnceButton : System.Web.UI.WebControls.Button    {        /// <summary>        /// 默认的构造函数。        /// </summary>        public ClickOnceButton()        {            this.ViewState["afterSubmitText"] = "正在提交,请稍候...";            base.Text = "ClickOnceButton";            this.ViewState["showMessageBox"] = false;            this.ViewState["warningText"] = "确定要提交吗?";        }        /// <summary>        /// 获取或设置单击按钮后,按钮上所显示的文本。        /// </summary>        [Bindable(true),        Category("Appearance"),        DefaultValue("正在提交,请稍候..."),        Description("指示单击提交后,按钮上所显示的文本。")]        public string AfterSubmitText        {            get            {                string afterSubmitText = (string)this.ViewState["afterSubmitText"];                if (afterSubmitText != null)                {                    return afterSubmitText;                }                else                {                    return string.Empty;                }            }            set            {                this.ViewState["afterSubmitText"] = value;            }        }        [Bindable(true),        Category("Appearance"),        DefaultValue(false),        Description("指示是否要显示一个提示框。")]        public bool ShowMessageBox        {            get            {                return (bool)this.ViewState["showMessageBox"];            }            set            {                this.ViewState["showMessageBox"] = value;            }        }        [Bindable(true),        Category("Appearance"),        DefaultValue("确定要提交吗?"),        Description("指示提示框内所包含的内容。")]        public string WarningText    ;    {            get            {                return (string)this.ViewState["warningText"];            }            set            {                this.ViewState["warningText"] = value;            }        }        /// <summary>        /// AddAttributesToRender        /// </summary>        /// <param name="writer">HtmlTextWriter</param>        protected override void AddAttributesToRender(HtmlTextWriter writer)        {            System.Text.StringBuilder ClientSideEventReference = new System.Text.StringBuilder();            if (((this.Page != null) && this.CausesValidation) && (this.Page.Validators.Count > 0))            {                ClientSideEventReference.Append("if (typeof(Page_ClientValidate) == 'function'){if (Page_ClientValidate() == false){return false;}}");            }            //ShowMessageBox?            if (this.ShowMessageBox)            {                ClientSideEventReference.Append("if (!confirm('" + this.WarningText + "')){return false}");            }            ClientSideEventReference.AppendFormat("this.value = '{0}';", (string)this.ViewState["afterSubmitText"]);            ClientSideEventReference.Append("this.disabled = true;");            ClientSideEventReference.Append(this.Page.ClientScript.GetPostBackEventReference(this, string.Empty));            writer.AddAttribute(HtmlTextWriterAttribute.Onclick, ClientSideEventReference.ToString(), true);            base.AddAttributesToRender(writer);        }    }} 

热点排行
Bad Request.