Я получаю эту ошибку, когда пытаюсь запросить этот контроллер
Сообщение об ошибке
JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles. Path: $.speciality.Doctor.speciality.Doctor.speciality.Doctor.speciality.Doctor.speciality.Doctor.speciality.Doctor.speciality.Doctor.speciality.Doctor.speciality.Doctor.speciality.Doctor.Id.
Контроллер
public IActionResult List(int id)
{
var doc = _context.Doctors.Include(t => t.speciality).ToList();
return Json(doc);
}
Вот dataContext и модели
public class AppDbContext: DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
public DbSet<Doctor> Doctors { get; set; }
public DbSet<Speciality> Specialities { get; set; }
}
public class Doctor
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public int SpecialityId { get; set; }
public Speciality speciality { get; set; }
}
public class Speciality
{
public int SpecialityId { get; set; }
public string SpecialityName { get; set; }
public ICollection<Doctor> Doctor { get; set; }
}
Я попробовал использовать Async и сначала ждал, и он выдал ту же ошибку Я установил Microsoft.AspNetCore.Mvc.NewtonsoftJson и все равно получаю эту ошибку
Корень проблемы здесь в том, что вы используете тип сущности Entity Framework (class Doctor
) в качестве DTO JSON/веб-сервиса, а это означает, что ваш сериализатор JSON будет проходить через все ваши навигационные свойства EF, потенциально вызывая ленивый подход. загрузка до бесконечности, а также застревание в ссылочных циклах. По этой причине (и по многим другим причинам) не следует использовать типы сущностей EF в качестве DTO JSON. Вместо этого определите типы DTO отдельно (да, это утомительно) и используйте методы сопоставления (или используйте AutoMapper) для маршалирования между ними.
Хорошо, я попробую это, спасибо.
Проблема, с которой вы столкнулись, связана с циклической ссылкой между сущностями Doctor
и Speciality
. При попытке преобразовать эти данные в JSON
сериализатор застревает в бесконечном цикле, поскольку каждый Doctor
ссылается на Speciality
, который, в свою очередь, ссылается на Doctor
и так далее.
Чтобы это исправить, вы можете использовать опцию ReferenceHandler
.Preserve с JsonSerializerOptions для обработки ссылочных циклов. Этот подход позволит сохранить ссылки на объекты и обрабатывать циклы во время сериализации.
Обновите действие контроллера, чтобы использовать JsonSerializer
с ReferenceHandler.Preserve
. Вот как вы можете изменить действие контроллера:
public IActionResult List(int id)
{
var doc = _context.Doctors.Include(t => t.speciality).ToList();
var options = new JsonSerializerOptions
{
ReferenceHandler = ReferenceHandler.Preserve,
WriteIndented = true
};
var json = JsonSerializer.Serialize(doc, options);
return Content(json, "application/json");
}
Также лучше использовать метод Json
, предоставляемый ASP.NET Core. Вы можете настроить параметры JSON для всего приложения в Startup.cs
следующим образом:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
options.JsonSerializerOptions.WriteIndented = true;
});
// Other service configurations
}
Тогда исходное действие контроллера может остаться неизменным.
При таком подходе параметры сериализации JSON настраиваются глобально, поэтому любая сериализация JSON в вашем приложении будет использовать эти параметры по умолчанию.
Доктор относится к специальности, которая относится к (многим) докторам. Вы должны разорвать этот круг.