Description
Is there an existing issue for this?
- I have searched the existing issues
Is your feature request related to a problem? Please describe the problem.
I'm trying to specify what type the SystemTextJsonOutputFormatter
should serialize, but it's not possible, because it goes out of its way to use the actual type of the value.
Let's consider code like this:
class Parent {}
class Child : Parent {
public string Prop { get; set; }
}
[ApiController]
class Ctrl : ControllerBase {
[HttpGet]
public Parent Get1() {
return new Child();
}
[HttpGet]
public ActionResult<Parent> Get2()
{
return new Child();
}
[HttpGet]
public IActionResult Get3() {
// getting desperate ...
var ok = Ok(new Child());
ok.DeclaredType = typeof(Parent);
return ok;
}
}
In all cases above, the value is serialized as Child
and not Parent
. In fact there seems to be no way to serialize it as Parent
.
This is because of code in SystemTextJsonOutputFormatter
I understand the sentiment. As the comment says, you want to be compatible with NewtonsoftJson at least at the root level. But I think it goes too far and hope that there can be a way added to specify the type for serialization.
I think the comment: "context.ObjectType reflects the declared model type when specified" is inaccurate. In case of simple return type (Parent Get() {}
), the ObjectType
property is in fact set to the runtime type of the instance due to code in OutputResultExecutor
:
Describe the solution you'd like
I understand that there's slim chance you'll change the existing behavior, because it will be a breaking change. But anyway, I'd like the cases where ObjectResult
specifies the DeclaredType
to pass that type to the STJ serializer. That means that in the example code above, second and third cases should serialize the value as Parent
and not Child
.
Additional context
I stumbled upon this problem when analyzing some code that directly returns EF entities out of MVC actions. The entity used virtual property for lazy loading support. The property was decorated with JsonIgnore
attribute, but it didn't work.
The analysis showed that Mvc passes the EF-generated proxy type to STJ and STJ doesn't read inherited attributes (GetCustomAttributes(..., inherit: false)
. The end result is that lazy loaded property was getting serialized while the intention was to ignore it.