8
votes

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 à

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


11 commentaires

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 à Product


Je 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 votre ProductCategory . 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


5 Réponses :


2
votes

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)


1 commentaires

Je fais cela et supprime ProductId mais l'erreur existe toujours.Essayez également l'option set dans les services.AddControllers () mais ne fonctionne pas



20
votes

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.

  1. vous pouvez utiliser Newtonsoft.Json dans votre projet au lieu de System.Text.Json (j'ai lié un article pour vous)

  2. 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 ...


1 commentaires

À partir de System.Text.Json v5 preview6, ReferenceHandling est désormais ReferenceHandler . Voir: github.com/dotnet/runtime/pull/37296/files



0
votes

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
        };


0 commentaires

1
votes

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;
})


0 commentaires

0
votes

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);
}


0 commentaires