skip to Main Content

In process of migrating from .net framework and are struggling with a difference of response serialization.

Everything here seems to indicate that by default a response will go out via the json serializer.
https://learn.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting?view=aspnetcore-5.0 but when returning a simple string value all our endpoints have the content type of "text/plain" so the text isn’t surrounded by quotes.

Given this basic controller:

[ApiController]
[Route("[controller]")]
public class SanityController : ControllerBase
{
    public SanityController()
    {
    }

    [HttpGet0]
    public string Get()
    {
        return "Where are the quotes?";
    }
}

And our Program.cs:

var builder = WebApplication.CreateBuilder(args);

...

// Tried this as well, not sure what the difference even is between this an AddJsonOptions, seemed to work the same.
//builder.Services.Configure<JsonOptions>(options =>
//{
//    options.SerializerOptions.IncludeFields = true;
//    options.SerializerOptions.Converters.Add(new JsonStringEnumConverter());
//    options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
//    options.SerializerOptions.PropertyNameCaseInsensitive = true;
//});

...

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.IncludeFields = true;
        options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
        options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
        options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
    });

...

app.Run();

But the Content-Type returned for all of our endpoints that return strings is just "text/plain". We tried changing the Accept header on our client from
application/json, text/plain, */* to application/json, text/plain;q=0.9, */*;q=0.8 but it would still return text. Only if we only set it to just application/json would it finally return json. But this doesn’t help when hitting it directly from a browser window where it will again just return it as "text/plain".

We also found could also put [Produces("application/json")] on the controller method and that would also work.

But considering 99% of all our endpoints should return JSON with barely a handful returning text or xml, is there not a way to change the aggressive default for a string response to be application/json app wide like it was with asp.net?

2

Answers


  1. You can remove StringOutputFormatter (if needed add it to the end with options.OutputFormatters.Add(new StringOutputFormatter()); after RemoveType call):

    builder.Services.AddControllers(options =>
    {
        options.OutputFormatters.RemoveType<StringOutputFormatter>();
    });
    
    Login or Signup to reply.
  2. String value is a valid JSON, however it is confusing to ASP.Net core and it can’t know if you intended it to be an application/json or a text/plain.
    What you can do in this case, is to specify that you need a application/json in the request levraging content negotation.

    using the Accept to be application/json will make asp.net core return application/json instead of text/plain.

    Postman screenshot
    And the proper header.
    Headers

    Or else if you want to do it in a global manner, you can remove the
    plain/text formatter :

    services.AddControllers(options => options.OutputFormatters.RemoveType<StringOutputFormatter>());
    

    This, of course, will prevent you from never being able to send text/plain back. even if you set the Produces Attribute, or send an Accept header with text/plain.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search