发送HTTP标头后,服务器无法设置内容类型 - 在更新面板内发生错误后

时间:2015-01-22 19:15:54

标签: asp.net http-headers updatepanel

我收到以下错误:服务器无法在发送HTTP标头后设置内容类型。我在网上看了一下,包括一些SO问题,但是没有一个问题解决了我的问题。这是我的特殊情况:

我有一个更新面板内的asp.net gridview(它也恰好位于modalpopupextender中)。 gridview有一个带有图像按钮的模板字段,单击该按钮可下载PDF。一切正常,直到我遇到试图下载的错误。我处理Gridview.RowCommand事件中的错误,并且页面不会像我想要的那样在客户端上更改。 然而,如果我再次单击下载,则文件不会下载,我在ScriptManager.AsyncPostBackError事件中捕获错误“服务器无法在发送HTTP标头后设置内容类型。”提前谢谢!

这是我的代码:

- Default.aspx的 -

<asp:HiddenField ID="hdnHiddenField" runat="server" />
<cc1:ModalPopupExtender ID="hdnHiddenField_mpeModalPopup" runat="server" Enabled="True" TargetControlID="hdnHiddenField"
    CancelControlID="lnkClose" PopupControlID="pnlPanel" BackgroundCssClass="modalBackground"></cc1:ModalPopupExtender>
<asp:Panel ID="pnlPanel" runat="server" BorderStyle="Double" Width="50%" Height="75%" CssClass="modalPopup" style="overflow: auto; display: none">
    <div class="modalHeaderClose">
        <asp:LinkButton ID="lnkClose" runat="server" Text="Close [X]"></asp:LinkButton>
    </div>
    <cc1:Accordion ID="accdnPolicyInfo" runat="server" SelectedIndex="0" RequireOpenedPane="false">
        <Panes>
            <cc1:AccordionPane ID="accpnlDocuments" runat="server">
                <Header>
                    <div class="accordionHeader">Documents</div>
                </Header>
                <Content>
                    <asp:UpdatePanel ID="upDocuments" runat="server" UpdateMode="Conditional">
                        <ContentTemplate>
                            <div style="text-align: center; padding: 0 10px 10px 10px;">
                                <asp:GridView ID="gvGridView" runat="server" AutoGenerateColumns="False" Width="100%" ShowHeaderWhenEmpty="True">
                                    <Columns>                                       
                                        <asp:TemplateField>
                                            <ItemTemplate>
                                                <asp:ImageButton ID="imgDownloadPDF" runat="server" 
                                                    CommandArgument='<%# Bind("ImageKey") %>' CommandName="DownloadDocument" 
                                                    ImageUrl="~/images/PDF-download.png" ToolTip="Download file to your computer" />
                                            </ItemTemplate>
                                        </asp:TemplateField>
                                    </Columns>
                                    <EmptyDataRowStyle ForeColor="Red" HorizontalAlign="Center" />
                                </asp:GridView>
                            </div>
                        </ContentTemplate>
                    </asp:UpdatePanel> 
                </Content>
            </cc1:AccordionPane>
        </Panes>                
    </cc1:Accordion>            
</asp:Panel>

- Default.aspx.vb -

Private Sub gvPolicyDocs_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvPolicyDocs.RowDataBound
    Dim imgDownloadPDF As ImageButton = e.Row.FindControl("imgDownloadPDF")
    If imgDownloadPDF IsNot Nothing Then
        ScriptManager.GetCurrent(Page).RegisterPostBackControl(imgDownloadPDF)  
        'I just tried changing to RegisterAsyncPostBackControl method and found that I receive the same error even on the first attempt
    End If
End Sub

Protected Sub gvPolicyDocs_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles gvPolicyDocs.RowCommand
    Try
        StreamPDF(e.CommandArgument, False)
    Catch ex As Exception
        ErrorHandler.HandleError(ex)    'sends out an email and returns back; ErrorHandler is an object I created
    End Try
    hdnHiddenField_mpeModalPopup.Show()    'otherwise modal popup disappears after return from postback
End Sub

Private Sub StreamPDF(ByVal strImageKey As String)
    Dim dtImagePaths As DataTable
    Dim oPDFManager As New PdfManager   'from ASPPDF library
    Dim bytes() As Byte
    Dim strImagePath As String = String.Empty

    If String.IsNullOrEmpty(strImageKey) Then
        Throw New Exception("Invalid Image Key")
    End If

    'Get image path from database
    ...
    ...

    strImagePath = dtImagePaths.Rows(0).Item("ImagePath")
    bytes = oPDFManager.OpenDocument(strImagePath).SaveToMemory()   
    'I checked that on the run after the error, bytes contains exactly what I want - so when I write it to a file locally, I can see the PDF

    With Current
        .Response.BufferOutput = False  'tried true and false
        .Response.Clear()
        .Response.ClearContent()
        .Response.ClearHeaders()
        .Response.ContentType = "application/pdf"
        .Response.AddHeader("Content-Disposition", String.Format("{0}; filename={1}.pdf", IIf(bDownloadFile, "attachment", "inline"), strImageKey))
        .Response.AddHeader("Content-Length", bytes.Length)
        .Response.BinaryWrite(bytes)
        .Response.Flush()
        .Response.Close()
        'Response.End()     '--> See http://support.microsoft.com/kb/312629
        .ApplicationInstance.CompleteRequest()
    End With
End Sub

3 个答案:

答案 0 :(得分:1)

UpdatePanel可能是这里的问题。

请看这里。

Why won't Response.Write() export a CSV file to the browser?

答案 1 :(得分:0)

好吧,如果有其他人遇到这个问题,this article完全帮助了我。它基本上表明您无法在同一页面上下载和使用异步后备功能(通过UpdatePanel)。它演示了一种解决方法,其中所有下载代码都在完全独立的页面上完成,并且该页面在当前页面上的隐藏iframe中打开。另外,如果您也尝试在新窗口中打开pdf,则应用相同的解决方法,但不是向当前页面添加iframe,而是可以在JavaScript中调用window.open()。

答案 2 :(得分:0)

所以,我不确定如何在VB中解决这个问题,但我知道C#中这个问题的原因,因为我自己只需处理这个问题。

问题在于按钮本身。您需要使用ScriptManager注册该按钮。您无法在PageLoad()事件中执行此操作,实际上您必须向该按钮添加OnInit事件并在其中添加注册。

C#中的示例:

ASP页面代码:

<asp:ImageButton ID="imgDownloadPDF" runat="server" onInit="imgDownloadPDF_Init" ... />

代码背后:

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

我希望这会有所帮助。