尝试解决错误:在发送HTTP标头后,服务器无法设置内容类型

时间:2016-04-20 15:58:57

标签: c# asp.net webforms

我知道这个问题已被多次询问过,我已经仔细研究了这些答案,以找到解决我的代码所发生情况的潜在解决方案无济于事。所以这里。

我有一个包含更新面板的页面。在此更新面板上,我有一个生成Telerik pdf报告并下载它的按钮。但是,单击按钮时出现臭名昭着的错误:服务器无法在发送HTTP标头后设置内容类型。

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

    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.
}

令人困惑的部分是我在其他项目中运行完全相同的代码,它绝对没有任何问题。所以,如果有人能指出我做错了什么,我会非常感激。

1 个答案:

答案 0 :(得分:1)

好的,这个问题让我感到很长时间,直到我偶然发现了一个解决方案。

对于任何遇到类似问题的人来说,最终对我有用。

我从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()方法修复了此问题。