Представьте себе набор сущностей Entity Framework:
public class Country {
public string CountryCode { get; set; }
public string Name { get; set; }
public string Flag { get; set; }
}
public class Market {
public string CountryCode { get; set; }
public virtual Country Country { get; set; }
public int ProductID { get; set; }
public virtual Product Product { get; set; }
}
public class Product {
public int ProductID { get; set; }
public string Name { get; set; }
public virtual ICollection<Market> Markets{ get; set; }
}
Представьте также DOTNET 5 api GET
// GET api/product
[HttpGet]
public async Task<IActionResult> GetProduct([FromRoute] int id)
{
return Ok(await _context.Products
.Include(p => p.Markets)
.SingleAsync(m => m.ProductID == id));
}
Если к объекту не привязаны рынки, данные возвращаются без проблем, но как только у меня есть несколько связанных элементов, я получаю сообщение об ошибке:
Ошибка HTTP 502.3 - Bad Gateway
В указанном приложении CGI произошла ошибка, и сервер завершил процесс.
Я смутно припоминаю предыдущее приложение, в котором каждый сложный объект EF имел объект типа «только примитивы» для отправки и получения этого объекта клиенту и от него, но мне интересно, есть ли способ общаться без промежуточных объектов?
eg:
public class ProductViewModel {
public int ProductID { get; set; }
public string Name { get; set; }
public List<MarketViewModel> Markets{ get; set; }
}
public class MarketViewModel {
public int ProductID { get; set; }
public Country Country { get; set; }
}
Меня беспокоят накладные расходы на кодирование при переводе каждого сложного объекта от клиента туда и обратно (что, признаюсь, я не уверен, что это даже плохо, возможно, это все равно нужно делать).
Поскольку API-интерфейсы с каркасом, похоже, принимают и возвращают объекты напрямую, мне интересно, есть ли способ напрямую обрабатывать сложную часть объекта.
Редактировать №1:
Согласно комментарию Ноэля ниже, если я изменю код, который вызывает ошибку
[HttpGet("{id}", Name = "GetProduct")]
public async Task<IActionResult> GetProduct([FromRoute] int id)
{
Product product = await _context.Products
.Include(t => t.Markets)
.SingleAsync(m => m.ProductID == id);
throw new System.Exception("error sample");
return Ok(product);
}
трассировка стека правильно брошена. Если я удалю исключение, появится ошибка шлюза 500. Я согласен, что это похоже на ошибку сериализации, но трудно сказать.
РЕДАКТИРОВАТЬ 2 — согласно комментарию Олега ниже:
Решение проблем с плохим шлюзом состоит в том, чтобы сначала явно обновить более позднюю версию NewtonSoft.Json
в зависимостях в файле project.json
:
"dependencies": {
"Newtonsoft.Json": "8.0.1-beta3",
затем вы должны изменить файл Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(options => {
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
с этими двумя настройками плохой шлюз больше не возникает, и вызов API успешно возвращает сложный объект, как и ожидалось.
Newtonsoft.Json
в последнюю версию 8.0.1-beta3 явно. Вы можете изучитьpackage.lock.json
, чтобы узнать, какая версия будет загружена автоматическим разрешением зависимостей. См. ошибку, подтверждающую ошибку HTTP 502.3 — Bad Gateway во время сериализации. Можно попробовать установитьNewtonsoft.Json.ReferenceLoopHandling.Ignore;
в конфигурацииSerializerSettings.ReferenceLoopHandling
(см. вопрос). - person Oleg   schedule 16.12.2015