VS2010中UpdatePanel内GridView的LinkButton下载触发解析异常
这个错误是ASP.NET UpdatePanel异步回发机制和文件下载操作的典型冲突,我来帮你拆解原因并给出可行的修复方案:
错误原因解析
UpdatePanel的异步回发(AJAX)要求服务器返回符合ASP.NET AJAX格式的JSON响应,用来局部更新页面内容。但你的下载代码直接向Response写入了文件的二进制数据,并且通过Response.End()强制终止了响应——这导致服务器返回的内容完全不符合PageRequestManager的解析规则,因此抛出了Sys.WebForms.PageRequestManagerParserErrorException。
核心矛盾:文件下载操作不能在异步回发中执行,必须让触发下载的LinkButton触发全页回发。但因为LinkButton是GridView动态生成的,没法直接在UpdatePanel的Triggers里静态指定,所以需要用以下方法处理:
解决方案1:在RowCreated事件中注册回发控件
在GridView的RowCreated事件里,把每行的LinkButton注册为全页回发控件,绕过UpdatePanel的异步处理:
后台代码修改
protected void gvLogFilesDownload_RowCreated(object sender, GridViewRowEventArgs e) { // 只处理数据行 if (e.Row.RowType == DataControlRowType.DataRow) { LinkButton downloadBtn = e.Row.FindControl("lnkLogFiles") as LinkButton; if (downloadBtn != null) { // 告诉ScriptManager这个按钮要触发全页回发 ScriptManager.GetCurrent(Page).RegisterPostBackControl(downloadBtn); } } }
页面配置调整
不需要在UpdatePanel的Triggers里添加任何配置(可以清空现有的Triggers代码),这样点击LinkButton时就会触发全页回发,下载代码就能正常执行,不会干扰UpdatePanel的异步响应解析。
解决方案2:修改LinkButton的提交行为
另一种方法是给LinkButton禁用默认的提交行为,确保它触发全页回发:
页面代码修改
在GridView的ItemTemplate里更新LinkButton属性:
<asp:LinkButton ID="lnkLogFiles" runat="server" Text='<%#Eval("Log Files") %>' Font-Underline="true" CommandName="Download" CommandArgument="<%#((GridViewRow)Container).RowIndex %>" OnClick="lnkLogFiles_Click" UseSubmitBehavior="false"/>
然后同样在RowCreated事件中执行方案1的注册代码,本质和方案1一致,都是让按钮绕过UpdatePanel的异步机制。
额外优化建议
- 动态设置ContentType:你的代码里固定用了
APPLICATION/pdf,如果需要支持其他文件类型,可以根据文件扩展名自动获取MIME类型:
string contentType = System.Web.MimeMapping.GetMimeMapping(sPath); Response.ContentType = contentType;
- 避免Response.End()的潜在问题:
Response.End()会抛出ThreadAbortException,虽然不影响功能,但可以用更优雅的方式终止响应:
// 替换Response.End(); HttpContext.Current.ApplicationInstance.CompleteRequest();
内容的提问来源于stack exchange,提问作者user71934

