Alachisoft / NCache

NCache: Highly Scalable Distributed Cache for .NET
http://www.alachisoft.com
Apache License 2.0
647 stars 123 forks source link

Exception when getting element from .NETCore that are added by .NET. #67

Open MeValori opened 2 years ago

MeValori commented 2 years ago

Hi, I'm trying to setup and environment where a console app, based on .NET461, adds elements to a cache, elements that are getted by a .NETCore 3.1 web app. The console app uses the ICache interface, while the .NETCore web app uses the IDIstributedCache interface. All packages are updated to the latest available. When the .NETCore web app executes the GetString() method, an exception arises from the NCache subsystem and no element returns. The relevant piece of code of the console app is: string cacheKey = $"elm:pagestree|idcn:{idCN}"; string cacheItem = Newtonsoft.Json.JsonConvert.SerializeObject(shadowPagesTreeList, Newtonsoft.Json.Formatting.None); if (cacheManager.Contains(cacheKey)) { cacheManager.Remove(cacheKey); } cacheManager.Insert(cacheKey, cacheItem);

The relevant piece of code of the web app is: string cacheKey = $"elm:pagestree|idcn:{idCN}"; var cacheItem = _distributedCache.GetString(cacheKey); if (cacheItem != null) { l = System.Text.Json.JsonSerializer.Deserialize<List>(cacheItem); }

The exception arises when executing the GetString() or Get() methods and is: _System.Configuration.Provider.ProviderException HResult=0x80131500 Message=Unable to cast object of type 'System.String' to type 'System.Byte[]'. Source=Alachisoft.NCache.DistributedCache StackTrace: at Alachisoft.NCache.Caching.Distributed.NCacheDistributedCache.RaiseException(Exception exc) at Alachisoft.NCache.Caching.Distributed.NCacheDistributedCache.LogError(Exception exception) at Alachisoft.NCache.Caching.Distributed.NCacheDistributedCache.Get(String key) at Microsoft.Extensions.Caching.Distributed.DistributedCacheExtensions.GetString(IDistributedCache cache, String key) at IsibetPRO.IsiPlanner.ServiceWebApp.Controllers.MainController.GetPagesTree(Byte appType) in D:\Users\andre\Source\Repos\IsiPlanner\IsibetPRO.IsiPlanner.ServiceWebApp\Controllers\MainController.cs:line 262 at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync() at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()

This exception was originally thrown at this call stack: [External Code]

Inner Exception 1: InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Byte[]'._

The cache, server side, is configured as in file attached. Please note that other combinations of data-format and serialization parameters don't resolve. If the web app itself adds and gets elements from the cache, all works as expected.

Thanks in advance, Andrea Valori.

config.ncconf.txt

Dan-Ahmed commented 2 years ago

@MeValori, As per our discussion over the support ticket, I have executed the application on my end again in Debug mode and here are my findings.

During the testing, I was unable to reproduce the error that you're seeing on your end. However, I noticed a behavior where after adding the items in the Cache through the .NET Framework 4.6.1 console app, I get a "null" value from the "idistributedcache" using the .NET Core 3.1 web app which uses NCache IDistributedCache Provider.

The IDistributedCache Provider approach is used by those users who want to stick to it. I've noticed that you are adding the items in the Cache using NCache Direct API i.e. "_cache.Insert()" and then trying to retrieve those items using IDistributedCache Provider. I need to discuss this with the Engineering team if they know about any known specific behaviors in this particular scenario.

Moreover, I tried to modify your sample application where it uses NCache Direct APIs (i.e. _cache.Get() & _cache.Insert()) in both applications (.NET Framework 4.6.1 & .NET Core 3.1) and it is working without any issues. You can easily retrieve the items from Cache in this case. Here are some code snippets that I have used on my end for this.

// Insert the item in the Cache using Insert() API.
if (cacheManager.Contains(cacheKey))
{
     LogInstance.Debug($"66D43421-> Item with key {cacheKey} in cache {Properties.Settings.Default.NCacheName} will be updated.");
}
cacheManager.Insert(cacheKey, cacheItem);

// Retrieve the item from NCache using Get() API.
string cacheItem;
try
{
     cacheItem = distributedCache.Get<string>(cacheKey);
}

I have also noticed that you're using the JSON serialization/deserialization process explicitly while adding and retrieving the items from the cache. This could be a requirement for IDistributedCache but please note that it is not needed for NCache. All items are serialized/deserialized automatically by NCache during the insertion/retrieval process. In the case of Binary serialized cache, you need to mark the entities that you want to cache as "Serializable" and NCache will handle everything else itself from there. NCache also supports "JSON" serialization mode for the Cache which does not require the entities to be marked as "Serializable".

Hope this helps.