Need to create a dynamic routing for categories and products

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
10 anni tempo fa
Hi,

First of all, thanks for an awesome contribution to the ecommerce community with nopcommerce!

In nopcommerce 2.7 or 2.8, can't remember id less urls were introduced. This made the url's look alot better! But, for me this is not enough. I would like a more dynamic approach like this.

www.yourstore.com/category/subcategory/product

or just

www.yourstore.com/category/product

When not grouping products under categories it makes it hard to make full use of google analytics and all the measurement you can do there.

Has anyone done this before? I am running nopcommerce 3.10.

Any suggestions would be helpful :)

Thanks!
10 anni tempo fa
I have solved it like this.

Added a new route that hits on everything that nopcommerce does find.


routes.MapLocalizedRoute("RouteName",
                "{*slug}",
                new { controller = "Routing", action = "DetermineControllerAndAction" },
                new[] { "Nop.Web.Controllers" });


Created the new controller and added the method.


    public class RoutingController : BaseNopController
    {
        private readonly IUrlRecordService _urlRecordService;

        public RoutingController(IUrlRecordService urlRecordService)
        {
            _urlRecordService = urlRecordService;
        }

        public ActionResult DetermineControllerAndAction(string slug)
        {
            var record = _urlRecordService.GetBySlug(slug);

            var data = CreateRouteData(record);

            var context = new HttpContextWrapper(System.Web.HttpContext.Current);
            var request = new RequestContext(context, data);

            var controller = ControllerBuilder.Current.GetControllerFactory()
                .CreateController(request, data.Values["controller"].ToString());

            controller.Execute(request);

            return new EmptyResult();
        }

        /// <summary>
        /// Creates the RouteData object so the right controller and action is executed
        /// </summary>
        private RouteData CreateRouteData(UrlRecord record)
        {
            var data = new RouteData();

            //Show page not found if record is null
            if (record == null)
            {
                data.Values["controller"] = "Common";
                data.Values["action"] = "PageNotFound";
                return data;
            }

            //Handle 301
            if (!record.IsActive)
            {
                var activeSlug = _urlRecordService.GetActiveSlug(record.EntityId, record.EntityName, record.LanguageId);

                if (!string.IsNullOrWhiteSpace(activeSlug))
                {
                    //the active one is found
                    var webHelper = EngineContext.Current.Resolve<IWebHelper>();
                    var response = System.Web.HttpContext.Current.Response;
                    response.Status = "301 Moved Permanently";
                    response.RedirectLocation = string.Format("{0}{1}", webHelper.GetStoreLocation(false), activeSlug);
                    response.End();                    
                }
                else
                {
                    //no active slug found
                    data.Values["controller"] = "Common";
                    data.Values["action"] = "PageNotFound";
                    return data;
                }
            }

            try
            {
                switch (record.EntityName)
                {
                    case "Category":
                        data.Values.Add("controller", "Catalog");
                        data.Values.Add("action", "TransferToCategory");
                        data.Values.Add("categoryId", record.EntityId);
                        data.Values.Add("SeName", record.Slug);
                        break;
                    case "Product":
                        data.Values.Add("controller", "Catalog");
                        data.Values.Add("action", "TransferToProduct");
                        data.Values.Add("productId", record.EntityId);
                        data.Values.Add("SeName", record.Slug);
                        break;
                }

                return data;
            }
            catch (Exception e)
            {
                
            }

            return null;
        }
    }


At last, added two methods to the CatalogController that just calls the original nop methods of category and product.


        [NopHttpsRequirement(SslRequirement.No)]
        public ActionResult TransferToCategory(int categoryId)
        {
            return Category(categoryId, new CatalogPagingFilteringModel());
        }

        [NopHttpsRequirement(SslRequirement.No)]
        public ActionResult TransferToProduct(int productId)
        {
            return Product(productId);
        }


This way, I can for example add to the urlrecord table "category/subcategory" and "category/subcategory/productname" and get a more dynamic routing and still use all the nopcommerce methods out of the box.
7 anni tempo fa
I know this is an old post but it does solve a major issue with NopCommerce and Google friendly urls very elegantly.

In NopCommerce v3.80 the following method does not build as the method "Product(productId)" does not exist in the CatalogController.

[NopHttpsRequirement(SslRequirement.No)]
        public ActionResult TransferToProduct(int productId)
        {
            return Product(productId);
      }


Please can someone direct me to how to solve this.

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