Uttam Ughareja
Uttam Ughareja

Reputation: 1345

Download file request returning JSON instead of file in ASP.NET Web API on server

I'm trying to download CSV file in ASP.NET Web API. Here is my code, and it's working in local.

[Route("{name?}")]
public HttpResponseMessage Get(string name = "DownloadFile")
{
    name = name.EndsWith(".csv") ? name : $"{name}.csv";
    var stream = new MemoryStream();
    var writer = new StreamWriter(stream);
    writer.Write("Hello, World!");
    writer.Flush();
    stream.Position = 0;

    var result = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new ByteArrayContent(stream.ToArray())
    };
    result.Content.Headers.Add("x-filename", name);
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
    {
        FileName = name
    };
    return result;
}

The file is being downloaded in browser in localhost. I deployed the same code on the server and it's returning a JSON in the browser instead of downloading a file.

JSON looks like this:

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

I've checked mime type in IIS and it's there. Am I missing anything ??

Upvotes: 6

Views: 3416

Answers (3)

Girish Khadse
Girish Khadse

Reputation: 45

I faced the similar issue and answer here to another SO question helped me with it.

Apparently it was the conflicts in System.Net.Http assemblies causing the HttpResponse to behave abnormally. I uninstalled the System.Net.Http nuget package and installed it back. And then I checked in Binding Redirects generated in the web.config.

Upvotes: 0

cbedrosian
cbedrosian

Reputation: 470

I ran into this similar problem using WebApi which worked fine locally when debugging in Visual Studio and when deployed to IIS locally. On my server, I was getting the JSON response as above. After a fresh deploy I was seeing a new error about missing method:

Method not found: 'System.Net.Http.HttpRequestMessage System.Web.Http.Controllers.HttpActionContext.get_Request()'.

The resolution was to add a new binding redirect. Perhaps this is an effective fix for you.

  <dependentAssembly>
    <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.2.0.0" />
  </dependentAssembly>

Upvotes: 1

Train
Train

Reputation: 3496

This is what usually works for me

        private ActionResult GetFile(string path, string fileName)
        {
            var memory = new MemoryStream();
            using (var stream = new FileStream(path + fileName, FileMode.Open))
            {
                stream.CopyTo(memory);
            }
            memory.Position = 0;
            var file = File(memory, GetContentType(path + fileName), Path.GetFileName(path + fileName));
            file.FileDownloadName = fileName;
            return file;
        }

        private string GetContentType(string path)
        {
            var types = GetMimeTypes();
            var ext = Path.GetExtension(path).ToLowerInvariant();
            return types[ext];
        }
        //find out what .csv is these won't work for you
        private Dictionary<string, string> GetMimeTypes()
        {
            return new Dictionary<string, string>
            {
                //{".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation" }
                //{".docx", "application/vnd.ms-word"}
                //{".pdf", "application/pdf"}
            };
        }

Then for the controller call it like this

public FileResult GeneratePoExportDocument(params)
{

    return GetFile(HostingEnvironment.ApplicationPhysicalPath + "Documents", "\\mydoc.docx");
}

After that it should automatically download the file.

Edit: Fix return type for controller method

Try the mimetypes

application/vnd.ms-excel

or

text/csv

Upvotes: 0

Related Questions