2

I have a solution that contains a Web API and an MVC Web application.

My API has this entity model, with an abstract parent class and a couple child classes:

public abstract class Person
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

public class Student : Person
{
    public Address Dormitory { get; set; }
    ... additional fields
}

public class Professor : Person
{
    public Schedule OfficeHours { get; set; }
    ... additional fields
}

I have an endpoint to get all Persons:

[HttpGet]
[ProducesResponseType(typeof(IEnumerable<Person>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetPersons()
{
    var persons = await _dbContext.Persons.ToListAsync();

    return Ok(persons);
}

This which works great with Entity Framework, it returns a collection of both Students and Professors, with their properties.

My web application is calling this API. The web project has view models, that are basically the same as the entity models in the API. Here's the method that attempts to call the API and deserialize the results:

public async Task<IEnumerable<PersonViewModel>> GetPersons()
{
    var data = await _apiClient.GetStringAsync(_personsUri);

    var response = JsonConvert.DeserializeObject<IEnumerable<PersonViewModel>>(data);

    return response;
}

The problem is that I can't deserialize to my view model, I get an exception saying:

JsonSerializationException: Could not create an instance of type PersonViewModel. Type is an interface or abstract class and cannot be instantiated.

And if I remove abstract from my PersonViewModel, it only returns those objects, and doesn't contain the properties for Students or properties for Professors.

Is there another way I can do this?

Steven
  • 18,761
  • 70
  • 194
  • 296
  • 3
    You need a custom converter, see the second answer [in this question](https://stackoverflow.com/questions/20995865/deserializing-json-to-abstract-class) for more details. Basically you need to tell the deserializer what concrete type gets the data, and you decide that based on the existence of a field. – Ron Beyer Oct 15 '18 at 02:33
  • 2
    There are already several questions about this including [How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects?](https://stackoverflow.com/q/8030538/3744182), [Deserializing polymorphic json classes without type information using json.net](https://stackoverflow.com/q/19307752/3744182), [Json.net serialize/deserialize derived types?](https://stackoverflow.com/q/8513042/3744182) and [how to deserialize JSON into IEnumerable with Newtonsoft JSON.NET](https://stackoverflow.com/q/6348215/3744182). Do any of those meet you needs? – dbc Oct 15 '18 at 03:33

0 Answers0