aspnetcore
aspnetcore copied to clipboard
When returning a TypedResult from a controller or minimal API endpoint the configured JsonOptions are not used
Is there an existing issue for this?
- [X] I have searched the existing issues
Describe the bug
When JsonOptions are configured either through AddControllers().AddJsonOptions() or PostConfigure<JsonOptions>, endpoints that return IActionResult respect this configuratrion. Endpoints that return TypedResult do not.
builder.Services.PostConfigure<JsonOptions>(opt =>
opt.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull);
// this works as expected and omits null values from the response
[HttpGet("{thingId}")]
public async Task<IActionResult> GetThing(string thingId, CancellationToken cancellationToken) =>
await handler.Handle(new GetThingRequest(thingId), cancellationToken) switch
{
{ } thing=> new JsonResult(thing),
_ => NotFound()
};
// this does not work, null values are always included
[HttpGet("{thingId}")]
public async Task<Results<Ok<Thing>, NotFound>> GetThing(string thingId, CancellationToken cancellationToken) =>
await handler.Handle(new GetThingRequest(thingId), cancellationToken) switch
{
{ } thing => TypedResults.Ok(thing ),
_ => TypedResults.NotFound()
};
Changing Ok<Thing> to JsonHttpResult<Thing> and passing the DI'd JsonOptions serializer settings does work correctly but this feels cumbersome and defeats the purpose of it being configured globally.
Expected Behavior
I could see the argument that minimal APIs wouldn't use JsonOptions that were configured by chaining off AddControllers because you're not really using the MVC pipeline, but not respecting the options that are configured via PostConfigure is confusing. Having to DI another dependency into your controller or endpoint just to have TypedResult.Json respect what has already been configured also seems odd. I would expect it to simply use what was configured - same goes for TypedResult.Ok when your default serialization is JSON.
Steps To Reproduce
No response
Exceptions (if any)
No response
.NET Version
7.0.101
Anything else?
No response
@MonocleKelso Unfortunately, there are two different JsonOptions
- https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.json.jsonoptions?view=aspnetcore-7.0
- https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.jsonoptions?view=aspnetcore-7.0
TypedResult depends on #1 and I believe you are configuring #2. Could you try add:
builder.Services.ConfigureHttpJsonOptions(opt =>
opt.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull);
@brunolins16 can you file an issue so we can build another API that sets the default in all the different cases?

Thanks @brunolins16 that worked. And yes, @davidfowl I think unfortunate is the right word to use 🤣
@brunolins16 can you file an issue so we can build another API that sets the default in all the different cases?
What if MVC registered an IConfigureOptions<Mvc.JsonOptions> that copies from the extensions JsonOptions?
Thanks for contacting us.
We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.
Triage: Need to investigate if the proposal here is a viable approach.
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
The code provided by @brunolins16 also helped when I needed to use a custom converter in minimal API. In my case I have this endpoint:
app.MapPatch("/{id}", async Task<Results<Ok, NotFound>> (ICarService carService, Guid id, IDictionary<string, object?> changes)
and I wanted to get real values and not JsonElements (which is weird IMO) After creating a custom converter and registering it using the provided code in the Program.cs everything works fine.
Maybe info about custom converters should be added here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/parameter-binding?view=aspnetcore-7.0#configure-json-deserialization-options-globally?
@Misiu Would linking to the official docs be helpful here?