Search code examples
c#asp.net-corecontrollerhttp-get.net-7.0

Return Class Derived From Parent Class - ASP.NET CORE Controller


I would like to return an object in a Get-Controller. The class from the object itself derives from a class and it should be possible to return a list with objects from different classes, but derived from the same class.

My problem is that the members of the derived classes are ignored.

Here's my Code:

The father class

namespace FooBar
{
    public class Foo
    {
        public string FooField { get; set; } = "Foo";
    }
}

The deriving classes

namespace FooBar
{
    public class BarOne : Foo
    {
        public string BarOneField { get; set; } = "BarOne";
    }

    public class BarTwo : Foo
    {
        public string BarTwoField { get; set; } = "BarTwo";

    }
}

The Controller

namespace PWManagerService.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class FooController : ControllerBase
    {

        [HttpGet]
        [Route("all")]
        public async Task<ActionResult<List<Foo>>> GetAll()
        {

            List<Foo> fooList = new List<Foo>();

            BarOne barOne = new BarOne();
            BarTwo barTwo = new BarTwo();

            fooList.Add(barOne);
            fooList.Add(barTwo);

            return Ok(fooList);
        }

    }
}

The result:

[
    {
        "fooField": "Foo"
    },
    {
        "fooField": "Foo"
    }
]

The result I'm looking for

[
    {
        "fooField": "Foo",
        "barOneField": "BarOne"

    },
    {
        "fooField": "Foo",
        "barTwoField": "BarTwo"
    }
]

Solution

  • You need to tell the JSON serializer that you're using inherited/derived (polymorphic) types.

    The following example assumes you are using System.Text.Json and not another 3rd party library. Other 3rd party library solutions may differ.

    https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism?pivots=dotnet-7-0

    [JsonDerivedType(typeof(BarOne))]
    [JsonDerivedType(typeof(BarTwo))]
    public class Foo
    {
        public string FooField { get; set; } = "Foo";
    }
    

    That will give you the desired result:

    [
      {
        "BarOneField": "BarOne",
        "FooField": "Foo"
      },
      {
        "BarTwoField": "BarTwo",
        "FooField": "Foo"
      }
    ]