Веб-API .NET Core 3: [из тела] как привязать свойство абстрактного класса

#c# #.net #asp.net-core #asp.net-core-webapi #asp.net-core-3.1

#c# #.net #asp.net-core #asp.net-core-webapi #asp.net-core-3.1

Вопрос:

У меня есть иерархия классов для запроса модели API:

 public class Human
{
    public string Name { get; set; }
    public byte Age { get; set; }
    public IEnumerable<HumanData> Data { get;  set; }
}

public abstract class HumanData
{
    public Guid Id { get; set; }
    public string Text { get; set; }
    public virtual string Type => GetType().Name;
}

public class HealthData : HumanData
{
    public byte Weight { get; set; }
    public byte Growth { get; set; }
    public string Pressure { get; set; }
}

public class AddressData : HumanData
{
    public string City { get; set; }
    public string Street { get; set; }
    public uint House { get; set; }
    public uint Apartment { get; set; }
}
  

Я создал API для добавления человека:

 [ApiController]
public class HumanController : ControllerBase
{
    ...

    [HttpPost]
    public async Task<IActionResult> Add([FromBody] Human humanRequest)
    {
        //Functionality
    }
}
  

Я вызываю API и передаю модель запроса:

 {
"Name":"Alex",
"Age":30
"Data":[{
    "Id": "10",
    "Text":"Residence address",
    "City":"Elblag",
    "Street":"1 maja",
    "House":"95",
    "Type":"AddressData",
},{
    "Id": "5",
    "Text":"Residence address",
    "Weight":"75",
    "Growth":"179",
    "Pressure":"120/85",
    "Type":"HealthData",
}]}
  

Но модель запроса не извлекается в humanRequest переменной. Причина кроется в Data HumanData иерархии классов полей. Как сделать такую привязку?

Комментарии:

1. Какой сериализатор JSON вы используете?

2. Я использую NewtonsoftJson.

Ответ №1:

Единственный способ получить свою модель, если вы измените свою подпись действия следующим образом

 [HttpPost]
    public async Task<IActionResult> Add([FromBody] JObject humanRequest)
    {

        //Functionality
    }
but you will have untyped Object in this case and you have to read it like this:
var name=humanRequest["Name"].ToString();
  

Гораздо лучший способ, если ваша структура данных будет изменена на что-то вроде этого:

 public class Human
{
   public Guid Id { get; set; }
  
    public string Name { get; set; }
    public byte Age { get; set; }
public Guid AddressId {get;set;}
public Guid HealthId {get;set;}
    public virtual AddressData Address { get;  set; }
 public virtual HealthData Health { get;  set; }
}

public class HealthData
{
public Guid Id {get; set;}
  public string Text { get; set; }
    public byte Weight { get; set; }
    public byte Growth { get; set; }
    public string Pressure { get; set; }
}

public class AddressData 
{
public Guid Id {get; set;}
  public string Text { get; set; }
    public string City { get; set; }
    public string Street { get; set; }
    public uint House { get; set; }
    public uint Apartment { get; set; }
}
  

Ваша модель Json должна выглядеть следующим образом

 {
Id: "0f8fad5b-d9cb-469f-a165-70867728950e"
"Name":"Alex",
"Age":30,
AddressId="0f8fad5b-d9cb-469f-a165-70867728950e",
HealthId="0f8fad5b-d9cb-469f-a165-70867728950d",
"Address":{
    "Id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "Text":"Residence address",
    "City":"Elblag",
    "Street":"1 maja",
    "House":"95",
    "Type":"AddressData"
},
"Health":{
    "Id": "0f8fad5b-d9cb-469f-a165-70867728950d",
    "Text":"Residence address",
    "Weight":"75",
    "Growth":"179",
    "Pressure":"120/85",
    "Type":"HealthData"
}
}
  

Но, честно говоря, я не понимаю, зачем вам нужны 3 таблицы для человека. В большинстве случаев у вас будут индивидуальные отношения. Я бы подумал о том, чтобы объединить все эти 3 таблицы в 1.