skip to Main Content

Consider the following minimal repro example using the default ASP.NET Core template:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// Content-Type application/json, Body: true
app.MapGet("/True", () => Results.Json(true));

// Content-Type application/json, Body: "string"
app.MapGet("/String", () => Results.Json("string"));

// Content-Type application/json, Body: {"someProperty":"someValue"}
app.MapGet("/Object", () => Results.Json(new { SomeProperty = "someValue" }));


// expected: Content-Type application/json, Body: null
// actual: no Content-Type header, zero-length Body
app.MapGet("/Null", () => Results.Json(null));


app.Run();

As you can see, Results.Json always yields a Content-Type of application/json and a body containing the json-serialized version of the first argument, except in the case of null (which is annoying, because it means I need to treat this special case in my client differently as well).

I know that I can work around this by creating my own version of Results.Json, but I’d like to understand why this happens. After all, the developers of the Results class apparently went the extra mile to implement a special-case logic for null, so they might have had a good reason for doing that (which I don’t understand yet). Unfortunately, the documentation has not been helpful.


Note:

  • I know that I don’t need Results.Json for the first (/True) and the third (/Object) case. I do need it for the second case, because otherwise ASP.NET will return text (Content-Type text/plain) instead of a JSON string, which would mean yet another special case in my client.
  • app.MapGet("/Null2", () => (object?)null); does return the expected result (a JSON-encoded null).

2

Answers


  1. I want to body to contain the JSON literal null

    This can’t be done via Results.Json because it explicitly does nothing for null value – source code.

    You can return null as object:

    app.MapGet("/Null", () => (object?)null);
    

    Or explicitly serialize and return content:

    app.MapGet("/Null", () =>
        Results.Content(JsonSerializer.Serialize<string?>(null), MediaTypeHeaderValue.Parse("application/json")));
    

    As for why – I can only guess here – mine would be "perfromance", maybe there is a case in TechEmpower benchmarks which allows such return, so shortcutting makes sense =)

    Login or Signup to reply.
  2. The only other way I could figure out how to get the null JSON value was using JsonElement:

    var jsonNull = JsonDocument.Parse("null").RootElement;
    
    app.MapGet("/", () => Results.Json(jsonNull));
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search