You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Asp.Net中避免点击按钮后页面刷新重复执行操作的方案

问题分析与解决方案

咱们先拆解你遇到的两个核心问题:

  1. 静态变量rowNum的致命问题:你用了static int rowNum,静态变量是应用程序级别的,所有访问这个页面的用户会共享它的值——不仅刷新页面会导致它持续自增,其他用户点击"Add More"也会干扰到当前用户的行数,这完全不符合单用户页面状态的需求。
  2. 页面刷新重复提交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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:08:41