AliBazzi / IdentityServer4.Contrib.RedisStore

A persistence layer using Redis DB for operational data and for caching capability for Identity Server 4
https://www.nuget.org/packages/IdentityServer4.Contrib.RedisStore
MIT License
137 stars 48 forks source link

Self referencing loop for JSON #65

Closed Psybax closed 3 years ago

Psybax commented 3 years ago

I have error when calling SetAsync API in RedisCache.cs

 Message: 
    Newtonsoft.Json.JsonSerializationException : Self referencing loop detected for property 'Client' with type 'IdentityServer4.EntityFramework.Entities.Client'. Path 'ClientSecrets[0]'.
  Stack Trace: 
    JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter writer, Object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
    JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
    JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
    JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
    JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
    JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
    JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
    JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
    JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
    JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
    JsonSerializer.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
    JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer)
    JsonConvert.SerializeObject(Object value, Type type, JsonSerializerSettings settings)
    JsonConvert.SerializeObject(Object value, JsonSerializerSettings settings)
    RedisCache`1.Serialize(T item)
    RedisCache`1.SetAsync(String key, T item, TimeSpan expiration)
    ClientService.CacheClientAsync(Client client) line 239
    ClientService.CreateAsync(Client client) line 49
    ClientServiceTests.CreateAsync_ClientUseClientStoreCache_CreateInDbAndCache() line 80
    --- End of stack trace from previous location where exception was thrown ---

On Stackoverflow https://stackoverflow.com/questions/7397207/json-net-error-self-referencing-loop-detected-for-type, it requires to add

new JsonSerializerSettings 
{ 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore
})

when using JsonConvert.SerializeObject. Since the JSON convert is wrapped into RedisCache.cs I can not change it. I also tried other ways without changing JsonSerializerSettings, like add

services.AddControllers()
                .AddNewtonsoftJson(options =>
                {
                    // Use the default property (Pascal) casing
                    options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                    options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                });

in Start.cs. But it still has the error when running unit test. Do we need to add ReferenceLoopHandling = ReferenceLoopHandling.Ignore in JsonSerializerSettings to solve this problem?

AliBazzi commented 3 years ago

Hi @Psybax

The library is not built to store the entity framework object, it's designed to store the models available in IdentityServer4.Models namespace.

there are extension methods to convert back from the EF entity to the model, you can search for it.

Psybax commented 3 years ago

Hi @Psybax

The library is not built to store the entity framework object, it's designed to store the models available in IdentityServer4.Models namespace.

there are extension methods to convert back from the EF entity to the model, you can search for it.

Thanks for the answer. Changed to use model and it works.