C
C#5w ago
Joschi

✅ MVC and [JsonPolymorphic] response

I'm trying to return a JsonPolymorphic object from an MVC endpoint, but the JSON Serializer seems to omit the $type metadata field which is required to serialize the type. When directly using the JsonSerializer the $type field is present as expected. There is a long git issue for the runtime regarding this behavior https://github.com/dotnet/runtime/issues/77532 and over at aspnetcore https://github.com/dotnet/aspnetcore/pull/46008 as well. Both are marked as completed and as far as I understand them this should work (It works in Minimal APIs, but not in MVC Controllers).
Expected
{"$type":"devived","lastName":null,"name":null}

Actual
{"lastName":null,"name":null}
Expected
{"$type":"devived","lastName":null,"name":null}

Actual
{"lastName":null,"name":null}
c#
[JsonPolymorphic]
[JsonDerivedType(typeof(Derived), "devived")]
public abstract class Parent
{
public string Name { get; set; }
}

public sealed class Derived : Parent
{
public string LastName { get; set; }
}


[HttpGet]
public IActionResult Get()
{
Parent response = new Derived();
return Ok(response); // No discriminator in response JSON
}

[HttpGet]
public IActionResult JsonResponse()
{
Parent response = new Derived();
return Json(response); // Also no discriminator
}

[HttpGet]
public IActionResult Manual()
{
Parent response = new Derived();
var json = JsonSerializer.Serialize(response, JsonSerializerOptions.Web);
return Ok(json); // This works as expected and adds the disciminator
}
c#
[JsonPolymorphic]
[JsonDerivedType(typeof(Derived), "devived")]
public abstract class Parent
{
public string Name { get; set; }
}

public sealed class Derived : Parent
{
public string LastName { get; set; }
}


[HttpGet]
public IActionResult Get()
{
Parent response = new Derived();
return Ok(response); // No discriminator in response JSON
}

[HttpGet]
public IActionResult JsonResponse()
{
Parent response = new Derived();
return Json(response); // Also no discriminator
}

[HttpGet]
public IActionResult Manual()
{
Parent response = new Derived();
var json = JsonSerializer.Serialize(response, JsonSerializerOptions.Web);
return Ok(json); // This works as expected and adds the disciminator
}
I seem to be missing or misunderstanding something in the mentioned git issues. But is there a way to make this with in MVC without having to use the JsonSerializer directly?
GitHub
System.Text.Json Polymorphic Type Resolving Issue · Issue #77532 ...
Description hi there, as discussed in #dotnet/aspnetcore/issues/41399 SystemTextJsonOutputFormatter calls serializer with derived type of the object and this seems reasonable (as per the comment in...
GitHub
Adding STJ Polymorphism to Result Types by brunolins16 · Pull Requ...
Fixes #44852 This PR enables support System.Text.Json polymorphism configuration (eg.: JsonDerivedAttribute) by calling the S.T.J.GetTypeInfo APIs to check if the declared type is polymorphic safe ...
2 Replies
Unknown User
Unknown User5w ago
Message Not Public
Sign In & Join Server To View
Joschi
JoschiOP5w ago
Ohh you are correct. I tried returning the type directly like this
c#
[HttpGet("action")]
public Parent GetParent()
{
Parent response = new Derived()
{
LastName = "World",
Name = "Hello"
};
return response;
}
c#
[HttpGet("action")]
public Parent GetParent()
{
Parent response = new Derived()
{
LastName = "World",
Name = "Hello"
};
return response;
}
But I somehow missed to try
c#
[HttpGet("typed-result")]
public Ok<Parent> Typed()
{
Parent response = new Derived();
return TypedResults.Ok(response);
}
c#
[HttpGet("typed-result")]
public Ok<Parent> Typed()
{
Parent response = new Derived();
return TypedResults.Ok(response);
}
which works. For some reason I always assumed that the typed results are specific to minimal APIs.

Did you find this page helpful?