ASP.NET如何防止页面重复提交


1.System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("if (typeof(Page_ClientValidate) == 'function') { if (Page_ClientValidate() == false) { return false; }}");//保证验证函数的执行
sb.Append("if(window.confirm('提醒:您确定要进行此次操作吗?')==false) return false;");//自定义客户端脚本
sb.Append("disableOtherSubmit();");// disable所有submit按钮
sb.Append(ClientScript.GetPostBackEventReference(this.btnSubmit,null));//用__doPostBack来提交,保证按钮的服务器端click事件执行
sb.Append(";");
btnSubmit.Attributes.Add("onclick", sb.ToString());

2.

捕获回车事件时,表单重复提交问 ...

今天在页面中捕获回车事件,发现提交表单时,会重复提交,最后在方法后面加一个return false,问题才得以解决。 document.onkeydown=function() {//捕捉回车 if (event.keyCode==13) { checkFormValidate(); return false; } }  

4。同事写的,收录一下,方法如下:

    /// <summary>
    /// 防止重复提交
    /// </summary>
    /// <param name="imaButtons">按键集合</param>
    /// <param name="clientID">页面有JS验证的组件</param>
    public void RepeatSubmitCheckForRC( List<ImageButton> imaButtons)
    {
        foreach (ImageButton button in imaButtons)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("if (typeof(Page_ClientValidate) == 'function') { if (Page_ClientValidate() == false) { return false; }};");
            if (button.ID != "saveButton")
            {
                sb.Append("if(!contentRequiredValidator()){return false};");//富文本编辑为空验证
            }
            sb.Append("this.disabled  = true;");
            sb.Append(this.Page.ClientScript.GetPostBackEventReference(button, ""));
            sb.Append(";");
            button.Attributes.Add("onclick", sb.ToString());
        }
    }

调用方法的时候

        List<ImageButton> imaButtons = new List<ImageButton>();
        imaButtons.Add(sumbitButton);
        imaButtons.Add(saveButton);
        RepeatSubmitCheckForRC(imaButtons);

5.

转: http://www.cnblogs.com/freshman0216/archive/2008/09/11/1288745.html

ASP.NET项目中经常会遇到这样的情况:页面提交后需要很长的处理时间,用户耐心受到挑战就开始摧残页面上的提交按钮,造成了该页面重复提交多次,带来意想不到的问题。

       在项目实践中,采用了一种比较简单的方式解决这种问题:用户点击提交按钮后,通过JavaScript脚本将提交按钮disable掉,同时显示动画提示用户系统正在处理,并触发服务器端事件。具体是通过在Page_Load事件中添加如下代码实现的:

        //sb保存的是JavaScript脚本代码,点击提交按钮时执行该脚本
        StringBuilder sb = new StringBuilder();
        
//保证验证函数的执行 

        sb.Append("if (typeof(Page_ClientValidate) == 'function') { if (Page_ClientValidate() == false) { return false; }};");
        
//点击提交按钮后设置Button的disable属性防止用户再次点击,注意这里的this是JavaScript代码

        sb.Append("this.disabled  = true;");
        
//用__doPostBack来提交,保证按钮的服务器端click事件执行 

        sb.Append(this.ClientScript.GetPostBackEventReference(this.btnSubmit, "")); 
        sb.Append(
";"
);
        
//
SetUIStyle()是JavaScript函数,点击提交按钮后执行,如可以显示动画效果提示后台处理进度
        
//注意SetUIStyle()定义在aspx页面中

        sb.Append("SetUIStyle();");
        
//给提交按钮增加OnClick属性

        this.btnSubmit.Attributes.Add("onclick", sb.ToString());


       代码中添加了比较详细的注释,具体就不多解释了。 但实际上这是一种治标不治本的方法,这种方法是不能防止用户按F5刷新的,但用在因为后台的耗时操作叫用户不耐烦引起的重复提交场景上应该是没什么问题的。

       关于如何防止F5重复刷新可以参考MSDN知识库中的文章基于功能更丰富的基础类构建您自己的 ASP.NET 页面。另外,CodeProject上有人写了防重复提交的扩展的Button控件PleaseWaitButton


3.解决刷新页面造成数据重复提交的方法(转载)

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,


posted on 2009-12-24 09:54  风雨者2  阅读(11805)  评论(2编辑  收藏  举报

导航