Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASP.NET Core Web API (Native AOT) project fail to serialize the object to JSON #59659

Closed
1 task done
Scythemen opened this issue Dec 30, 2024 · 3 comments
Closed
1 task done
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates

Comments

@Scythemen
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Environment:
Visual Studio Community 2022 17.12.3
Win10 + .NET SDK 8

I created an ASP.NET Core Web API (Native AOT) project in Visual Studio using .NET 8. The minimal API endpoints below worked as expected:

using System.Text.Json.Serialization;

namespace WebApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateSlimBuilder(args);

            builder.Services.ConfigureHttpJsonOptions(options =>
            {
                options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
            });

            var app = builder.Build();

            var sampleTodos = new Todo[] {
                new(1, "Walk the dog"),
                new(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),
                new(3, "Do the laundry", DateOnly.FromDateTime(DateTime.Now.AddDays(1))),
                new(4, "Clean the bathroom"),
                new(5, "Clean the car", DateOnly.FromDateTime(DateTime.Now.AddDays(2)))
            };

            var todosApi = app.MapGroup("/todos");
            todosApi.MapGet("/", () => sampleTodos);
            todosApi.MapGet("/{id}", (int id) =>
                sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
                    ? Results.Ok(todo)
                    : Results.NotFound());

            app.Run();
        }
    }

    public record Todo(int Id, string? Title, DateOnly? DueBy = null, bool IsComplete = false);

    [JsonSerializable(typeof(Todo[]))]
    internal partial class AppJsonSerializerContext : JsonSerializerContext
    {

    }
}

After moving the endpoints to TodosController.cs and configuring the JSON serializer in a separate file JsonTypeMetaData.cs, I encountered the following exception:

NotSupportedException: JsonTypeInfo metadata for type 'WebApplication1.Todo[]' was not provided by TypeInfoResolver of type '[]'. 
If using source generation, ensure that all root types passed to the serializer have been annotated with 'JsonSerializableAttribute', along with any types that might be serialized polymorphically.

TodosController.cs:

// TodosController.cs
using Microsoft.AspNetCore.Mvc;

namespace WebApplication1.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class TodosController : ControllerBase
    {
        private static readonly Todo[] sampleTodos = new Todo[] {
            new(1, "Walk the dog"),
            new(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),
            new(3, "Do the laundry", DateOnly.FromDateTime(DateTime.Now.AddDays(1))),
            new(4, "Clean the bathroom"),
            new(5, "Clean the car", DateOnly.FromDateTime(DateTime.Now.AddDays(2)))
        };

        [HttpGet]
        public IActionResult GetTodos()
        {
            return Ok(sampleTodos);
        }

        [HttpGet("{id}")]
        public IActionResult GetTodoById(int id)
        {
            var todo = sampleTodos.FirstOrDefault(a => a.Id == id);
            return todo is not null ? Ok(todo) : NotFound();
        }
    }
}

JsonTypeMetaData.cs:

// JsonTypeMetaData.cs

using System.Text.Json;
using System.Text.Json.Serialization;

namespace WebApplication1
{
    public static class JsonTypeMetaData
    {
        public static void ConfigureJsonTypeMetaDatas(this IServiceCollection services)
        {
            services.ConfigureHttpJsonOptions(options =>
            {
                options.SerializerOptions.TypeInfoResolverChain.Insert(0, TodoJsonSerializerContext.Default);
            });
        }
    }


    public record Todo(int Id, string? Title, DateOnly? DueBy = null, bool IsComplete = false);

    [JsonSerializable(typeof(Todo[]))]
    internal partial class TodoJsonSerializerContext : JsonSerializerContext
    {
    }

}

Program.cs:

namespace WebApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateSlimBuilder(args);

            builder.Services.ConfigureJsonTypeMetaDatas();   //   JsonTypeMetaData.cs

            builder.Services.AddControllers();

            var app = builder.Build();

            app.MapControllers();

            app.Run();
        }
    }

}

WebApplication.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <InvariantGlobalization>true</InvariantGlobalization>
    <PublishAot>true</PublishAot>
  </PropertyGroup>

</Project>

I tried a similar solution (#59128), but it didn't work for me. Any help would be greatly appreciated.

Expected Behavior

No response

Steps To Reproduce

The mini project:
WebApplication1.zip

Exceptions (if any)

No response

.NET Version

dotnet 8.0.404

Anything else?

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-web-frameworks *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels label Dec 30, 2024
@martincostello
Copy link
Member

ConfigureHttpJsonOptions is only for Minimal APIs. For MVC you need to configure the Microsoft.AspNetCore.Mvc.JsonOptions class instead:

services.AddMvc().AddJsonOptions(...)

@martincostello martincostello added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates and removed NativeAOT area-web-frameworks *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels labels Dec 30, 2024
@martincostello
Copy link
Member

Also note that MVC does not support native AOT.

@Scythemen
Copy link
Author

Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates
Projects
None yet
Development

No branches or pull requests

2 participants