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.
Allow / in sename, to do that UrlRecordService
has GetSeName
method and in okChars
variable you want to add /
as one of the valid characters.
Fix your call related to dynamic routes. You have {
missing in your code. It should be:
endpointRouteBuilder.MapDynamicControllerRoute<SlugRouteTransformer>("{SeName}");
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!