Asp.net-core – Return Excel File from WebAPI ASPNetCore

asp.net-coreasp.net-web-api

I am trying to create the WebAPI which will return an Excel file by using ClosedXML Library.

It's all working fine, if I return the FileStreamResult. But if I changed it to HttpResponseMessage as discussed here Web API Return A File, I couldn't download a file or see the content anymore and getting JSON string.

I would like to know how I could extract the File Content from this HttpResponseMessage.

I tested in browser or PostMan tool and all I got back is JSON String:

{
      "version": {
        "major": 1,
        "minor": 1,
        "build": -1,
        "revision": -1,
        "majorRevision": -1,
        "minorRevision": -1
      },
      "content": {
        "headers": [
          {
            "key": "Content-Disposition",
            "value": [
              "attachment; filename=ERSheet.xlsx"
            ]
          },
          {
            "key": "Content-Type",
            "value": [
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            ]
          }
        ]
      },
      "statusCode": 200,
      "reasonPhrase": "OK",
      "headers": [],
      "requestMessage": null,
      "isSuccessStatusCode": true
    }

My Code is as follow:

[HttpGet("ERSheet2")]
        public HttpResponseMessage ER_GenerateWBLWorksheet2()
        {
            MemoryStream stream = new MemoryStream();
            var workbook = new XLWorkbook();

            var SheetNames = new List<string>() { "15-16", "16-17", "17-18", "18-19", "19-20" };

            foreach (var sheetname in SheetNames)
            {
                var worksheet = workbook.Worksheets.Add(sheetname);

                worksheet.Cell("A1").Value = sheetname;
            }

            workbook.SaveAs(stream);
            stream.Seek(0, SeekOrigin.Begin);

            HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
            result.Content = new ByteArrayContent(stream.ToArray());
            result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
            result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            result.Content.Headers.ContentDisposition.FileName = "ERSheet.xlsx";
            return result;
        }

Updated

This one is different from this question Download file with ClosedXML because I mentioned that I already made it work by using 'FileStreamResult'. I am asking this because of this comment "Better to return HttpResponseMessage with StreamContent inside of it." made in this thread Web API Return A File. So, trying to use HttpResponseMessage in .Net Core and didn't know that it doesn't support anymore as Darin's answer.

Best Answer

ASP.NET Web API running on .NET Core doesn't support HttpResponseMessage anymore. So basically it tries to serialize the instance of this object that you are returning to JSON (as if it was a simple view model of yours). There are some compatibility shim hacks which you could use but in general I would recommend you using the more idiomatic approach - return an IActionResult instance from your action:

[HttpGet("ERSheet2")]
public IActionResult ER_GenerateWBLWorksheet2()
{
    using (MemoryStream stream = new MemoryStream())
    {
        var workbook = new XLWorkbook();

        var SheetNames = new List<string>() { "15-16", "16-17", "17-18", "18-19", "19-20" };

        foreach (var sheetname in SheetNames)
        {
            var worksheet = workbook.Worksheets.Add(sheetname);

            worksheet.Cell("A1").Value = sheetname;
        }

        workbook.SaveAs(stream);
        stream.Seek(0, SeekOrigin.Begin);

        return this.File(
            fileContents: stream.ToArray(), 
            contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", 

            // By setting a file download name the framework will
            // automatically add the attachment Content-Disposition header
            fileDownloadName: "ERSheet.xlsx"
        );
    }
}