Content Negotiation Between Browser and ASP.NET Core
Problem Statement
The ASP.NET Core Server sends a response in text/plain format even when the browser requests putting application/json at a higher priority in the Accept header.
The Accept header sent by the browser is Accept: application/json, text/plain, */*.
The action method is defined as follows:
[HttpGet("data")]public IActionResult GetData(){ var data = "Hello, World!"; return Ok(data);}Analysis
This is the default behavior description of ASP.NET Core when it detects that the request is coming from a web browser. 1
Unlike typical API clients, web browsers supply Accept headers. Web browsers specify many formats, including wildcards.
By default, when the framework detects that the request is coming from a browser:
- The Accept header is ignored.
- The content is returned in JSON, unless otherwise configured.
This approach provides a more consistent experience across browsers when consuming APIs.
According to the above description, the response content should be in JSON format. However, in practice, the response is in text/plain format.
Why does this happen?
Because the second bullet point is not entirely accurate. The actual framework behavior is to select the first registered output formatter that can handle the response type.
In this case, the response type is string, and the first registered output formatter that can handle string is the StringOutputFormatter, which produces text/plain responses. 2
Solution
Since the issue is due to the accept header being ignored for browser requests, we can configure the framework to respect the Accept header even for browser requests by setting the RespectBrowserAcceptHeader option to true.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>{ options.RespectBrowserAcceptHeader = true;});