Asp.Net中避免点击按钮后页面刷新重复执行操作的方案
问题分析与解决方案
咱们先拆解你遇到的两个核心问题:
- 静态变量
rowNum的致命问题:你用了static int rowNum,静态变量是应用程序级别的,所有访问这个页面的用户会共享它的值——不仅刷新页面会导致它持续自增,其他用户点击"Add More"也会干扰到当前用户的行数,这完全不符合单用户页面状态的需求。 - 页面刷新重复提交Post请求:当你点击"Add More"时,浏览器会发送一个Post请求到服务器,刷新页面时浏览器会重新发送这个请求,导致
btnAdd_Click被再次执行,重复添加行。
下面是具体的修复方案,分步骤来:
步骤1:替换静态变量,用ViewState存储行数
把静态的rowNum改成用ViewState保存,ViewState是和当前页面实例绑定的,每个用户的页面有独立的状态,不会互相干扰,而且PostBack时会自动保留状态。
修改代码:
// 删掉原来的 static int rowNum; // 改用ViewState封装的属性 private int RowNum { get { // 如果ViewState里没有值,默认初始为1 return ViewState["RowNum"] != null ? (int)ViewState["RowNum"] : 1; } set { ViewState["RowNum"] = value; } }
步骤2:添加防重复提交Token,阻止刷新时重复执行Add操作
我们给页面生成一个唯一的Token,每次点击"Add More"时验证Token,执行操作后更新Token——这样刷新页面时,浏览器发送的旧Token会和服务器端的新Token不匹配,就不会重复执行添加逻辑。
第一步:在ASPX页面添加一个隐藏字段
<asp:HiddenField ID="hdnAntiForgeryToken" runat="server" />
第二步:添加Token生成与验证方法
在后台代码里添加这两个方法:
// 生成唯一的防重复提交Token private void GenerateAntiForgeryToken() { string uniqueToken = Guid.NewGuid().ToString(); ViewState["AntiForgeryToken"] = uniqueToken; hdnAntiForgeryToken.Value = uniqueToken; } // 验证Token是否有效 private bool IsValidAntiForgeryToken() { string serverToken = ViewState["AntiForgeryToken"] as string; string clientToken = hdnAntiForgeryToken.Value; return !string.IsNullOrEmpty(serverToken) && !string.IsNullOrEmpty(clientToken) && serverToken.Equals(clientToken); }
第三步:在Page_Load初始化Token
在Page_Load的!IsPostBack分支里添加Token初始化:
if (!IsPostBack) { RowNum = 1; // 替换原来的 rowNum = 1; // 原来的其他初始化代码... // 新增:初始化防重复Token GenerateAntiForgeryToken(); }
第四步:修改btnAdd_Click方法,加入Token验证
protected void btnAdd_Click(object sender, EventArgs e) { // 先验证防重复Token,无效直接返回 if (!IsValidAntiForgeryToken()) { return; } if (RowNum != 8) { RowNum++; // 这里可以优化你的代码:把多个addNewRowX方法整合成一个方法,比如AddNewRow(RowNum) if (RowNum == 2) addNewRow2(); else if (RowNum == 3) addNewRow3(); else if (RowNum == 4) addNewRow4(); else if (RowNum == 5) addNewRow5(); else if (RowNum == 6) addNewRow6(); else if (RowNum == 7) addNewRow7(); else if (RowNum == 8) addNewRow8(); // 执行完操作后,更新Token,防止再次重复提交 GenerateAntiForgeryToken(); } else { lblError.Text = "You Can Add Max 5 Post Graduation Information."; lblError.ForeColor = Color.Red; divMessageFailed.Visible = true; divMessageSuccess.Visible = false; } }
额外优化建议
你的addNewRow2()到addNewRow8()方法逻辑应该很相似,可以把它们整合成一个通用方法,比如:
private void AddNewRow(int rowNumber) { // 根据rowNumber动态生成对应的行控件 // 比如复制模板行、设置控件ID等 // 替换原来的多个addNewRowX方法,减少冗余代码 }
这样btnAdd_Click里的代码就可以简化成:
RowNum++; AddNewRow(RowNum);
为什么这个方案可行?
- ViewState存储行数:保证每个用户的页面有独立的行数状态,不会和其他用户互相干扰,页面重新Get请求(比如刷新后重新进入)时会重置为1,符合你"刷新后还能继续点击Add More"的需求。
- 防重复Token:阻止了刷新页面时重复提交Post请求导致的重复添加操作,同时不影响用户正常点击"Add More"的功能。
内容的提问来源于stack exchange,提问作者Mahiuddin Al Kamal
相关产品推荐
相关产品推荐

