Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect content negotiation after configuring a custom output formatter #5653

Closed
f2bo opened this issue Feb 16, 2020 · 2 comments
Closed

Comments

@f2bo
Copy link

f2bo commented Feb 16, 2020

By default, the runtime handles requests without an explicit Accept header by returning a JSON formatted response. However, it seems that after configuring a custom output formatter, it replaces this default so that every request that doesn't specify a format uses the custom format.

Moreover, it appears that the runtime chooses the formatter based on its data type instead of the supported media types that the formatter declares. For example, if the custom formatter derives from JsonOutputFormatter, it also replaces the standard JSON formatter for any requests that explicitly specify a JSON response, even if the supported media types of the custom formatter do not include "application/json".

Neither of the two behaviors described above match the current behavior in ASP.NET Core applications.

For example, the code below registers a formatter for the "application/xxx" media type. After including this code, any requests that do not explicitly request a format are handled by the custom formatter.

public class MyCustomOutputFormatter : TextOutputFormatter
{
    public MyCustomOutputFormatter()
    {
        this.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/xxx"));
        this.SupportedEncodings.Add(Encoding.UTF8);
        this.SupportedEncodings.Add(Encoding.Unicode);
    }

    public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
    {
        await context.HttpContext.Response.WriteAsync("This is my custom formatter");
    }
}

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        services.AddMvcCore(config =>
        {
            config.OutputFormatters.Add(new MyCustomOutputFormatter());
        });
    }
}

In fact, when multiple custom formatters are added, the default formatter becomes the first one that was registered. So a workaround seems to be to register JsonOutputFormatter as the first one, though I'm not sure whether that could result in problems elsewhere given that, presumably, the runtime will also register it.

When the custom formatter is changed to derive from JsonOutputFormatter instead of TextOutputFormatter, as shown below, it will start handling all JSON requests despite it clearing the SupportedMediaTypes list and specifying "application/xxx" only.

public class MyCustomJsonOutputFormatter : JsonOutputFormatter
{
    public MyCustomJsonOutputFormatter(JsonSerializerSettings settings)
        : base(new JsonSerializerSettings(), ArrayPool<char>.Create())
    {
        this.SupportedMediaTypes.Clear();
        this.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/xxx"));
    }

    public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
    {
        var response = context.HttpContext.Response;
        var buffer = Encoding.UTF8.GetBytes("This is a JSON derived custom formatter");
        response.Body.WriteAsync(buffer, 0, buffer.Length);
    }
}
@ghost ghost assigned madelinegordon Feb 16, 2020
@v-anvari v-anvari self-assigned this Dec 30, 2020
@v-anvari
Copy link

Hi @f2bo , Apologies for the delayed response. Were you able to find a solution here. Kindly let us know if you are you still facing this challenge? If yes, then please provide us repro steps so as to clone the issue.

@ghost
Copy link

ghost commented Jan 9, 2021

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

@ghost ghost closed this as completed Jan 12, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Feb 11, 2021
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants