.NET Core pdf downloader "No output formatter was found for content types 'application/pdf'..."

Viewed 2156

I'm creating a .NET Core 3.1 web api method to download a pdf for a given filename. This method is shared across teams where their client code is generated using NSwag.

I recently changed produces attribute to Produces("Application/pdf") from json, this change is required so other teams can generate valid client code. However since this change, I haven't been able to download any files from this method. Requests to download documents return with a 406 error (in Postman) and the following error is logged to the server event viewer.

No output formatter was found for content types 'application/pdf, application/pdf' to write the response.

Reverting the produced content-type to 'application/json' does allow documents to be downloaded, but as mentioned, this value is required to be pdf.

Any suggestions would be greatly appreciated.

Method:


[HttpGet("{*filePath}")]
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[Produces("Application/pdf")]
public async Task<ActionResult> GetDocument(string fileName) {

    RolesRequiredHttpContextExtensions.ValidateAppRole(HttpContext, _RequiredScopes);

    var memoryStream = new MemoryStream();

    var memoryStream = new MemoryStream();

    using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: true)) {
        stream.CopyTo(memoryStream);
    }
    memoryStream.Seek(offset: 0, SeekOrigin.Begin);

    return new FileStreamResult(memoryStream, "Application/pdf");
}
4 Answers

I just came across the same error and after some investigation I found out that the cause of the exception was indeed in the model binding error. You already wrote about it in your answer, but on closer inspection it became obvious that the reason was not related to binding itself, rather to the response body.

Since you specified [Produces("application/pdf")] the framework assumes this content type is the only possible for this action, but when an exception is thrown, you get application/json containing error description instead.

So to make this work for both "happy path" and exceptions, you could specify multiple response types:

[Produces("application/pdf", "application/json")]
public async Task<ActionResult> GetDocument(string fileName) 
{
...
}

I'am using

public asnyc Task<IActionResult> BuildPDF()
{
    Stream pdfStream = _pdfService.GetData();
    byte[] memoryContent = pdfStream.ToArray();

    return File(memoryContent, "application/pdf");
}

and it works. Could you please try?

The issue was caused by renaming the method parameter and not updating [HttpGet("{*filePath}")] to [HttpGet("{*fileName}")]

I had the same error, it is very confusing in some cases. I got this error after adding new parameter of type int[] to my method forgetting [FromQuery] attribute for it. After adding [FromQuery] attribute error gone.

Related