title: How to upload and download multiple files without Page Refresh using a GridView in ASP .NET C#?
body: <p>For a week I am working on a project, which has a functionality of uploading and downloading pdf and jpg files, the project is from a friend but it was assigned to me because he went on a trip.</p>
  
  <p>The point is that this functionality of uploading and downloading files is very curious and I have made several changes which has caused me severe problems in downloading files.</p>
  
  <p>Initially we have a web form (ASPX) which is part of a MasterPage, in one part of this form an ASCX control is implemented, this control is the one that has all the loading and unloading of files, within this control there is a button to add a file loader (HyperLink) and another to download (button with flag runat = "server"), the final part is a GridView, the code looks like this:</p>
  
  <pre><code>&lt;%@ Control Language="C#" CodeBehind="MultiUpload.ascx.cs" Inherits="D_Soft.DynamicData.FieldTemplates.MultiUpload" %&gt;
  &lt;%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" Tagprefix="cc1" %&gt;
  
  &lt;fieldset class="fUploadControl"&gt;
      &lt;legend&gt;
          &lt;h1&gt;Upload Files&lt;/h1&gt;
      &lt;/legend&gt;
      &lt;asp:UpdatePanel ID="upMultiUpload" runat="server" UpdateMode="Always"&gt;
          &lt;ContentTemplate&gt;
  
              &lt;asp:Panel ID="pnlUpload" runat="server"&gt;
  
                  &lt;asp:FileUpload ID="upldFile_0" CssClass="form-control" runat="server" /&gt;
  
              &lt;/asp:Panel&gt;
              &lt;br /&gt;
  
              &lt;div class="row"&gt;
              &lt;div class="col-xs-12 col-sm-12 col-md-2 col-lg-2"&gt;
                  &lt;asp:HyperLink ID="lnkAddFileUpload" CssClass="btn btn-block btn-primary" NavigateUrl="javascript:addFileUploadCtrl();" runat="server"&gt;&lt;i class="fa fa-plus"&gt;&lt;/i&gt;&amp;nbsp;&amp;nbsp;Add&lt;/asp:HyperLink&gt;
              &lt;/div&gt;
              &lt;div class="col-xs-12 col-sm-12 col-md-2 col-lg-2"&gt;
                  &lt;button runat="server" id="btnUpload" data-ajax="false" type="button" onserverclick="btnUpload_Click" class="btn btn-block btn-primary"&gt;&lt;i class="fa fa-upload"&gt;&lt;/i&gt;&amp;nbsp;&amp;nbsp;Upload&lt;/button&gt;
              &lt;/div&gt;
  
          &lt;/div&gt;
          &lt;/ContentTemplate&gt;
          &lt;Triggers&gt;
              &lt;asp:PostBackTrigger ControlID="btnUpload" /&gt;
          &lt;/Triggers&gt;
      &lt;/asp:UpdatePanel&gt;
  
      &lt;br /&gt;
  
      &lt;div class="row"&gt;
          &lt;div class="col-xs-12 col-sm-12 col-md-12 col-lg-12"&gt;
              &lt;div style="width: 100%; overflow: auto"&gt;
                      &lt;asp:GridView ID="GridFiles" runat="server"
                          AutoGenerateColumns="False" CellPadding="3" DataKeyNames="RowId,File,Path,Exists"
                          Font-Names="Calibri" Font-Size="10pt" OnRowDeleting="GridFilesArchivos_RowDeleting" OnSelectedIndexChanged="GridFiles_SelectedIndexChanged"
                          ForeColor="#333333" GridLines="Both" Height="25px"
                          Width="500px"
                          Style="font-size: 10pt"
                          CssClass="mGrid" PagerStyle-CssClass="pgr" AlternatingRowStyle-CssClass="alt"&gt;
                          &lt;FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" /&gt;
                          &lt;RowStyle BackColor="#F7F6F3" ForeColor="#333333" /&gt;
                          &lt;PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" /&gt;
                          &lt;SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" /&gt;
                          &lt;HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" /&gt;
                          &lt;Columns&gt;
                              &lt;asp:BoundField DataField="RowId" SortExpression="RowId" Visible="False" /&gt;
                              &lt;asp:BoundField DataField="File" HeaderText="FILE" SortExpression="File"&gt;
                                  &lt;HeaderStyle HorizontalAlign="Center" /&gt;
                                  &lt;ItemStyle Width="85%" HorizontalAlign="Center" /&gt;
                              &lt;/asp:BoundField&gt;
                              &lt;asp:BoundField DataField="Path" SortExpression="Path" Visible="False" /&gt;
                              &lt;asp:BoundField DataField="Exists" SortExpression="Exists" Visible="False" /&gt;
                              &lt;asp:CommandField ItemStyle-Width="15%" ItemStyle-HorizontalAlign="Center" ShowCancelButton="false" HeaderText="ACTION" ButtonType="Image" Visible="true" DeleteImageUrl="~/img/trash.png" ShowDeleteButton="True" ShowSelectButton="true" SelectImageUrl="~/img/download.png" /&gt;
                          &lt;/Columns&gt;
                      &lt;/asp:GridView&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/fieldset&gt;
  </code></pre>
  
  <p>And the GUI look this:</p>
  
  <p><a href="https://i.stack.imgur.com/OBJJT.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/OBJJT.png" alt="enter image description here"></a></p>
  
  <p>For the code C # has a file upload and file download event, however, I had to make changes since some web form controls are adapted to Postback calls and I do not want the page to load again, what you see something like this:</p>
  
  <pre><code>protected void Page_Load(object sender, EventArgs e)
  {
      Page.Form.Attributes.Add("enctype", "multipart/form-data");
  }
  
  protected void btnUpload_Click(object sender, EventArgs e)
  {
      UploadFiles();
  }
  
  public bool UploadFiles()
  {
      DataTable dtFiles = new DataTable();
  
      dtFiles.Columns.Add(new DataColumn("RowId", typeof(int)));
      dtFiles.Columns.Add(new DataColumn("File", typeof(string)));
      dtFiles.Columns.Add(new DataColumn("Path", typeof(string)));
      dtFiles.Columns.Add(new DataColumn("Exists", typeof(string)));
  
      //Number of files, here the files to be uploaded are captured, 
      //before uploading any file valid the size, name and extension of the 
      //file, this code I have omitted because I do not think it is necessary
  
      HttpFileCollection col = Request.Files;
  
      int cantFiles = 0;
  
      //This code allows me to save each of the files in Request.Files
  
      for (int i = 0; i &lt; fcol.Count; i++)
      {
          HttpPostedFile postedF = col[i];
          if (postedF.ContentLength &gt; 0)
          {
              string tmpsave = string.Format("{0}\\{1}", dirPath, Path.GetFileName(postedF.FileName));
  
              //Create a temporary file name that will be used for checking duplicates
  
              string tempfileName = "";
  
              // Check if there is already a file with the same name to load
  
              if (System.IO.File.Exists(tmpsave))
              {
                  int counter = 2;
                  while (System.IO.File.Exists(tmpsave))
                  {
                      tempfileName = counter.ToString() +"_"+ Path.GetFileName(postedF.FileName);
                      tmpsave= string.Format("{0}\\{1}", dirPath, tempfileName);
                      counter++;
                  }
              }
  
              //Save File in server
  
              postedF.SaveAs(tmpsave);
  
              //Update Rows
  
              DataRow dwRow = dtFiles.NewRow();
  
              dwRow["RowId"] = cantFiles;
              dwRow["File"] = Path.GetFileName(postedF.FileName);
              dwRow["Path"] = tmpsave;
              dwRow["Exists"] = "NO";
  
              dtFiles.Rows.Add(dwRow);
  
              cantFiles++;
          }
      }
  
      //Update GridView
  
      GridFiles.DataSource = dtFiles;
      GridFiles.DataBind();
  }
  
  protected void GridArchivos_SelectedIndexChanged(object sender, EventArgs e)
  {
      string stPathDes = this.GridFiles.DataKeys[this.GridFiles.SelectedIndex][2].ToString();
  
      DownloadFile(HttpContext.Current, stPathDes, Path.GetFileNameWithoutExtension(stPathDes) + Path.GetExtension(stPathDes).ToLower());
  }
  
  public static void DownloadFile(System.Web.HttpContext context, string stUbication, string stName)
  {
  
      stUbication can be: "D:\\Project\\ProjectUpload\\ProjectUpload.Web\\Files\\anyfolder\\\\123.pdf"
  
      stName can be: "123.pdf"
  
      try
      {
          System.IO.FileInfo toDownload = new System.IO.FileInfo(stUbication);
          System.Web.HttpResponse response = context.Response;
  
          if (toDownload.Exists)
          {
              response.ClearContent();
              response.Clear();
              response.AddHeader("Content-Disposition", "attachment; filename=" + stName);
              response.AddHeader("Content-Length", toDownload.Length.ToString());
              response.ContentType = "application/octet-stream";
              response.WriteFile(stUbication);
              response.Flush();
              //response.End();
              context.ApplicationInstance.CompleteRequest();
          }
      }
      catch (Exception ex)
      {
          throw ex;
      }
  }
  </code></pre>
  
  <p>The first line of the Page_Load method together with the implementation of the UpdatePanel and the PostBackTrigger allow me to load multiple files, this I did because the Request.File variable always arrived empty.</p>
  
  <p>Now the file upload works without problems until now. The line response.End(); is commented because I had generated an exception of type "Unable to evaluate the expression because the code is optimized or a native frame is on top of the call stack".</p>
  
  <p>The problem is that pressing the button to download the file is never downloaded and the progress bar is triggered, in addition to this an error arises in the JavaScript console ("Cannot read property 'PRM_ParserErrorDetails' of undefined"):</p>
  
  <p><a href="https://i.stack.imgur.com/llX6T.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/llX6T.png" alt="enter image description here"></a></p>
  
  <p>The error does not have much documentation and I really do not know if I'm building a code incorrectly or I need to implement something else.</p>
  
  <p>This control is implemented in the web form (ASPX) as follows:</p>
  
  <pre><code>&lt;%@ Page Title="" Language="C#" MasterPageFile="~/TheMaster.Master" AutoEventWireup="true" CodeBehind="MyForm.aspx.cs" Inherits="ProjectUpload.Web.MyForm" MaintainScrollPositionOnPostback="true" %&gt;
  &lt;%@ Register Src="~/Controls/MultiUpload.ascx" TagPrefix="uc1" TagName="MultiUpload" %&gt;
  
  &lt;asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server"&gt;
  
      &lt;asp:UpdatePanel ID="upPanelRequest" runat="server"&gt;
          &lt;ContentTemplate&gt;
  
              //In this UpdatePanel I have a button (btnButtonSave)
              //I do this to not refresh the page again, this button performs a process with the database, 
              //therefore, it is delayed and I need to do the Return to show a progress bar (gif)
  
              &lt;uc1:MultiUpload runat="server" id="MultiUpload" /&gt;
  
              &lt;button runat="server" type="button" id="btnButtonSave" onclick="DisableButton(this);" onserverclick="btnButtonSave_ServerClick" class="btn btn-success btn-block"&gt;
                  &lt;i class="fa fa-save"&gt;&lt;/i&gt;&amp;nbsp;&amp;nbsp;SAVE
              &lt;/button&gt;
  
          &lt;/ContentTemplate&gt;
          &lt;Triggers&gt;
              &lt;asp:AsyncPostBackTrigger ControlID="btnButtonSave" /&gt; 
              &lt;asp:AsyncPostBackTrigger ControlID="MultiUpload" /&gt; 
          &lt;/Triggers&gt;
      &lt;/asp:UpdatePanel&gt;
  
  &lt;/asp:Content&gt;
  </code></pre>
  
  <p>Something strange that I have noticed is that when I upload a file, the form reloads completely. What could I be using wrong?</p>
  
  <p>Can anybody help me?</p>