Ответ API формата 2 .net с глубокими свойствами - PullRequest
0 голосов
/ 17 декабря 2018

Я создаю приложение, которое состоит только из API, использующего .net core 2.1.

У меня есть родительский класс (Dad), которому принадлежит только один ребенок (Kid).Я ищу наиболее эффективный способ отформатировать JSON-ответ моего контроллера;для разработчиков, которые будут интегрировать мой API в свои приложения.

public class Dad
{
    public long Id{get;set;}
    public string Name{get;set;}
    public Kid OnlyChild {get;set;}
}

public class Kid
{
    public long Id{get;set;}
    public string FirstName{get;set;}
    public string LastName{get;set;}
    public string Useless{get;set;}
}

В настоящее время я делаю что-то подобное в контроллере:

[HttpGet("{id}")]
public async Task<IActionResult> GetDad([FromRoute] long id)
{
    dynamic DadResponse = _context.Dads
        .Where(o => o.Id == id)
        .AsNoTracking()
        .Select(p => new
        {
            Dad = p.Name, 
            Kid = string.Format("{0} {1}", p.Kid.FirstName, p.Kid.LastName)
        }).FirstOrDefault();

    return Ok(DadResponse);
}

Преимущество этого подхода заключается в следующем:

  1. результирующий объект DadResponse имеет формат, который я хочу для моего API.
  2. результирующий запрос MySQL, сгенерированный EF Core, будет оптимизирован и будет выбран только Dad.Name, Kid.FirstName и Kid.LastName.

Недостатком является то, что если значение Kid равно нулю, оно сгенерирует исключение.

Как лучше всего обойти это;возможно я использую неправильный подход все вместе.Я пытался использовать атрибуты JsonIgnore в своих моделях, но каждый из моих контроллеров мог бы возвращать немного разные свойства (например, GET / Kids будет возвращать всех детей с их идентификатором, тогда как GET / Dads может возвращать только формат, описанный выше).

Обновление: В идеале я бы хотел, чтобы Kid возвращал нулевое значение, если у папы нет Kid, но я не могу сделать что-то вроде этого:

Kid = (Kid == null ? null : string.Format("{0} {1}", p.Kid.FirstName, p.Kid.LastName))

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

    dynamic DadResponse = _context.Dads
        .Where(o => o.Id == id)
        .AsNoTracking()
        .Select(p => new
        {
            Dad = p.Name, 
            Kid = p.Kid
        }).FirstOrDefault();


        DadResponse.Kid = (DadResponse.Kid == null ? null : string.Format("{0} {1}", DadResponse.Kid.Firstname, DadResponse.Kid.Lastname);

    return Ok(DadResponse);

Но это вызывает другое исключение.

1 Ответ

0 голосов
/ 17 декабря 2018

Ваш запрос является EF-запросом, который будет переведен в SQL.Нулевое распространение не может быть переведено, поэтому вы получаете эту ошибку.

У вас нет для форматирования строки в запросе EF, однако вы можете загрузить нужные данные и использовать другой запрос LINQ to Objects, чтобы отобразить их в окончательной форме.Если вы загружаете только один объект, вы можете вернуть новый анонимный тип:

Например:

var data = _context.Dads
                  .AsNoTracking()
                  .Where(o => o.Id == id)        
                  .Select(p => new {
                          Dad = p.Name, 
                          Kid = new {p.Kid?.FirstName, p.Kid?.LastName}
                       })
                  .FirstOrDefault();
var dadResponse = new {
                          data.Dad,
                          Kid= $"{data.Kid.FirstName} {data.Kid.LastName}"
                      };
return Ok(dadResponse);

Если вы не хотите вернуть *Элемент 1012 * вообще, вы можете просто опустить его из результата:

if (data.Kid.FirstName==null && data.Kid.LastName==null)
{
    return Ok(new {Dad=data.Dad});
}
else 
{
    ...
}

Конечно, кто-то может сказать, что, поскольку нам не важно свойство Kid, мы можем просто вернуть KidFirstNameи KidLastName как отдельные свойства, что делает код немного проще:

var data = _context.Dads
                  .AsNoTracking()
                  .Where(o => o.Id == id)        
                  .Select(p => new {
                          Dad = p.Name, 
                          KidFirstName = p.Kid?.FirstName
                          KidLastName =  p.Kid?.LastName
                       })
                  .FirstOrDefault();

if (data.KidFirstName==null && data.KidLastName==null)
{
    return Ok(new {data.Dad});
}
else 
{
    return Ok(new {data.Dad,Kid=$"{data.KidFirstName} {data.KidLastName}");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...