Trying to solve error: Server cannot set content type after HTTP headers have been sent

Trying to solve error: Server cannot set content type after HTTP headers have been sent

我知道这个问题已经被问过很多次了,我已经搜索了这些答案以寻找解决我的代码所发生问题的潜在解决方案,但无济于事。就这样吧。

我有一个带有更新面板的页面。在这个更新面板上,我有一个按钮可以生成 Telerik pdf 报告并下载它。但是,当单击该按钮时,出现臭名昭著的错误:发送 HTTP headers 后服务器无法设置内容类型。

这是我的代码(为便于发布此问题而进行了简化:

    protected void Page_Load(object sender, EventArgs e)
{ 
    ScriptManager.GetCurrent(this).RegisterPostBackControl(btnPayrollDetails);
}

    protected void btnPayrollDetails_Click(object sender, EventArgs e)
{
    PayPeriod pay = GetPeriod();
    if (pay == null || (pay.Expenses.Count == 0 && pay.Invoices.Count == 0))
    {
        return;
    }
    var file = "test";
    var report = new Core.Reports.PayrollDetails(Global.Account.Member.ID, pay, mypMonth.SelectedDate.Value);
    Telerik.Reporting.Processing.RenderingResult result = new Telerik.Reporting.Processing.ReportProcessor().RenderReport("PDF", report, null);
    this.Response.DownloadFile(result.DocumentBytes, file + ".pdf");
}

对this.Response.DownloadFile的调用在这里调用了一个扩展方法:

public static void DownloadFile(this HttpResponse Response, byte[] fileBytes, string fileName, string mime = "application/pdf")
{
    Response.Clear();
    Response.BufferOutput = true;
    Response.ContentType = mime;
    Response.AddHeader("content-disposition", "attachment; filename=\"" + fileName + "\"");
    using (MemoryStream ms = new MemoryStream(fileBytes)) { ms.WriteTo(Response.OutputStream); }
    HttpContext.Current.Response.Flush(); // Sends all currently buffered output to the client.
    HttpContext.Current.Response.SuppressContent = true;  // Gets or sets a value indicating whether to send HTTP content to the client.
    HttpContext.Current.ApplicationInstance.CompleteRequest(); // Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event.
}

令人困惑的是,我在其他项目中使用了完全相同的代码 运行,而且它完全可以正常工作,没有任何问题。所以,如果有人能指出我做错了什么,我将不胜感激。

好吧,这个问题困扰了我很长时间,直到我偶然发现了解决方案。

对于遇到与此类似问题的任何人,这里是最终对我有用的方法。

我从 Page_Load() 事件中删除了 ScriptManager.GetCurrent(this).RegisterPostBackControl(btnPayrollDetails); 并将其添加到 button_Init 事件中:

<asp:Button ID="btnPayrollDetails" runat="server" Text="Payroll Details" OnClick="btnPayrollDetails_Click" OnInit="btnPayrollDetails_Init" />

protected void btnPayrollDetails_Init(object sender, EventArgs e)
{
     ScriptManager.GetCurrent(this).RegisterPostBackControl(btnPayrollDetails);
}

出于某种原因,按钮没有注册到脚本管理器并将其从 PageLoad() 移至按钮 Init() 方法解决了这个问题。