The IT Dejan
The IT Dejan

Reputation: 866

NetCore API Return pdf file in a POST request

I'm using NET Core v2.0

I'm trying to accept a post request with an XML file as a Body, parse the request, and return a generated PDF file. Without going too deep into logic, here's what I have in a controller :

public async Task<HttpResponseMessage> PostMe() {
        return await Task.Run(async () => {
            try {
                using (var reader = new StreamReader(Request.Body, Encoding.UTF8)) {
                    var serializer = new XmlSerializer(typeof(XmlDocument));
                    var objectToParse = (XmlDocument) serializer.Deserialize(reader);
                    var pdfFileLocation = await _service.ParseObject(objectToParse);

                    var response = new HttpResponseMessage(HttpStatusCode.OK);
                    var file = System.IO.File.ReadAllBytes(pdfFileLocation);

                    response.Content = new ByteArrayContent(file);
                    response.Content.Headers.Add("Content-Type", "application/pdf");

                    return response;
                }
            } catch (Exception e) {
                return new HttpResponseMessage(HttpStatusCode.BadRequest);
            }
        });
    }

XML file is a simple XML file I convert into an object, that part works and its irrelevant (also NDA).

I see couple (more than a couple) of questions similar to mine, but I've tried everything and didn't come up with a solution yet. Using postman I get a response like so :

{
 "version": {
     "major": 1,
     "minor": 1,
     "build": -1,
     "revision": -1,
     "majorRevision": -1,
     "minorRevision": -1
 },
 "content": {
     "headers": [
         {
             "key": "Content-Type",
             "value": [
                 "application/pdf"
             ]
         }
     ]
 },
 "statusCode": 200,
 "reasonPhrase": "OK",
 "headers": [],
 "requestMessage": null,
 "isSuccessStatusCode": true 
}

As you can see, the response.Content acts as if nothing has been set. With 100% certainty, the file is created locally, and it's a valid pdf which I can open and see.

I've tried many variations of the response above, but nothing worked. It's either 406's, or empty content. Can anyone help me with this? I've been banging my head for past 4 hours.

Thanks!

Upvotes: 1

Views: 6409

Answers (1)

M&#233;toule
M&#233;toule

Reputation: 14502

In ASP.NET Core, everything returned by a controller's action is serialized: you can't return an HttpResponseMessage, because that, too, will be serialized (this is what you see in your PostMan result).

Your method's signature should instead return IActionResult, and then you should call the File method, like so:

public async Task<IActionResult> PostMe() {
    try {
        using (var reader = new StreamReader(Request.Body, Encoding.UTF8)) {
            var serializer = new XmlSerializer(typeof(XmlDocument));
            var objectToParse = (XmlDocument) serializer.Deserialize(reader);
            var pdfFileLocation = await _service.ParseObject(objectToParse);

            var file = System.IO.File.ReadAllBytes(pdfFileLocation);

            // returns a variant of FileResult
            return File(file, "application/pdf", "my_file.pdf");
        }
    } catch (Exception e) {
        return BadRequest();
    }
}

Note that the File method return different variants of FileResult, depending on which overload you use.

Upvotes: 4

Related Questions