FIXED Breadcrumb and Left Navigation for product in multiple categories

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
3 years ago

        protected override ProductDetailsModel.ProductBreadcrumbModel PrepareProductBreadcrumbModel(Product product)
        {
            if (product == null)
                throw new ArgumentNullException(nameof(product));

            var cacheKey = string.Format(NopModelCacheDefaults.ProductBreadcrumbModelKey,
                    product.Id,
                    _workContext.WorkingLanguage.Id,
                    string.Join(",", _workContext.CurrentCustomer.GetCustomerRoleIds()),
                    _storeContext.CurrentStore.Id);
            var cachedModel = _cacheManager.Get(cacheKey, () =>
            {
                var breadcrumbModel = new ProductDetailsModel.ProductBreadcrumbModel
                {
                    Enabled = _catalogSettings.CategoryBreadcrumbEnabled,
                    ProductId = product.Id,
                    ProductName = _localizationService.GetLocalized(product, x => x.Name),
                    ProductSeName = _urlRecordService.GetSeName(product)
                };
                var productCategories = _categoryService.GetProductCategoriesByProductId(product.Id);
                if (!productCategories.Any())
                    return breadcrumbModel;

                //override to get referring URL instead of defaulting to 1st cat
                var urlReferrer = _webHelper.GetUrlReferrer();
                var category = !string.IsNullOrEmpty(urlReferrer)
                    ? GetReferringCategory(urlReferrer, productCategories)
                    : productCategories[0].Category;


                if (category == null)
                    return breadcrumbModel;

                foreach (var catBr in _categoryService.GetCategoryBreadCrumb(category))
                {
                    breadcrumbModel.CategoryBreadcrumb.Add(new CategorySimpleModel
                    {
                        Id = catBr.Id,
                        Name = _localizationService.GetLocalized(catBr, x => x.Name),
                        SeName = _urlRecordService.GetSeName(catBr),
                        IncludeInTopMenu = catBr.IncludeInTopMenu
                    });
                }

                return breadcrumbModel;
            });
            return cachedModel;
        }



        private Category GetReferringCategory(string referringUrl, IList<ProductCategory> categories)
        {
            var referringUrlSplit = referringUrl.Split('/');
            if (referringUrlSplit.Length > 0)
            {
                for (var i = 0; i < referringUrlSplit.Length; i++)
                {
                    if (referringUrlSplit[i].Length > 0)
                    {
                        var referringCategoryURL = referringUrlSplit[i];
                        var url = _urlRecordService.GetBySlug(referringCategoryURL);
                        if (url != null && url.EntityName.ToLower() == "category")
                        {
                            var referringCategory = _categoryService.GetCategoryById(url.EntityId);
                            if (referringCategory != null)
                                return referringCategory;                            
                        }
                    }
                }
            }
            return categories[0].Category;
        }
3 years ago
af1racing wrote:

        protected override ProductDetailsModel.ProductBreadcrumbModel PrepareProductBreadcrumbModel(Product product)
        {
            if (product == null)
                throw new ArgumentNullException(nameof(product));

            var cacheKey = string.Format(NopModelCacheDefaults.ProductBreadcrumbModelKey,
                    product.Id,
                    _workContext.WorkingLanguage.Id,
                    string.Join(",", _workContext.CurrentCustomer.GetCustomerRoleIds()),
                    _storeContext.CurrentStore.Id);
            var cachedModel = _cacheManager.Get(cacheKey, () =>
            {
                var breadcrumbModel = new ProductDetailsModel.ProductBreadcrumbModel
                {
                    Enabled = _catalogSettings.CategoryBreadcrumbEnabled,
                    ProductId = product.Id,
                    ProductName = _localizationService.GetLocalized(product, x => x.Name),
                    ProductSeName = _urlRecordService.GetSeName(product)
                };
                var productCategories = _categoryService.GetProductCategoriesByProductId(product.Id);
                if (!productCategories.Any())
                    return breadcrumbModel;

                //override to get referring URL instead of defaulting to 1st cat
                var urlReferrer = _webHelper.GetUrlReferrer();
                var category = !string.IsNullOrEmpty(urlReferrer)
                    ? GetReferringCategory(urlReferrer, productCategories)
                    : productCategories[0].Category;


                if (category == null)
                    return breadcrumbModel;

                foreach (var catBr in _categoryService.GetCategoryBreadCrumb(category))
                {
                    breadcrumbModel.CategoryBreadcrumb.Add(new CategorySimpleModel
                    {
                        Id = catBr.Id,
                        Name = _localizationService.GetLocalized(catBr, x => x.Name),
                        SeName = _urlRecordService.GetSeName(catBr),
                        IncludeInTopMenu = catBr.IncludeInTopMenu
                    });
                }

                return breadcrumbModel;
            });
            return cachedModel;
        }



        private Category GetReferringCategory(string referringUrl, IList<ProductCategory> categories)
        {
            var referringUrlSplit = referringUrl.Split('/');
            if (referringUrlSplit.Length > 0)
            {
                for (var i = 0; i < referringUrlSplit.Length; i++)
                {
                    if (referringUrlSplit[i].Length > 0)
                    {
                        var referringCategoryURL = referringUrlSplit[i];
                        var url = _urlRecordService.GetBySlug(referringCategoryURL);
                        if (url != null && url.EntityName.ToLower() == "category")
                        {
                            var referringCategory = _categoryService.GetCategoryById(url.EntityId);
                            if (referringCategory != null)
                                return referringCategory;                            
                        }
                    }
                }
            }
            return categories[0].Category;
        }


So i've implemented this for 4.2 and it works, but for 4.3 wasn't able to get this working.
3 years ago
sorry, I'm not on 4.3 yet but I see they no longer cache the result:
https://github.com/nopSolutions/nopCommerce/blob/master/src/Presentation/Nop.Web/Factories/ProductModelFactory.cs

the theory should be similar though in using _webHelper.GetUrlReferrer() before falling back on productCategories[0].CategoryId
3 years ago
Good stuff! I'd like to see this implemented in to default source code.
2 years ago
Here is a simple plugin that allows you to define a Master Category for a product.
When a product is in multiple categories then the Master Category is used to deturmine the Breadcrumb, instead of the default which is category product display order option.
See https://www.selectsystems.com.au/product-extensions-master-category-selector


This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.