Question

I am trying to send an Excel file to the client of an ASP.Net web page, but it doesn't work.

When the user clicks a button, some data from our server-side database is formatted, put in an Excel file and sent to the user (as a direct download).

Everything works well, except the sending part and any help would be greatly appreciated.

Here is the code I'm using right now (client side):

var dataAjax = {};
$.ajax({
    async: false,
    type: "POST",
    url: "Default.aspx/BuildExcelFile",
    contentType: "application/json",
    data: JSON.stringify(dataAjax),
    dataType: "text",
    success: function(html) {
        //alert(html);
    },
    error: function(request, status, error) {
        alert("An error occurred : [" + error + "]");
    }

});

And the server side code:

<WebMethod()> _
Public Shared Function BuildExcelFile() As String
    Dim localExcelPath = "C:\temp1111.xlsx"

    'Build the excel file here...
    '...

    'Delete the old version of the Excel file
    System.IO.File.Delete(localExcelPath)
    'Save the Excel File locally
    xWorkSheet.SaveAs(localExcelPath)
    xWorkBook.Close()
    exc.Quit()

    'The generated excel is valid, can be opened on the server just fine

    'Send the excel file to the client
    'This part is not working! :(
    System.Web.HttpContext.Current.Response.Clear()
    System.Web.HttpContext.Current.Response.ContentType = "MS-Excel/xls"
    System.Web.HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=" & System.IO.Path.GetFileName(localExcelPath))
    System.Web.HttpContext.Current.Response.TransmitFile(localExcelPath)
    System.Web.HttpContext.Current.Response.End()

    Return "Success"

End Function

I am getting this error when I try to verify the value of Current.Response

Response: Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class.

Also, if I remove the Response.End() call, the data is received in the html variable of the success function in the ajax. However, I want the file to be downloaded, not received as text...

If I keep Response.End(), I get an Internal Server Error.

Is it not working because my Webmethod is shared? Any clue what's going on here? What can I do to fix this problem?

Edit:

I'm using .Net 3.5, if that matters

I'm not using MVC

Was it helpful?

Solution

I had this exact same problem sending data from client to server as well. You could get around it by loading an iFrame dynamically that kicks off the download - the iFrame is basically just filled with a blank aspx page that starts the download in the Page_Load. You could also save the file to the server and provide a link to download it in the client. Those are the workarounds I found that worked.

I don't know if you can do it the way you're trying or not. I checked examples all over and it never worked. If you can't figure it out, these ways worked for me.

OTHER TIPS

Public Shared Function BuildExcelFile() As String
    Dim localExcelPath = "C:\temp1111.xlsx"

    'Build the excel file here...
    '...
    xWorkSheet.SaveAs(localExcelPath)
    xWorkBook.Close()
    exc.Quit()

    'The generated excel is valid, can be opened on the server just fine

    'Send the excel file to the client
    'This part is not working! :(
    System.Web.HttpContext.Current.Response.Clear()
    System.Web.HttpContext.Current.Response.ContentType = "MS-Excel/xls"
    System.Web.HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=" & System.IO.Path.GetFileName(localExcelPath))
    System.Web.HttpContext.Current.Response.TransmitFile(localExcelPath)
    System.IO.File.Delete(localExcelPath)

    System.Web.HttpContext.Current.Response.End()

    Return "Success"
End Function
  1. Use postbacktrigger on your button click if you are using Ajax

This works for me:

string fileName = "ExampleFileName.xlsx";
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment;  filename=" + fileName);
Response.BinaryWrite(excelPackage.GetAsByteArray());
// Response.End(); Replaced with below 3 lines to avoid ThreadAbortException
Response.Flush(); // Sends all currently buffered output to the client.
Response.SuppressContent = true;  // Gets or sets a value indicating whether to send HTTP content to the client.
ApplicationInstance.CompleteRequest(); // Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event.

I am using a dll called 'EPPlus.dll' as my Excel library. There is no need for an Ajax call as you can instantiate the download from an Asp.net button, or simply call a method from your server-side code when you want to start the download.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top