AJAX updatepanel giving error

ajaxasp.netupdatepanelvb.net

I am trying to use AJAX UpdateProgress to display the loading image when the zip file is being created but get the following error:

Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled. Detals: Error parsing near 'PK'.

Below is the code for my .aspx page

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style type="text/css">
        #progressBackgroundFilter
        {
            position: fixed;
            top: 0px;
            bottom: 0px;
            left: 0px;
            right: 0px;
            overflow: hidden;
            padding: 0;
            margin: 0;
            background-color: #000;
            filter: alpha(opacity=50);
            opacity: 0.5;
            z-index: 1000;
        }

        #processMessage
        {
            position: fixed;
            top: 30%;
            left: 43%;
            padding: 10px;
            width: 14%;
            z-index: 1001;
            background-color: #fff;
            border: solid 1px #000;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:CheckBox ID="chb_pass" runat="server" Text="Do you want the zip file to have a password?"
                    AutoPostBack="True" />
                <br />
                <asp:TextBox ID="txt_password" runat="server" MaxLength="20" Visible="false" Style="margin-top: 6px"
                    Width="152px"></asp:TextBox>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="txt_password"
                    ErrorMessage="* Need Password!"></asp:RequiredFieldValidator>
                <br />  
        <asp:Button ID="btnDownloadPhotos" runat="server" Text="Download Album Photos" Height="27px"
                    Style="margin-top: 3px" Width="284px" />


            </ContentTemplate>
            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="btnDownloadPhotos" EventName="Click" />
            </Triggers>
        </asp:UpdatePanel>
        <asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1">
            <ProgressTemplate>
                <div id="progressBackgroundFilter">
                </div>
                <div id="processMessage">
                    Preparing download...<br />
                    <br />
                    <img alt="Loading" src="img/ajax-loader.gif" />
                   </div>
             </ProgressTemplate>
        </asp:UpdateProgress> 
       </div>
    </form>
</body>
</html>

…and below is the code for the aspx.vb page

Imports System.IO
Imports System.Text
Imports Ionic.Zip

Partial Class download
    Inherits System.Web.UI.Page

    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDownloadPhotos.Click

        Dim PhotoFileList As New List(Of String)
        Dim uploadDirectory As String = Server.MapPath("") & "\uploads\"
        Dim albumName As String = "cricket"

        PhotoFileList.Add(uploadDirectory & "CIMG1455.JPG")
        PhotoFileList.Add(uploadDirectory & "CIMG1453.JPG")
        PhotoFileList.Add(uploadDirectory & "CIMG1451.JPG")
        PhotoFileList.Add(uploadDirectory & "CIMG1450.JPG")

        createZip(PhotoFileList, albumName)

    End Sub

    Private Sub createZip(ByVal listOfFilename As List(Of String), ByVal albumName As String)

        ' Tell the browser we're sending a ZIP file!
        Dim downloadFileName As String = String.Format(albumName & "-{0}.zip", DateTime.Now.ToString("yyyy-MM-dd-HH_mm_ss"))
        Response.ContentType = "application/zip"
        Response.AddHeader("Content-Disposition", "filename=" & downloadFileName)

        ' Zip the contents of the selected files
        Using zip As New ZipFile()
            'Add the password protection, if specified
            If chb_pass.Checked = True Then
                zip.Password = txt_password.Text

                'This encryption is weak! Please see http://cheeso.members.winisp.net/DotNetZipHelp/html/24077057-63cb-ac7e-6be5-697fe9ce37d6.htm for more details
                zip.Encryption = EncryptionAlgorithm.PkzipWeak
            End If

            ' Construct the contents of the README.txt file that will be included in this ZIP
            Dim readMeMessage As String = String.Format("This ZIP file {0} contains the following photos within the " & albumName & " album:{1}{1}", downloadFileName, Environment.NewLine)

            ' Add the checked files to the ZIP
            For Each li As String In listOfFilename.ToArray()
                ' Record the file that was included in readMeMessage
                readMeMessage &= String.Concat(vbTab, "* ", li.ToString, Environment.NewLine)

                ' Now add the file to the ZIP (use a value of "" as the second parameter to put the files in the "root" folder)
                zip.AddFile(li.ToString, "Your Files")

            Next

            ' Add the README.txt file to the ZIP
            zip.AddEntry("README.txt", readMeMessage, Encoding.ASCII)

            ' Send the contents of the ZIP back to the output stream
            zip.Save(Response.OutputStream)
        End Using
    End Sub

    Protected Sub chb_pass_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles chb_pass.CheckedChanged
        If chb_pass.Checked = True Then
            txt_password.Visible = True
        ElseIf chb_pass.Checked = False Then
            txt_password.Visible = False
        End If
    End Sub
End Class

Any ideas how I can solve this problem? any help would be greatly appreciated.

Thanks

Best Answer

I had a similar problem in the past trying to stream an excel document with a button inside an update panel. Here is my solution, hope it helps.

VB.NET:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    Dim sm = ScriptManager.GetCurrent(Me.Page)
    sm.RegisterPostBackControl(Me.YOUR_BUTTON)

    AddPostBackTrigger(Me.YOUR_BUTTON.UniqueID.ToString())

End Sub


Public Sub AddPostBackTrigger(ByVal ControlId As String)
    Dim existingTrigger = FindPostBackTrigger(ControlId)
    If existingTrigger Is Nothing Then
        Dim trigger As New PostBackTrigger()
        trigger.ControlID = ControlId
        Me.YOUR_UPDATE_PANEL_GOES_HERE.Triggers.Add(trigger)
    End If
End Sub
Public Sub RemovePostBackTrigger(ByVal ControlId As String)
    Dim existingTrigger = FindPostBackTrigger(ControlId)
    If existingTrigger IsNot Nothing Then
        Me.YOUR_UPDATE_PANEL_GOES_HERE.Triggers.Remove(existingTrigger)
    End If
End Sub
Private Function FindPostBackTrigger(ByVal ControlId As String) As PostBackTrigger
    For Each Trigger In Me.YOUR_UPDATE_PANEL_GOES_HERE.Triggers
        If Trigger.GetType().Name = "PostBackTrigger" Then
            Dim pt = CType(Trigger, PostBackTrigger)
            If pt.ControlID = ControlId Then
                Return pt
            End If
        End If
    Next
    Return Nothing
End Function

C#:

protected void Page_Load(object sender, EventArgs e)
{
    ScriptManager sm = ScriptManager.GetCurrent(Page);
    if (sm != null) sm.RegisterPostBackControl(YOUR_CONTROL);
    AddPostBackTrigger(YOUR_CONTROL.UniqueID);
}

private void AddPostBackTrigger(string controlId)
{
    PostBackTrigger existingTrigger = FindPostBackTrigger(controlId);

    if (existingTrigger != null)
    {
        var trigger = new PostBackTrigger {ControlID = controlId};
        YOUR_UPDATE_PANEL.Triggers.Add(trigger);
    }
}

private PostBackTrigger FindPostBackTrigger(string controlId)
{
    return
        YOUR_UPDATE_PANEL
            .Triggers.OfType<PostBackTrigger>()
            .FirstOrDefault(pt => pt.ControlID == controlId);
}