1

I've created an ASP.NET Web API 2 controller POST method that returns an HttpResponseMessage containing a csv file. Unfortunately, when I try to use this method from my Angular app the response is always a serialized version of the HttpResponseMessage.

The controller method:

[Route("club/{clubId}/audience/export/csv")]
[HttpPost]
[ProducesResponseType(typeof(HttpResponseMessage), 200)]
public async Task<HttpResponseMessage> ExportAudienceCSV([FromRoute] int clubId, [FromBody]EmailInput emailInput)
{
   return await this.GenerateCsv($"AudienceExport_{DateTime.UtcNow:HHmmssddMMyy}",
         () => _commsServices.ExportAudienceCSV(clubId, emailInput));
}

My method that creates the HttpResponseMessage using a stream containing the csv data (the stream was reset to the position 0 before this):

public static async Task<HttpResponseMessage> GenerateCsv(this BaseController controller,
    string fileName,
    Func<Task<MemoryStream>> fileGenerator)
{
  var reportStream = await fileGenerator.Invoke();

  var result = new HttpResponseMessage(HttpStatusCode.OK)
  {
     Content = new StreamContent(reportStream)
  };

  result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
  {
     FileName = $"{fileName}.csv"
  };

  result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
  result.Content.Headers.ContentLength = reportStream.Length;

  return result;
}

The request method looks like this:

POST http://localhost:51056/api/v1/comms/club/2/audience/export/csv HTTP/1.1
Host: localhost:51056
Connection: keep-alive
Content-Length: 121
Origin: http://localhost:5000
AppTimezoneOffset: 0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
Content-Type: application/json
Accept: application/json, text/plain, */*
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Referer: XXXXXXXXXXXXXXXXXXX
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,en-GB;q=0.8

{"audience":[{"series":378,"divisions":[],"subseries":[],"races":[],"includeSkippers":true,"includeAllBoatAdmins":true}]}

The response is this:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Vary: Origin
Server: Kestrel
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:5000
Access-Control-Expose-Headers: *
Request-Context: appId=cid-v1:73955d83-a87e-4968-b6b4-5878f10f9dab
X-Powered-By: ASP.NET
Date: Thu, 09 Jan 2020 11:17:57 GMT
Content-Length: 416

{"version":{"major":1,"minor":1,"build":-1,"revision":-1,"majorRevision":-1,"minorRevision":-1},"content":{"headers":[{"key":"Content-Disposition","value":["attachment; filename=AudienceExport_111755090120.csv"]},{"key":"Content-Type","value":["application/octet-stream"]},{"key":"Content-Length","value":["5915"]}]},"statusCode":200,"reasonPhrase":"OK","headers":[],"requestMessage":null,"isSuccessStatusCode":true}

As you can see, the HttpResponseMessage has just been serialised but there is no content containing the file. Any idea what might be going on here?

James Mundy
  • 4,180
  • 6
  • 35
  • 58
  • have you tried result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv"); ?? – dimmits Jan 09 '20 at 12:45
  • 1
    Try to use [`FileResult`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.fileresult): `return File(fileStream, "text/csv", fileDownloadName)`. Also you can use [custom formatter](https://learn.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting) – Didgeridoo Jan 09 '20 at 13:42
  • Yep, FileResult is the way. – Derek Jan 09 '20 at 14:10
  • Also, see this: https://stackoverflow.com/questions/29948809/web-api-return-csv-file/29951751 – Stuart Jan 09 '20 at 20:30
  • Thanks, I will give it a go. I did try "text/csv" – James Mundy Jan 09 '20 at 22:34

1 Answers1

-1

try this code first, you need to create a file into Stream.

  public HttpResponseMessage GenrateFile(Stream stream, string fileName)
  {
        HttpResponseMessage response;
        response = Request.CreateResponse(HttpStatusCode.OK);
        MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("text/csv");
        response.Content = new StreamContent(stream);
        response.Content = response.Content;
        response.Content.Headers.ContentType = mediaType;
        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
        response.Content.Headers.ContentDisposition.FileName = fileName;
        return response;
   }
Sunny Jangid
  • 578
  • 4
  • 19