Dans mon API Web, lorsque je lance un projet pour obtenir des données de la base de données, cette erreur .net core 3.1
JsonException: un cycle d'objet possible a été détecté et n'est pas pris en charge. Cela peut être dû à un cycle ou si la profondeur de l'objet est supérieure à la profondeur maximale autorisée de 32.
Voici mon code mon modèle
[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()); } }
ma classe productCategory est:
public interface IProductRepository { ... Task<IList<Product>> GetAllProductAsync(); ... }
mon dépôt est
public async Task<IList<Product>> GetAllProductAsync() { return await _context.Products.Include(p => p.ProductCategory).ToListAsync(); }
mon interface
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; } }
et ceci est mon contrôleur dans le projet api
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; } }
Lorsque je lance un projet api et que je mets cette URL: https: // localhost: 44397 / api / products, j'ai eu cette erreur, je ne peux pas la résoudre
5 Réponses :
Assurez-vous d'avoir [JsonIgnore] sur les bons champs pour éviter une référence circulaire.
Dans ce cas, vous aurez besoin
public class Product { public int Id { get; set; } public string Name { get; set; } public string ProductText { get; set; } [JsonIgnore] public virtual ProductCategory ProductCategory { get; set; } }
Vous n'avez probablement pas besoin du champ ProductCategoryId (dépend si vous utilisez d'abord EF et code pour définir votre base de données)
Je fais cela et supprime ProductId mais l'erreur existe toujours.Essayez également l'option set dans les services.AddControllers () mais ne fonctionne pas
cela se produit parce que vos données ont une boucle de référence.
par exemple
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;} }
Vous ne pouvez pas encore gérer la situation de boucle de référence dans le nouveau System.Text.Json
(netcore 3.1.1) sauf si vous ignorez complètement une référence et ce n'est pas toujours une bonne idée. (en utilisant l'attribut [JsonIgnore]
)
mais vous avez deux options pour résoudre ce problème.
vous pouvez utiliser Newtonsoft.Json
dans votre projet au lieu de System.Text.Json
(j'ai lié un article pour vous)
Téléchargez le package d'aperçu System.Text.Json
version 5.0.0-alpha.1.20071.1
partir de la galerie dotnet5 (via le client NuGet de Visual Studio):
utilisation de l'option 1:
// 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 });
utilisation de l'option 2:
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(...);
ces sérialiseurs ont la fonction ReferenceLoopHandling
.
mais si vous décidez d'ignorer simplement une référence, utilisez [JsonIgnore]
sur l'une de ces propriétés. mais cela provoque un résultat nul sur votre réponse API pour ce champ même si vous n'avez pas de boucle de référence.
// 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 ...
À partir de System.Text.Json
v5 preview6, ReferenceHandling
est désormais ReferenceHandler
. Voir: github.com/dotnet/runtime/pull/37296/files
Enfin corrigé le mien avec System.Text.Json et non NewtonSoft.Json en utilisant
objstr = JsonSerializer.Serialize(obj,options);
Utilisation d'options pour sérialiser
var options = new JsonSerializerOptions() { MaxDepth = 0, IgnoreNullValues = true, IgnoreReadOnlyProperties = true };
Pour net core 3.1, vous devez ajouter Startup.cs:
<PackageReference Include="System.Text.Json" Version="5.0.0-rc.1.20451.14" />
et importez au moins ce paquet à l'aide de nuget.org, incluez la pré-version:
services.AddMvc.AddJsonOptions(o => { o.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve; o.JsonSerializerOptions.MaxDepth = 0; })
J'ai le même problème, ma solution consistait à ajouter le mot clé async et await puisque j'appelle une méthode async sur ma logique métier.
Voici mon code d'origine:
HttpGet] public async Task<IActionResult> Get() { var results = await _repository.GetAllDataAsync(); return Ok(results); }
À celui-ci:
[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); }
Comment votre produit et votre catégorie de produits sont-ils liés?
Vous aurez probablement besoin d'un
[JsonIgnore]
sur la propriété FK de ProductCategory à ProductJe mets à jour ma question mais l'erreur existe.
ReferenceLoopHandling.Ignore peut être une option
vous devez ajouter la classe ProductCategory à la place de l'interface
@Alireza pouvez-vous en décrire plus que je ne peux pas ajouter en haut de la classe productCatgory
vous avez probablement une référence à la classe
Product
dans votreProductCategory
. et vous créez une boucle de référence.Ajout de [JsoneIgnore] dans la catégorie mu mais j'ai cette erreur aussi je mets à jour mon code et ajoute la classe ProductCategory
Découvrez ce stackoverflow.com/questions/34753498/...
Il semble que l'attribut JsonIgnore ne fonctionne pas pour vous. Vérifiez s'il correspond au sérialiseur que vous utilisez.
Est-ce que cela répond à votre question? Un cycle d'objet possible .Net Core 3.0 a été détecté, ce qui n'est pas pris en charge