0

I want to allow forward slash into SENAME of my nop project. How can i do this using customisation?

for example,

  1. I want product url like "/product/htc-one-m8-android-l-50-lollipop" instead of "/htc-one-m8-android-l-50-lollipop"
  2. I want category url like "/category/desktops" instead of "/desktops"

I am using nopcommerce 4.3 version.

sample code

 endpointRouteBuilder.MapDynamicControllerRoute<SlugRouteTransformer>("SeName}");

I am not getting call into this TransformAsync method. i want to get call here when i add "/product/sename" into url

public override ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values)
        {
        }
Sangeet Shah
  • 3,079
  • 2
  • 22
  • 25

1 Answers1

1

You can register routes for Product/ and Category/ path in GenericUrlRouteProvider like:

endpointRouteBuilder.MapDynamicControllerRoute<SlugRouteTransformer>("Product/{SeName}");
endpointRouteBuilder.MapDynamicControllerRoute<SlugRouteTransformer>("Category/{SeName}");

If you want your existing links to be displayed correctly your also want to update default Product and Category routes and your register routes method should look like:

public void RegisterRoutes(IEndpointRouteBuilder endpointRouteBuilder)
{
    var pattern = "{SeName}";
    var productPattern = "Product/{SeName}";
    var catgoryPattern = "Category/{SeName}";
    if (DataSettingsManager.DatabaseIsInstalled)
    {
        var localizationSettings = endpointRouteBuilder.ServiceProvider.GetRequiredService<LocalizationSettings>();
        if (localizationSettings.SeoFriendlyUrlsForLanguagesEnabled)
        {
            var langservice = endpointRouteBuilder.ServiceProvider.GetRequiredService<ILanguageService>();
            var languages = langservice.GetAllLanguages().ToList();
            pattern = "{language:lang=" + languages.FirstOrDefault().UniqueSeoCode + "}/{SeName}";
            productPattern = "{language:lang=" + languages.FirstOrDefault().UniqueSeoCode + "}/{SeName}";
            catgoryPattern = "{language:lang=" + languages.FirstOrDefault().UniqueSeoCode + "}/{SeName}";
        }
    }
    endpointRouteBuilder.MapDynamicControllerRoute<SlugRouteTransformer>(pattern);
    endpointRouteBuilder.MapDynamicControllerRoute<SlugRouteTransformer>(productPattern);
    endpointRouteBuilder.MapDynamicControllerRoute<SlugRouteTransformer>(catgoryPattern);

    //and default one
    endpointRouteBuilder.MapControllerRoute(
        name: "Default",
        pattern: "{controller=Home}/{action=Index}/{id?}");

    //generic URLs
    endpointRouteBuilder.MapControllerRoute(
        name: "GenericUrl",
        pattern: "{GenericSeName}",
        new { controller = "Common", action = "GenericUrl" });

    //define this routes to use in UI views (in case if you want to customize some of them later)
    endpointRouteBuilder.MapControllerRoute("Product", productPattern, 
        new { controller = "Product", action = "ProductDetails" });

    endpointRouteBuilder.MapControllerRoute("Category", catgoryPattern, 
        new { controller = "Catalog", action = "Category" });

    endpointRouteBuilder.MapControllerRoute("Manufacturer", pattern, 
        new { controller = "Catalog", action = "Manufacturer" });

    endpointRouteBuilder.MapControllerRoute("Vendor", pattern, 
        new { controller = "Catalog", action = "Vendor" });
            
    endpointRouteBuilder.MapControllerRoute("NewsItem", pattern, 
        new { controller = "News", action = "NewsItem" });

    endpointRouteBuilder.MapControllerRoute("BlogPost", pattern, 
        new { controller = "Blog", action = "BlogPost" });

    endpointRouteBuilder.MapControllerRoute("Topic", pattern, 
        new { controller = "Topic", action = "TopicDetails" });

    //product tags
    endpointRouteBuilder.MapControllerRoute("ProductsByTag", pattern,
        new { controller = "Catalog", action = "ProductsByTag" });
}

Update:

In order to allow / in product name, there are multiple changes you need to make.

  1. Allow / in sename, to do that UrlRecordService has GetSeName method and in okChars variable you want to add / as one of the valid characters.

  2. Fix your call related to dynamic routes. You have { missing in your code. It should be: endpointRouteBuilder.MapDynamicControllerRoute<SlugRouteTransformer>("{SeName}");

  3. Update SlugRouteTransformer's TransformAsync method to unescape URL before searching for matching Url records using: var urlRecord = _urlRecordService.GetBySlug(Uri.UnescapeDataString(slug));

I believe that is all and after that you should be able to allow / in your entity name. Be aware that this might break existing pages and links might not work perfectly all the time. Also, if you look closely, your product/category url will have %2F in the URL, if you want to change that you will have to unesacpe all the links before rendering, something like: <a href="@System.Uri.UnescapeDataString(Url.RouteUrl("Product", new {SeName = Model.SeName}))">@Model.Name</a> BUT IT WILL BREAK A LOT OF THINGS!

Dipen Shah
  • 25,562
  • 1
  • 32
  • 58
  • sir thanks for suggetion, but I want dynamic url this url is not fixed that it contain "product/sename". bcz this sename is textbox so admin can able to add any url into this sename text like admin can add "xyz/sename". this solution i already know but i want dynamic url – Sangeet Shah Sep 30 '20 at 06:00
  • @SangeetShah I am having bit hard time understanding exactly what you are asking in the question. Could you please elaborate bit more on requirements? – Dipen Shah Sep 30 '20 at 06:51
  • Your provided solution work only if i write the "product/sename" for any product sename but if i write the "xyz/sename" for product sename the its getting stoped working. – Sangeet Shah Sep 30 '20 at 09:00
  • I am not sure if I have complete solution and I did not check if everything is working as expected, but I believe it is right direction, checkout update at the end of my original answer. – Dipen Shah Sep 30 '20 at 17:15
  • sorry you provided solution not working i have tested this already, do you another solution for this as per my requirnent. – Sangeet Shah Oct 01 '20 at 09:27
  • I am happy to get your solution. but static parameter already working in mine side. but i want dynamic url solution for sename. e.g. on product edit page user can add url into sename textbox like "/product/htc-one-m8-android-l-50-lollipop" or "/products/htc-one-m8-android-l-50-lollipop" or "/xyz/htc-one-m8-android-l-50-lollipop" I want to include forward slash in seName not otherwise. As SeName allows other characters such as -, similarly I need forward slash in same. Please suggest a way to do that. – Sangeet Shah Oct 01 '20 at 09:27
  • @sangeetshah, now we are talking so far I wasn't sure if needed customized view or meant product name as sename is built from product name. That being said, solution I will provide will have same issues I mentioned in my update, I can provide detail of changes but you will either have to be fine with %2F in url or there will be lots of unknown issues, will that work for you? – Dipen Shah Oct 01 '20 at 10:09
  • @dipeshshah actually my client not want to ad %2F in url thats a main problem. – Sangeet Shah Oct 01 '20 at 10:58
  • I see, @SangeetShah that will be a breaking issue for router, I am not sure if I will be able to spend time during week to even try to fix it, but I can at least put some steps you can follow as a guide. – Dipen Shah Oct 01 '20 at 11:01
  • 1
    Thank you so much for your time for my query but I already got the solution that you send to me but i didn't full fill my requirement. so i have posted my query on stack over flow. for this issue i have submit ticket to nopCommerce team. let me see their reply. – Sangeet Shah Oct 01 '20 at 11:57