Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serializing with JSON #38

Open
msant7 opened this issue Sep 10, 2020 · 4 comments
Open

Serializing with JSON #38

msant7 opened this issue Sep 10, 2020 · 4 comments

Comments

@msant7
Copy link

msant7 commented Sep 10, 2020

Hi, I was wondering if anyone had any thoughts about serializing with JSON instead of BinaryFormatter. I implemented the following as a test on my local dev and it seems to work well:
https://patrickdesjardins.com/blog/serializing-complex-object-for-redis

PROS

  • The big PRO is that you don't have to add and maintain [Serializable] to all your classes being cached in Redis.
    CONS
  • Small size increase, could compress but obviously adds overhead
  • It won't honor [NonSerialized] attributes, but I guess it would honor [JsonIgnore] attributes
  • It could be potentially easier for someone to inject a "Bad" object in the cache since the type is included in the cached object.

Here is an example of a cached item...

get dma9_DNN_SkinDefaults_SkinInfo
"{\r\n "$id": "1",\r\n "$type": "DotNetNuke.UI.Skins.SkinDefaults, DotNetNuke",\r\n "AdminDefaultName": "Admin.ascx",\r\n "DefaultName": "Inner.ascx",\r\n "Folder": "/Xcillion/"\r\n}"

Just curious if anyone has any thoughts on this or have tried this with DNN. Thanks

@davidjrh
Copy link
Owner

davidjrh commented Sep 10, 2020

Sounds really interesting to me. When I built this module some time back, I tried with different serializers like DataContract, XmlSerializer (there is still code about it

internal static byte[] SerializeXmlBinary(object obj)
that is not currently in use), etc. After lot of tests, the I got the best performance with binary uncompressed. Note that there is already an option to compress/decompress in place.

At that time, I didn't try with any JSON serialization, and after reviewing this post (https://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/), I'm thinking that having the option to use JSON or even other serializers would be an interesting experiment. Seems that just with JSON the performance would be better than binary.

Do you have measured the performance with lot of objects (small and large) so we can do some type of comparison?

On the other hand, the binary serializer can even serialize/deserialize private properties, not sure if that's possible with the other ones.

@msant7
Copy link
Author

msant7 commented Nov 23, 2020

Just to give an update on this. Everything was looking good, I was getting really good results on size and time, but then I hit a roadblock. I get the following exception:
Exception of type 'DotNetNuke.Collections.Internal.ReadLockRequiredException' was thrown.

at DotNetNuke.Collections.Internal.SharedDictionary2.EnsureReadAccess() at DotNetNuke.Collections.Internal.SharedDictionary2.IEnumerable_GetEnumerator()
at Newtonsoft.Json.Utilities.DictionaryWrapper`2.System.Collections.IDictionary.GetEnumerator()
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer)
at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Formatting formatting, JsonSerializerSettings settings)
at DotNetNuke.Providers.RedisCachingProvider.Shared.SerializeJSON(Object source) in C:\dnnsites\ot9\Providers\CachingProviders\RedisCachingProvider\RedisCachingProvider\Shared.cs:line 110
at DotNetNuke.Providers.RedisCachingProvider.RedisCachingProvider.Insert(String key, Object value, DNNCacheDependency dependency, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback) in C:\dnnsites\ot9\Providers\CachingProviders\RedisCachingProvider\RedisCachingProvider\RedisCachingProvider.cs:line 205

This occurs when TabInfo is serialized. What is specifically causing it is the following member variables:
image

In order for those elements to be accessed, it needs to be accessed as follows, or you can't read the element.
image

Not sure if anyone has any ideas.... Thanks

@mtrutledge
Copy link
Contributor

Was any progress on this ever made?

@mtrutledge
Copy link
Contributor

I am going to take a slightly different approach here. If the JSON serialization fails for some reason I am going to fall back to Binary serialization. Then check for base64encoded strings during deserialization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants