Distributed Cache DeserializeObject exception.

3 weeks ago
It is not related to nopCommerce but rather Newtonsoft.Json.  I am getting the error "type is an interface or abstract class and cannot be instantiated. Path '', line 1, position 1." It is happening when I am trying to cache the PagedList Data.

The Code

      var query = from p in _popupBannerRepository.Table
                        where p.PopupPageTypeId == 10 && p.Deleted == false && p.Active == true
                        select p;


            if (popupTypeId > 0)
                query = query.Where(v => v.PopupTypeId == popupTypeId);


            if (popupDisplayTypeId > 0)
                query = query.Where(v => v.PopupDisplayTypeId == popupDisplayTypeId);


            query = query.OrderByDescending(x => x.Id);


            var cacheKey = _staticCacheManager
                .PrepareKeyForDefaultCache(NopPopupBannerDefaults.PopUpAllCacheKey, popupTypeId, popupDisplayTypeId, pageSize);
            cacheKey.CacheTime = 60 * 8;


           var result= await _staticCacheManager.GetAsync(cacheKey, async () =>
            {
                return await query.ToPagedListAsync(pageIndex, pageSize); // Error here.
            });
            return result;
3 weeks ago
I have got a workaround by changing the query to something like the below.

var cacheKey = _staticMemoryCacheManager
                .PrepareKeyForDefaultCache(NopPopupBannerDefaults.PopUpAllCacheKey, popupTypeId, popupDisplayTypeId, pageSize);
            cacheKey.CacheTime = 60 * 8;

            var result = await _staticMemoryCacheManager.GetAsync(cacheKey, () =>
            {
                var query = from p in _popupBannerRepository.Table
                            where p.PopupPageTypeId == 10 && p.Deleted == false && p.Active == true
                            select p;


                if (popupTypeId > 0)
                    query = query.Where(v => v.PopupTypeId == popupTypeId);


                if (popupDisplayTypeId > 0)
                    query = query.Where(v => v.PopupDisplayTypeId == popupDisplayTypeId);


                query = query.OrderByDescending(x => x.Id);
                return query;
            });

            return await result.ToPagedListAsync(pageIndex, pageSize);

But I am little confused about the below line

  return await result.ToPagedListAsync(pageIndex, pageSize);

is not it calling to database every time when this line is executed?
3 weeks ago
No.  'result' is a List.  The lambda function passed as parameter to _staticMemoryCacheManager.GetAsync would access the DB, but it would only be called if the key is not in the cache (or expired).
3 weeks ago
New York wrote:
No.  'result' is a List.  The lambda function passed as parameter to _staticMemoryCacheManager.GetAsync would access the DB, but it would only be called if the key is not in the cache (or expired).


  'result' is a IQueryable
2 weeks ago
Yes, I guess in your case it is.  I don't see similar examples in 4.50 code.
In 4.50, similar lambda functions return lists.  Why does yours return an IQueryable?

What version of nopCommerce?
Where did you get code example from?
2 weeks ago
New York wrote:
Yes, I guess in your case it is.  I don't see similar examples in 4.50 code.
In 4.50, similar lambda functions return lists.  Why does yours return an IQueryable?

What version of nopCommerce?
Where did you get code example from?


The nopCommerce version is 4.5.x and the code is invalid for the distributed cache but working for the memory cache.  Because IQuerable<T> is a generic type and when Newtonsoft.Json try to deserialize then it throws an exception as   Newtonsoft.json does not know the type of the T
2 weeks ago
It seems to me that you are caching an "expression tree", and not the results (of the execution of the tree), which should be a list
2 weeks ago
New York wrote:
It seems to me that you are caching an "expression tree", and not the results (of the execution of the tree), which should be a list

Agreed and I have changed it already. Thanks