ASP.NET关闭子窗口刷新父页重复触发按钮点击事件如何解决
问题根因
该问题是ASP.NET Web Forms的表单回发重复提交特性导致的:
- 点击btnsearch按钮时页面触发POST回发,服务端执行
btnsearch_Click事件注册弹窗脚本,页面返回后脚本执行弹出子窗口 - 调用
window.opener.location.reload()刷新父页面时,浏览器会重复提交上次的POST回发请求,相当于再次触发btnsearch按钮点击事件,服务端又会注册弹窗脚本,最终形成死循环。
解决方案(按修改成本从低到高排序)
方案1:修改父页面刷新逻辑(仅改1行代码,成本最低)
把子窗口的refreshAndClose方法里的reload()改为直接赋值location.href,会以GET请求刷新父页面,不会重复提交之前的POST回发数据:
function refreshAndClose() { // 替换原有reload(),GET方式刷新不会重复提交表单 window.opener.location.href = window.opener.location.href; self.close(); }
注:该方案刷新后会清空父页面已填写的表单内容,如果需要保留表单值请选用方案2。
方案2:弹窗逻辑移到前端,避免回发(推荐)
弹窗属于纯前端交互,不需要走服务端回发,直接给按钮添加客户端点击事件即可:
- 给btnsearch按钮添加
OnClientClick属性,阻止默认回发:
<asp:Button ID="btnsearch" runat="server" Text="搜索" OnClientClick="open_GG9080(); return false;" />
- 删除
btnsearch_Click事件中注册弹窗脚本的代码即可,按钮点击不会触发整页回发,自然不会出现重复弹窗问题。
若点击按钮需要先执行服务端逻辑再弹窗,可以用AJAX调用服务端接口,执行完成后再触发弹窗,全程无需整页回发。
方案3:用Post/Redirect/Get模式解决回发重复提交
如果必须在服务端回发后弹窗,可以用PRG模式从根源避免重复提交:
- 在
btnsearch_Click执行完业务逻辑后,重定向到当前页并携带弹窗标记参数:
// 将需要传递的参数拼到重定向地址中 Response.Redirect($"当前页.aspx?openPopup=1&name={shareName}&No=1");
- 在父页面
Page_Load中判断弹窗标记,仅在首次GET请求时注册弹窗脚本:
protected void Page_Load(object sender, EventArgs e) { if(!IsPostBack && Request.QueryString["openPopup"] == "1") { string sclientScript = "open_GG9080('?name=" + Request.QueryString["name"] + "&No=1')"; ClientScript.RegisterStartupScript(this.GetType(), "event", "<script type='text/javascript'>" + sclientScript + "</script>"); } }
重定向后页面为GET请求,刷新时不会重复提交表单,也不会重复触发弹窗。
额外优化提示
你当前定义的open_GG9080是无参函数,但调用时传入了查询参数,如果需要用到传递的name、No参数,可以修改函数定义接收参数拼到弹窗地址:
function open_GG9080(query) { window.open("Page2.aspx" + query, "Shan", "width=200,height=200,scrollbars=no"); }
内容的提问来源于stack exchange,提问作者Chi Pham
相关产品推荐
相关产品推荐

