Nop Commerce automatically redirecting to different URL

793 views Asked by At

I am having a very peculiar issue. For some specific url nop website redirects to another url. For example -

This is the url that is supposed to go -

enter image description here

when clicked or even pasted in address bar, I debugged the code and in the application_beginrequest method notice the url -

enter image description here (notice the Path property of Request object)

It automatically changed from category_whisky-american-sour-mash to shipping-and-returns. Checked both the SEO urls from category and page but no duplicates.

I checked for SEO urls and there is only one entry, so no possible way of duplication

enter image description here

I am trying to solve this for almost a day now. Can anybody help? Why is this happening? I am relatively new to NopCommerce. Any suggestion is appreciated.

1

There are 1 answers

0
brainless coder On BEST ANSWER

Okay, after one and half day of trying I finally found the fix. I thought I should post the solution here.

It is due to wrong Slug values. In the UrlRecordService this method caches the slug by putting "" if no slug found -

    public virtual string GetActiveSlug(int entityId, string entityName, int languageId)
        {
            if (_localizationSettings.LoadAllUrlRecordsOnStartup)
            {
                string key = string.Format(URLRECORD_ACTIVE_BY_ID_NAME_LANGUAGE_KEY, entityId, entityName, languageId);
                return _cacheManager.Get(key, () =>
                {
                    //load all records (we know they are cached)
                    var source = GetAllUrlRecordsCached();
                    var query = from ur in source
                                where ur.EntityId == entityId &&
                                ur.EntityName == entityName &&
                                ur.LanguageId == languageId &&
                                ur.IsActive
                                orderby ur.Id descending
                                select ur.Slug;
                    var slug = query.FirstOrDefault();
                    //little hack here. nulls aren't cacheable so set it to ""
                    if (slug == null)
                        slug = ""; //slug is blank for null
                    return slug;
                });
            }
            else
            {
                //gradual loading
                string key = string.Format(URLRECORD_ACTIVE_BY_ID_NAME_LANGUAGE_KEY, entityId, entityName, languageId);
                return _cacheManager.Get(key, () =>
                {
                    var source = _urlRecordRepository.Table;
                    var query = from ur in source
                                where ur.EntityId == entityId &&
                                ur.EntityName == entityName &&
                                ur.LanguageId == languageId &&
                                ur.IsActive
                                orderby ur.Id descending
                                select ur.Slug;
                    var slug = query.FirstOrDefault();
                    //little hack here. nulls aren't cacheable so set it to ""
                    if (slug == null)
                        slug = ""; // slug is blank for null
                    return slug;
                });
            }
        }

Which ends creating a lot of urls with blank slugs. To fix this, you should do the followings -

  1. First modify the code that converts slug to item so that it ignore blanks - and
  2. then add check to ignore slugs with isActive = False -

    public virtual UrlRecordForCaching GetBySlugCached(string slug)
    {
        if (String.IsNullOrEmpty(slug))
            return null;
    
        if (_localizationSettings.LoadAllUrlRecordsOnStartup)
        {
            //load all records (we know they are cached)
            var source = GetAllUrlRecordsCached();
            var query = from ur in source
                        where ur.Slug.Equals(slug, StringComparison.InvariantCultureIgnoreCase)
                        && ur.IsActive // 2 add IsActive check
                        select ur;
            var urlRecordForCaching = query.FirstOrDefault();
            return urlRecordForCaching;
        }
        else
        {
            //gradual loading
            string key = string.Format(URLRECORD_BY_SLUG_KEY, slug);
            return _cacheManager.Get(key, () =>
            {
                if (string.IsNullOrEmpty(slug))  // 1 blank slug check
                    return null;
    
                var urlRecord = GetBySlug(slug);
                if (urlRecord == null)
                    return null;
    
                var urlRecordForCaching = Map(urlRecord);
                return urlRecordForCaching;
            });
        }
    }
    
    
    
    /// <summary>
    /// Gets all URL records
    /// </summary>
    /// <param name="slug">Slug</param>
    /// <param name="pageIndex">Page index</param>
    /// <param name="pageSize">Page size</param>
    /// <returns>Customer collection</returns>
    public virtual IPagedList<UrlRecord> GetAllUrlRecords(string slug, int pageIndex, int pageSize)
    {
        var query = _urlRecordRepository.Table;
        if (!String.IsNullOrWhiteSpace(slug))
            query = query.Where(ur => ur.Slug.Contains(slug) && ur.IsActive); // 2 add IsActive check
        query = query.OrderBy(ur => ur.Slug);
    
        var urlRecords = new PagedList<UrlRecord>(query, pageIndex, pageSize);
        return urlRecords;
    }
    
    /// <summary>
    /// Find URL record
    /// </summary>
    /// <param name="slug">Slug</param>
    /// <returns>Found URL record</returns>
    public virtual UrlRecord GetBySlug(string slug)
    {
        if (String.IsNullOrEmpty(slug))
            return null;
    
        var query = from ur in _urlRecordRepository.Table
                    where ur.Slug == slug && ur.IsActive // 2 add IsActive check
                    select ur;
        var urlRecord = query.FirstOrDefault();
        return urlRecord;
    }
    
    
    protected virtual IList<UrlRecordForCaching> GetAllUrlRecordsCached()
    {
        //cache
        string key = string.Format(URLRECORD_ALL_KEY);
        return _cacheManager.Get(key, () =>
        {
            var query = from ur in _urlRecordRepository.Table
                        where ur.IsActive # 2 add IsActive check
                        select ur;
            var urlRecords = query.ToList();
            var list = new List<UrlRecordForCaching>();
            foreach (var ur in urlRecords)
            {
                var urlRecordForCaching = Map(ur);
                list.Add(urlRecordForCaching);
            }
            return list;
        });
    }
    
    
    /// <summary>
    /// Gets all cached URL records
    /// </summary>
    /// <returns>cached URL records</returns>
    protected virtual IList<UrlRecordForCaching> GetAllUrlRecordsCached()
    {
        //cache
        string key = string.Format(URLRECORD_ALL_KEY);
        return _cacheManager.Get(key, () =>
        {
            var query = from ur in _urlRecordRepository.Table
                        where ur.IsActive // 2 add isActive check
                        select ur;
            var urlRecords = query.ToList();
            var list = new List<UrlRecordForCaching>();
            foreach (var ur in urlRecords)
            {
                var urlRecordForCaching = Map(ur);
                list.Add(urlRecordForCaching);
            }
            return list;
        });
    }
    
  3. Also don't forget to clear cookie and restart your server just in case.

So, far this solved my problem.