No more post back after file download in sharepoint

12,829

Solution 1

SharePoint registers a JavaScript "on submit" handler. In this handler the global variable _spFormOnSubmitCalled is set to true. SharePoint uses this variable to check if a submit was executed and prevents any further submits. Since your "download postback" does not refresh the page this variable remains true. With the effect that that all other buttons stop working.

As a workaround you can set this variable to false in a client click handler on your download button:

Button btn = new Button();
btn.Text = "Download";
btn.Click += DownloadButton_Click;

// set the client click handler
btn.OnClientClick = "window.setTimeout(function() { _spFormOnSubmitCalled = false; }, 10);"

Of course thats a little hacky and is not garantueed to work in upcoming SharePoint versions.

Solution 2

There is an easy way to work around this. Register OnClientClick event for the button click and set _spFormOnSubmitCalled to false.

<asp:Button ID="Button1" runat="server" Text="Export" onclick="Button1_Click" OnClientClick="javascript:setFormSubmitToFalse()" />

And put the script below in the page/js file.

<script type="text/javascript">
    function setFormSubmitToFalse() {
        _spFormOnSubmitCalled = false;        
        return true;
    }
</script>

Solution 3

I had no success using '_spFormOnSubmitCalled'. I did have success by placing this in my Page_Load function.

string js = @"_spSuppressFormOnSubmitWrapper = true;";
this.Page.ClientScript.RegisterStartupScript(this.GetType(), "js", js, true);

Ajax second postback not working in Sharepoint in UpdatePanel Provides some background information as to why this is needed.

Solution 4

I am using SharePoint 2010 and DexExpress and inside my visual webpart all I needed to add was the clientSideEvents portion. below is my code...

<dx:ASPxButton 
    runat="server" 
    ID="btnExportGrid" 
    Text="Export Data" 
    AutoPostBack="False"  
  OnClick="btnExportGrid_Click" Theme="Office2010Blue" Width="140px"    
  CausesValidation="False"  >
      <ClientSideEvents Click="function(s, e) {_spFormOnSubmitCalled=false;_spSuppressFormOnSubmitWrapper=true; }" />
</dx:ASPxButton>

and my C# code

protected void btnExportGrid_Click(object sender, EventArgs e)
{
  gridExporter.WriteXlsToResponse();   
}

Hope this helps.

Solution 5

there's an even easier solution to all of this. Instead of a download button simply use an

<a>

I usually use something like:

<a href='<%# String.Format("{0}",BuildUrl(Eval("Title")))%>' title='<%#Eval("Title") %>'>Download</a>
Share:
12,829
kevin
Author by

kevin

I am trying to be an expert :D

Updated on June 22, 2022

