AspNetCore Accept text/plain as applicatoin/json

We developed a REST API long time ago and recently found that the released client has a flaw: the HttpRequestMessage is missing content-type application/json. In earlier version we manually deserialize the request json by reading the request body but now we leverage AspNetCore framework to automatically get the request structure from the API parameter. However, the legacy client will not work: HTTP 415 "Unsupported Media Type" error happens.

Therefore, for backward compatibility, we need to make the server treat all coming requests as application/json even it is a plain text (by default).

The legacy client:

msg.Content = new StringContent(JsonConvert.SerializeObject(request));

It should be:

msg.Content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");

First, I try to force modify the request content-type to applicatoin/json. However, there is no elegant way to do this.

Then I explore 3 methods to support text/plain content-type:

  1. [Consumes()] annotation above Controller class. (not work) This method doesn't work as consumes annotation only restricts the request content-type, but not regard the request as application/json. In other words, if you specify text/plain in consumes annotation, although the action treat it as a valid type, it will not properly deserialize it to json. 415 error still exists.

  2. Reading request body and parsing as json yourself. https://weblog.west-wind.com/posts/2017/Sep/14/Accepting-Raw-Request-Body-Content-in-ASPNET-Core-API-Controllers?Page=2 This method works, but not what we want: we just deprecated manually deserializing object method and resort to leverage AspNetCore framework to do so.

  3. Add text/plain to SupportedMediaTypes. (RECOMMENDED) Open your aspnetcore Startup.cs, add following snippet to ConfigureServices:

    public void ConfigureServices(IServiceCollection services)
    {
        ...
        
        services.AddMvc(config =>
            {
                foreach (var formatter in config.InputFormatters)
                {
                    if (formatter.GetType() == typeof(JsonInputFormatter))
                    {
                        ((JsonInputFormatter) formatter).SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/plain"));
                    }
                }
            });
    
        ...
    }
    Now the server can handle both text/plain and application/json, treating request body as json format.

# Default input formatter in ASP.NET Core 2