Shoba Shoba - 25 days ago 33
ASP.NET (C#) Question

Return PDF to the Browser using Asp.net core

I created the Wep API in ASP.Net core to return the PDF. Here is my code:

public HttpResponseMessage Get(int id)
{
var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
var stream = new System.IO.FileStream(@"C:\Users\shoba_eswar\Documents\REquest.pdf", System.IO.FileMode.Open);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = "NewTab";
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
return response;
}


But it returns only the JSON response:

{
"version":{
"major":1,
"minor":1,
"build":-1,
"revision":-1,
"majorRevision":-1,
"minorRevision":-1
},
"content":{
"headers":[
{
"key":"Content-Disposition",
"value":[
"attachment; filename=NewTab"
]
},
{
"key":"Content-Type",
"value":[
"application/pdf"
]
}
]
},
"statusCode":200,
"reasonPhrase":"OK",
"headers":[

],
"requestMessage":null,
"isSuccessStatusCode":true
}


Am I doing anything wrong here?

Answer

As explained in ASP.NET Core HTTPRequestMessage returns strange JSON message, ASP.NET Core does not support returning an HttpResponseMessage (what package did you install to get access to that type?).

Because of this, the serializer is simply writing all public properties of the HttpResponseMessage to the output, as it would with any other unsupported response type.

To support custom responses, you must return an IActionResult-implementing type. There's plenty of those. In your case, I'd look into the FileStreamResult:

public IActionResult Get(int id)
{
    using (var stream = new FileStream(@"path\to\file", FileMode.Open))
    {
        return new FileStreamResult(stream, "application/pdf");
    }
}

Or simply use a PhysicalFileResult, where the stream is handled for you:

public IActionResult Get(int id)
{
    return new FileStreamResult(@"path\to\file", "application/pdf");
}

Or if you're converting an older MVC or Web API application and don't want to convert all your code at once, add a reference to WebApiCompatShim (NuGet) and wrap your current code in a ResponseMessageResult:

public IActionResult Get(int id)
{
    var response = new HttpResponseMessage(HttpStatusCode.OK);           
    var stream = ...
    response.Content...

    return new ResponseMessageResult(response);
}

As of now, the result types that return a file don't support setting the content-disposition header from the constructor or through properties. So you'll have to add that response header to the response yourself, as explained in ASP.Net Core Content-Disposition attachment/inline:

System.Net.Mime.ContentDisposition contentDisposition = new System.Net.Mime.ContentDisposition
{
    FileName = string,
    Inline = bool
};
Response.Headers.Add("Content-Disposition", contentDisposition.ToString());
Comments