Чтобы избежать этой проблемы, в каждом проекте я всегда использую DTO и Automapper. Как правило, никогда не нужно возвращать модель базы данных такой, какая она есть: дать только то, что вам нужно для решения функциональности. В вашем случае вам нужно вернуть все глоссарии.
В вашей ситуации я бы представил Automapper. После установки Automapper на ваш проект Net .Core, я бы создал 2 DTO с именем:
public class GlossaryDto : ICustomMapping
public Guid GlossaryId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ICollection<ItemDto> Items { get; set; }
public void CreateMappings(Profile configuration)
{
configuration.CreateMap<Glossary, GlossaryDto>();
}
public class ItemDto : ICustomMapping
{
public Guid ItemId { get; set; }
public string Name { get; set; }
public string Definition { get; set; }
public Guid GlossaryId { get; set; }
public void CreateMappings(Profile configuration)
{
configuration.CreateMap<Item, ItemDto>();
}
}
Теперь вы можете просто переписать свой Get, чтобы вернуть Dto вместо модель базы данных (сущность):
public async Task<IEnumerable<GlossaryDto>> Get()
{
var result = await _context.Glossaries
.Include(x => x.Items)
.OrderBy(x => x.CreatedAt)
.ToListAsync()
return await mapper.Map<IEnumerable<GlossaryDto>(result);
}
Таким образом, мы удалили циклическую ссылку из Dto, и у вас не возникло бы никаких проблем: поскольку ItemDto не имеет свойства "navigation" для GlossaryD, цепочка была правильно закрыто. Ваш JSON обладает всей необходимой информацией. В будущем, если вам нужно вернуть и ItemDto со свойством навигации GlossaryDto, создайте новое с другим именем. Вы также можете создать DTO, равный Model базы данных, а затем «вырезать» циклические ссылки с помощью автоматического преобразователя, указав MaxDepth () , но я предпочитаю создавать конкретные c DTO для того, что действительно необходимо.