In my web API when I run project to get data from the database got this error .net core 3.1
JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32.
These are my codes:
my Model
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string ProductText { get; set; }
public int ProductCategoryId { get; set; }
[JsonIgnore]
public virtual ProductCategory ProductCategory { get; set; }
}
my productCategory class is:
public class ProductCategory
{
public int Id { get; set; }
public string Name { get; set; }
public string CatText { get; set; }
public string ImagePath { get; set; }
public int Priority { get; set; }
public int Viewd { get; set; }
public string Description { get; set; }
public bool Active { get; set; }
public DateTime CreateDate { get; set; }
public DateTime ModifyDate { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
my repo is
public async Task<IList<Product>> GetAllProductAsync()
{
return await _context.Products.Include(p => p.ProductCategory).ToListAsync();
}
my interface
public interface IProductRepository
{
...
Task<IList<Product>> GetAllProductAsync();
...
}
and this is my controller in api project
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
private readonly IProductRepository _productRepository;
public ProductsController(IProductRepository productRepository)
{
_productRepository = productRepository;
}
[HttpGet]
public ActionResult Get()
{
return Ok(_productRepository.GetAllProduct());
}
}
When I run API project and put this URL: https://localhost:44397/api/products I got that error, I can't resolve it
this is happening because your data have a reference loop.
e.g
// this example creates a reference loop var p = new Product() { ProductCategory = new ProductCategory() { products = new List<Product>() } }; p.ProductCategory.products.Add(p); // <- this create the loop var x = JsonSerializer.Serialize(p); // A possible object cycle was detected ...
You can not handle the reference loop situation in the new System.Text.Json
yet (netcore 3.1.1) unless you completely ignore a reference and its not a good idea always. (using [JsonIgnore]
attribute)
but you have two options to fix this.
you can use Newtonsoft.Json
in your project instead of System.Text.Json
(i linked an article for you)
Download the System.Text.Json
preview package version 5.0.0-alpha.1.20071.1
from dotnet5 gallery (through Visual Studio's NuGet client):
option 1 usage:
services.AddMvc() .AddNewtonsoftJson( options => { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); // if you not using .AddMvc use these methods instead //services.AddControllers().AddNewtonsoftJson(...); //services.AddControllersWithViews().AddNewtonsoftJson(...); //services.AddRazorPages().AddNewtonsoftJson(...);
option 2 usage:
// for manual serializer var options = new JsonSerializerOptions { ReferenceHandling = ReferenceHandling.Preserve }; string json = JsonSerializer.Serialize(objectWithLoops, options); // ----------------------------------------- // for asp.net core 3.1 (globaly) services.AddMvc() .AddJsonOptions(o => { o.JsonSerializerOptions .ReferenceHandling = ReferenceHandling.Preserve });
these serializers have ReferenceLoopHandling
feature.
ReferenceHandling
changed to ReferenceHandler
in DotNet 5but if you decide to just ignore one reference use [JsonIgnore]
on one of these properties. but it causes null result on your API response for that field even when you don't have a reference loop.
public class Product { public int Id { get; set; } public string Name { get; set; } public string ProductText { get; set; } public int ProductCategoryId { get; set; } // [JsonIgnore] HERE or public virtual ProductCategory ProductCategory { get; set; } } public class ProductCategory { public int Id { get; set; } // [JsonIgnore] or HERE public ICollection<Product> products {get;set;} }
I have the same issue, my fix was to add async and await keyword since I am calling an async method on my business logic.
Here is my original code:
[HttpGet] public IActionResult Get() { //This is async method and I am not using await and async feature .NET which triggers the error var results = _repository.GetAllDataAsync(); return Ok(results); }
To this one:
HttpGet] public async Task<IActionResult> Get() { var results = await _repository.GetAllDataAsync(); return Ok(results); }
.NET 5 Web API
public static void ConfigureServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddControllers()
.AddJsonOptions(o => o.JsonSerializerOptions
.ReferenceHandler = ReferenceHandler.Preserve);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With