Comments

  • kevin
    kevin almost 2 years

    I tried to download a file from sharepoint. But after I download this file, I can't click on other buttons. What is wrong with my coding?

    This is my first way.

                Response.AppendHeader("content-disposition", "attachment; filename= " + fileName);
                Response.ContentType = "text/plain";
                Response.WriteFile(Server.MapPath("~/" + fileName));
                Response.End();
    

    This is my second way

                byte[] bytes = System.IO.File.ReadAllBytes("D:\\" + fileName);
    
                Response.ClearContent();
                Response.ClearHeaders();
                Response.AddHeader("Content-Type", "application/octet-stream");
                Response.AddHeader("Content-Length", bytes.Length.ToString());
    
                Response.AddHeader("content-disposition", "attachment; filename= " + fileName);
    
                Response.BinaryWrite(bytes);
                Response.Flush();
                Response.End();
    

    I even comment Response.End() but still the same result.

    Is there any other way I should tried?

    Any help would be really appreciated. In fact, I posted this question a few days ago, but only one gave me my second way to try but it is still not working.

    Thanks.

    UPDATE

    Here is my GridView under GridView.

               <asp:GridView ID="gvGiro" Width="100%" runat="server" GridLines="Both" AllowPaging="false" CssClass="form-table" ShowHeader="false"
                    AllowSorting="false" AutoGenerateColumns="false" OnRowDataBound="gvGiro_RowDataBound">
                    <Columns>
                        <asp:TemplateField ItemStyle-Width="20%" ItemStyle-HorizontalAlign="Center">
                            <ItemTemplate>
                                <asp:Label ID="lblValueDate" Text='<%# getDate(Eval("ValueDate")) %>' runat="server" />
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField>
                            <ItemTemplate>
    
                                <asp:GridView ID="gvDetail" runat="server" AllowPaging="false" AllowSorting="false" 
                                    CssClass="list-table border" HeaderStyle-CssClass="header" AutoGenerateColumns="false">
                                    <Columns>
                                        <asp:TemplateField HeaderText="Sequence Number" ItemStyle-HorizontalAlign="Left"
                                            ItemStyle-Width="30%" >
                                            <ItemTemplate>
                                                <%#((DataRowView)Container.DataItem)["MessageSeqNbr"] %>
                                            </ItemTemplate>
                                        </asp:TemplateField>
                                        <asp:TemplateField HeaderText="Total Number of Debit Transaction" ItemStyle-HorizontalAlign="Left"
                                            HeaderStyle-HorizontalAlign="Center">
                                            <ItemTemplate>
                                                <%#((DataRowView)Container.DataItem)["TotalDebitNbr"] %>
                                            </ItemTemplate>
                                        </asp:TemplateField>
                                        <asp:TemplateField HeaderText="Status" ItemStyle-HorizontalAlign="Left" ItemStyle-Width="25%"
                                            HeaderStyle-HorizontalAlign="Center">
                                            <ItemTemplate>
                                                <%#((DataRowView)Container.DataItem)["CodeDesc"] %>
                                                <asp:HiddenField ID="hidCode" runat="server" Value='<%#((DataRowView)Container.DataItem)["Code"] %>' />
                                            </ItemTemplate>
                                        </asp:TemplateField>
                                        <asp:TemplateField HeaderText="Action" ItemStyle-HorizontalAlign="Center" ItemStyle-Width="10%"
                                            HeaderStyle-HorizontalAlign="Center">
                                            <ItemTemplate>
                                            <asp:Button ID="btnDownload" runat="server" CssClass="button submit" Text="Download" 
                                    CommandName="download" OnCommand="onCmd" CommandArgument='<%#Eval("Id") %>' Width="80px"/>
                                            <asp:Button ID="btnUnbatch" runat="server" CssClass="button generic" Text="Un-Batch"
                                    CommandName="unbatch" OnCommand="onCmd" CommandArgument='<%#Eval("Id") %>' Width="80px"/>
                                            </ItemTemplate>
                                        </asp:TemplateField>
                                    </Columns>
                                </asp:GridView>
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>
    

    Here is my cs file

        protected void gvGiro_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            GridView gr;
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                gr = (GridView) e.Row.FindControl("gvDetail");
                using (class2 ct2= new Class2())
                {
                    Label lblValueDate = (Label)e.Row.FindControl("lblValueDate");
                    DateTime dt= DateTime.MinValue;
                    DataSet ds= ct2.GetData(dt);
                    gr.DataSource = ds; 
                    gr.DataBind();
    
                }
    
            }
        }
    
    
    protected void onCmd(object sender, CommandEventArgs e)
        {
            string id;
            switch (e.CommandName)
            {
                case "unbatch":
                    id= e.CommandArgument.ToString();
                    Unbatch(id);
                    break;
                case"download":
                    id= e.CommandArgument.ToString();
                    Download(id);
                    break;
                default:
                    break;
            }
        }
    
        protected void Download(string id)
        {
            // to do - substitute all hard-code guid
            Guid batchId = new Guid(id);
            string fileName = "";
            Class1 ct = new Class1();
    
    
            {
                if (!ct.FileExists(batchId , ref fileName))
                {
                    byte[] bytes = System.IO.File.ReadAllBytes("D:\\" + fileName);
                Response.ClearContent();
                Response.ClearHeaders();
                Response.AddHeader("Content-Type", "application/octet-stream");
                Response.AddHeader("Content-Length", bytes.Length.ToString());
                Response.AddHeader("content-disposition", "attachment; filename= " + fileName);
                Response.BinaryWrite(bytes);
                Response.Flush();
                Response.End();
                }
    
  • kevin
    kevin over 12 years
    I am trying to use your way. But unfortunately, I use onCommand for this button and those buttons are inside a GridView. When I try to substitue btn.Click+=DownloadButton_Click with btn.Command = onCmd, it does not work.
  • Stefan
    Stefan over 12 years
    can you post the code which creates the button or the grid view?
  • kevin
    kevin over 12 years
    Thx for ur help, in fact, it's GridView inside GridView. I will update in my question.
  • Stefan
    Stefan over 12 years
    Adding the OnClientClick handler in the asp does not work? => <asp:Button ... CommandName="download" OnCommand="onCmd" CommandArgument='<%#Eval("Id") %>' OnClientClick="window.setTimeout(function() { _spFormOnSubmitCalled = false; }, 10);" ... />
  • kevin
    kevin over 12 years
    it works perfectly now !!! Thx a lot !!! You are awesome, it took about 4 hours from me before u help me!!
  • kevin
    kevin over 12 years
    -> hi again !! One question, after downloading, I would like to disable the download button on the gridview. So I call gv.DataBind(). It does not work. What can the my problem? I even comment Response.End(). Same result.
  • kevin
    kevin over 12 years
    In BuildUrl , I should write the download coding ?
  • Tjassens
    Tjassens over 12 years
    yep, thats exactly what you should do. I usually make a reference to a utility class where I do this but you can also do it in the code behind of your user control.
  • Etienne
    Etienne over 10 years
    this worked for me while changing the _spFormOnSubmitCalled didn't so +1 and thanks for saving my day
  • Wint
    Wint about 10 years
    You saved my day buddy! (I just added this code to my aspx page and it worked like a charm: _spSuppressFormOnSubmitWrapper = true)
  • SP Developer
    SP Developer almost 8 years
    Thanks flip.. tried lots of tricks but only yours work for me :-)...thanks again