question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

.net 6 aspnet minimal api not using the System.Text.Json source generator?

See original GitHub issue

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

.NET 6 aspnet web project with minimal api

When using the .NET 6.0 System.Text.Json source generator with minimal api, it seems that source generators files (*.g.cs) never used on runtime, on HTTP request-response jobs.

I put a lot of stopping points in the source generators files (*.g.cs), but code execution does not go there.

Expected Behavior

I’m testing the performance of minimal api against System.Text.Json without source generators and with it in the context of web api projects.

I get exactly the same query results per second (RPS) on a simple POST query example. (on running Release mode of course)

I don’t understand how to make the code generated through JsonSerializerContext run.

Calling var json = JsonSerializer.Serialize(new MyJsonDto() { }, MyJsonDtoContext.Default.MyJsonDto); manually, in console app, successfully enters the *.g.cs files on Debug mode. And the benchmark shows an increase in performance in Release mode.

Steps To Reproduce

https://github.com/NYMEZIDE/JsonSourceGeneratorsNotUsed/

using System.Text.Json.Serialization;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.Configure<Microsoft.AspNetCore.Http.Json.JsonOptions>(options =>
{
    options.SerializerOptions.AddContext<MyJsonDtoContext>();
});

//builder.Services.Configure<Microsoft.AspNetCore.Mvc.JsonOptions>(options =>
//{
//    options.JsonSerializerOptions.AddContext<MyJsonDtoContext>();
//});


var app = builder.Build();

app.MapPost("/test", (MyJsonDto dto) =>
{
    return dto;
});

app.Run();



public class MyJsonDto
{
    public int Id { get; set; }

    public string Name { get; set; }
}

[JsonSerializable(typeof(MyJsonDto))]
public partial class MyJsonDtoContext : JsonSerializerContext { }

Exceptions (if any)

No response

.NET Version

6.0.400

Anything else?

.NET SDK (reflecting any global.json): Version: 6.0.400 Commit: 7771abd614

Среда выполнения: OS Name: Windows OS Version: 10.0.22000 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\6.0.400\

global.json file: Not found

Host: Version: 6.0.8 Architecture: x64 Commit: 55fb7ef977

.NET SDKs installed: 2.2.207 [C:\Program Files\dotnet\sdk] 6.0.400 [C:\Program Files\dotnet\sdk]

.NET runtimes installed: Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Download .NET: https://aka.ms/dotnet-download

Learn about .NET Runtimes and SDKs: https://aka.ms/dotnet/runtimes-sdk-info

Issue Analytics

  • State:closed
  • Created 10 months ago
  • Comments:17 (12 by maintainers)

github_iconTop GitHub Comments

1reaction
eerhardtcommented, Nov 15, 2022

and it comes down to the fact that this part of the JSON source generator (the serialization handlers) doesn’t work with encoders

It’s even worse than that, from what I can tell. ASP.NET calls the JsonSerializer.SerializeAsync<TValue>(Stream utf8Json, ...) overload:

https://github.com/dotnet/aspnetcore/blob/ce78832442d91ca307ca8366bafdc9003ea46bc9/src/Http/Http.Extensions/src/HttpResponseJsonExtensions.cs#L143-L151

From inspecting the code in System.Text.Json, this API will never call into the “fast path” / SerializeHandler code. No matter the Options being used.

This is because the WriteStack.SupportContinuation field gets set to true here:

https://github.com/dotnet/runtime/blob/264d7391ec9f6e698051db0621c5e090d0ae4710/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs#L319

And JsonMetadataServicesConverter<T> checks !state.SupportContinuation before calling the SerializeHandler:

https://github.com/dotnet/runtime/blob/264d7391ec9f6e698051db0621c5e090d0ae4710/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs#L67-L78

Repro:

using System;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;

var options = new JsonSerializerOptions(JsonSerializerDefaults.Web)
{
    //Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};

options.AddContext<MyJsonDtoContext>();

Console.WriteLine(JsonSerializer.Serialize(new MyJsonDto(), options)); // calls the "fast path"

Stream body = Console.OpenStandardOutput();
await JsonSerializer.SerializeAsync(body, new MyJsonDto(), options, cancellationToken: default); // doesn't call the "fast path"

public class MyJsonDto
{
    public int Id { get; set; }

    public string Name { get; set; }
}

[JsonSerializable(typeof(MyJsonDto))]
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
public partial class MyJsonDtoContext : JsonSerializerContext { }
Read more comments on GitHub >

github_iconTop Results From Across the Web

Using the .NET JSON Source Generator with ASP.NET Core ...
How to use the new .NET 6 JSON source generator in an application using ASP.NET Core Minimal APIs.
Read more >
Try the new System.Text.Json source generator - .NET Blog
In .NET 6.0, we are shipping a new C# source generator to help improve the performance of applications that use System.Text.Json .
Read more >
Speed Up ASP.NET Core JSON APIs with Source Generators
In this post, we'll see how you can use the latest JSON source generators shipped in .NET 6 to improve your JSON API...
Read more >
System.Text.Json source generation not working
If I just start a new project, using the ASP.NET Core Web API template and add the exact same code it works and...
Read more >
Playing with System.Text.Json Source Generators
In this post, I explore code which uses System.Text.Json source generators to optimise serialisation of types being indexed to ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found