ASP.NET跳转页面时Page_Load事件重复执行两次问题排查
问题原因
- Office客户端(Word/Excel等)点击内嵌链接存在特殊的请求逻辑:点击链接后Word不会直接唤起浏览器发起访问,会先由自身进程向目标地址发送一个HEAD探测请求,校验链接是否可访问、资源类型是否合法,校验通过后才会唤起浏览器发送正式的GET请求。调试时看到的第一次内容页Page_Load执行,就是这个HEAD探测请求触发的,这也是Page_Load会重复执行的核心原因。
Response.Redirect方法参数使用错误:当前代码调用的重载传入了第二个参数false,该参数控制跳转后是否终止当前请求执行,传入false时ASP.NET不会中断当前请求流,会继续执行后续的母版页Page_Load、页面其他生命周期事件、甚至页面渲染逻辑,很容易出现响应头冲突、逻辑重复执行的异常。
修复方案
- 过滤非GET的探测请求
在Page_Load逻辑最开始增加请求方法判断,拦截Word发出的HEAD探测请求,避免这类请求触发数据库查询和跳转逻辑:protected void Page_Load(object sender, EventArgs e) { // 拦截非GET请求,返回200状态通过Office的链接有效性校验 if (!Request.HttpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase)) { Response.SuppressContent = true; Response.StatusCode = 200; return; } if (!IsPostBack) { // GET THE ID OF THE OFFER string id = Request.QueryString["Offerid"]; // GET THE LINK AND THE LINK COUNT if (id != null) { string linkName = ""; string cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString; using (SqlConnection con = new SqlConnection(cs)) { SqlCommand cmd = new SqlCommand("SpOfferbyId", con); cmd.CommandType = CommandType.StoredProcedure; SqlParameter paramid = new SqlParameter("@ID", Convert.ToInt32(id)); cmd.Parameters.Add(paramid); con.Open(); SqlDataReader rdr = cmd.ExecuteReader(); while (rdr.Read()) { linkName = rdr["Link"].ToString(); } // 增加空链接校验,避免跳转空地址报错 if (string.IsNullOrWhiteSpace(linkName)) { Response.Write("当前跳转链接无效"); Response.End(); return; } // 修改Redirect第二个参数为true,跳转后立刻终止请求 Response.Redirect(linkName, true); } }//end if } } - 修正Redirect参数
将原有代码里的Response.Redirect(linkName,false)修改为Response.Redirect(linkName, true),确保设置跳转响应头后立刻终止当前请求执行,不再运行后续页面生命周期逻辑,避免响应冲突。 - 增加边界校验
补充数据库读取结果的空值判断,如果查询不到对应的跳转链接,返回友好提示而不是直接执行空地址跳转,避免触发异常。
内容的提问来源于stack exchange,提问作者SABRY MOURICE
相关产品推荐
相关产品推荐

