Skip to content

JSON polymorphic serialization does not add $type to single controller results #45548

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

Closed
1 task done
fabsenet opened this issue Dec 12, 2022 · 2 comments
Closed
1 task done
Labels
old-area-web-frameworks-do-not-use *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels

Comments

@fabsenet
Copy link

fabsenet commented Dec 12, 2022

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

dotnet/runtime#77044 added polymorphic serialization support to System.Text.Json and using it inside MVC controllers to return JSON with $type properties works in List<> cases but not if a single item is returned.

What I think happens under the covers after the controller action:

var json = JsonSerializer.Serialize<DerivedModel>(derivedModel); //will not write $type

what should happen:

var json = JsonSerializer.Serialize<BaseModel>(derivedModel); //will write $type !!!

Expected Behavior

$type gets written to the output in all cases if [JsonPolymorphic] is present.

Steps To Reproduce

dotnet new mvc -n JsonTypeMissingRepro

add controller file:

using Microsoft.AspNetCore.Mvc;
using System.Text.Json.Serialization;

namespace JsonTypeMissingRepro.Controllers
{
    [JsonPolymorphic]
    [JsonDerivedType(typeof(DerivedModel), nameof(DerivedModel))]
    [JsonDerivedType(typeof(DerivedDerivedModel), nameof(DerivedDerivedModel))]
    public abstract record BaseModel
    {
        public required string Hello { get; init; }
    }

    public record DerivedModel : BaseModel
    {
        public required string World { get; init; }
    }


    public record DerivedDerivedModel : DerivedModel
    {
        public string? Foo { get; init; }
    }

    [ApiController]
    [Route("api/[controller]")]
    [Produces("application/json")]
    public class ReproController : Controller
    {
        [HttpGet]
        [Route("GetAll")]
        public ActionResult<IList<BaseModel>> GetAll()
        {
            return Ok(new List<BaseModel>() { new DerivedModel { Hello = "Hello1", World = "World2" } });
            // [{"$type":"DerivedModel","world":"World2","hello":"Hello1"}]
        }

        [HttpGet]
        [Route("GetOne")]
        public ActionResult<BaseModel> GetOne()
        {
            return Ok(new DerivedModel { Hello = "Hello1", World = "World2" });
            // {"world":"World2","hello":"Hello1"}
            // ^^^^^^ No $type!!!
        }
    }
}

Call /api/Repro/GetOne and compare it to /api/Repro/GetAll. You will see a missing $type property.

Exceptions (if any)

No response

.NET Version

7.0.100

Anything else?

.NET SDK:
Version: 7.0.100
Commit: e12b7af219

Runtime Environment:
OS Name: Windows
OS Version: 10.0.19045
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\7.0.100\

Host:
Version: 7.0.0
Architecture: x64
Commit: d099f075e4

.NET SDKs installed:
3.1.425 [C:\Program Files\dotnet\sdk]
5.0.407 [C:\Program Files\dotnet\sdk]
5.0.408 [C:\Program Files\dotnet\sdk]
5.0.414 [C:\Program Files\dotnet\sdk]
7.0.100 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.25 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.31 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.16 [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.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.25 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.31 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.16 [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.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.24 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.25 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.31 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.16 [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.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.11 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
Not set

global.json file:
Not found

@fabsenet fabsenet changed the title JSON polymorphic serialization does not add $type single controller results JSON polymorphic serialization does not add $type to single controller results Dec 12, 2022
@fabsenet
Copy link
Author

using this workaround for now: dotnet/runtime#77532

@javiercn javiercn added the old-area-web-frameworks-do-not-use *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels label Dec 12, 2022
@brunolins16
Copy link
Member

@fabsenet Duplicate of # #44852 and we are working on a fix for this #45405

@brunolins16 brunolins16 closed this as not planned Won't fix, can't repro, duplicate, stale Dec 13, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Jan 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
old-area-web-frameworks-do-not-use *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels
Projects
None yet
Development

No branches or pull requests

3 participants