3

I want to remove existing route from RouteCollection and want to add new route with same route name in nopCommerce 4.00 via plugin

Existing route name:

//home page
            routeBuilder.MapLocalizedRoute("HomePage", "",
        new { controller = "Home", action = "Index" });

I Want to replace it with

   routeBuilder.MapLocalizedRoute("HomePage", "",
    new { controller = "CustomPage", action = "Homepage" });

I tried several ways but not get any luck.

Raju Paladiya
  • 778
  • 2
  • 12
  • 35

3 Answers3

5

In my case, I have to replace the robots.txt generation. I created a new public controller in my plugin, and I copy the original action here:

public class MiscCommonController : BasePublicController
{
    #region Fields
    private readonly ICommonModelFactory _commonModelFactory;
    #endregion Fields

    #region Ctor
    public MiscCommonController(
        ICommonModelFactory commonModelFactory
        )
    {
        this._commonModelFactory = commonModelFactory;
    }
    #endregion Ctor

    #region Methods
    //robots.txt file
    //available even when a store is closed
    [CheckAccessClosedStore(true)]
    //available even when navigation is not allowed
    [CheckAccessPublicStore(true)]
    public virtual IActionResult RobotsTextFile()
    {
        var robotsFileContent = _commonModelFactory.PrepareRobotsTextFile();
        return Content(robotsFileContent, MimeTypes.TextPlain);
    }
    #endregion Methods
}

After this I create a RouteProvider for my plugin, and I replaced the original route to my own one.

public partial class RouteProvider : IRouteProvider
{
    /// <summary>
    /// Gets a priority of route provider
    /// </summary>
    public int Priority => -1;

    /// <summary>
    /// Register routes
    /// </summary>
    /// <param name="routeBuilder">Route builder</param>
    public void RegisterRoutes(IRouteBuilder routeBuilder)
    {
        Route route = null;

        foreach (Route item in routeBuilder.Routes)
        {
            if (item.Name == "robots.txt")
            {
                route = item;
                break;
            }
        }

        if (route != null) routeBuilder.Routes.Remove(route);

        routeBuilder.MapRoute(
            "robots.txt",
            "robots.txt",
            new { controller = "MiscCommon", action = "RobotsTextFile" }
        );
    }
}

That's all.

After this implementation, the routing works fine, and the get request landed in my own controller, which is act like the original.

Now, I can replace the generation logic with my own.

I hope it helps.

Divyang Desai
  • 7,483
  • 13
  • 50
  • 76
Antal István
  • 126
  • 1
  • 3
1

in the RouteProvider.cs of your plugin write these codes (based on your names):

var lastExistingRoute= routeBuilder.Routes.FirstOrDefault(x => ((Route)x).Name == "HomePage");
            routeBuilder.Routes.Remove(lastExistingRoute);
            routeBuilder.MapRoute("HomePage", "",
                new { controller = "CustomPage", action = "Homepage", });

and the below codes worked for myself version 4.20:

  var lastDownloadRoute=routeBuilder.Routes.FirstOrDefault(x => ((Route)x).Name == "GetDownload");
            routeBuilder.Routes.Remove(lastDownloadRoute);
            routeBuilder.MapRoute("GetDownload", "download/getdownload/{guid}/{agree?}",
                new { controller = "AzTechProduct", action = "GetPayed", });
Arash.Zandi
  • 1,010
  • 2
  • 13
  • 24
  • This would work if you just manually added a Route. But I believe the routeBuilder code runs prior to ASP.NET's reflection-based registration. So if you're trying to remove a route that's part of a controller, this doesn't seem to work. – Suamere Jan 19 '20 at 17:22
  • Dear @Suamere Thanks for your comment, you are right but the nopCommerce default routing for all of it's controllers and actions is declared **Convention based** in the **RouteProvider.cs** of **Nop.Web** so It works for all existing actions. – Arash.Zandi Jan 19 '20 at 17:49
  • What about 4.30? I can't find any solution. – Antal István Feb 02 '21 at 10:28
  • @AntalIstván I also can't. please notice me if you have found a solution. – Arash.Zandi Feb 18 '21 at 05:36
1

There are two potential ways to deal with this in nopCommerce 4.3 that I see with a quick examination of the code.

First, you could create an IRouteProvider, add your route that has the same signature as the one you wish to 'delete' and make sure the Priority on the provider is greater than 1.

Doing this will basically override the default route built into Nop. This is my preferred method.

    public partial class RouteProvider: IRouteProvider
    {
        public void RegisterRoutes(IEndpointRouteBuilder endpointRouteBuilder)
        {

            var pattern = string.Empty;
            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 + "}/";
                }
            }

            // Handle the standard request
            endpointRouteBuilder.MapControllerRoute("Wishlist", pattern + "wishlist/{customerGuid?}",
                new { controller = "MyShoppingCart", action = "Wishlist" });

            return;
        }

        public int Priority => 100;
    }

The key to the code above is the Priority value. This route will get added to the list first and will therefore take precedence over the default route. Using this technique eliminates the need to delete the default route.

The second possible method turns out to not work because the endpointRouteBuilder.DataSources[n].Endpoints collection is read only. So, as far as I know, you can't remove mappings from that list after they have been added.

Mitch Baker
  • 53
  • 1
  • 6
  • One thing that I have discovered using the first technique is that it can have unintended consequences for the controller you are overriding. In my case, I had to specify that the call was an _[HttpGet]_ so that later posts, that I did not want to override, where preserved. – Mitch Baker Mar 31 '21 at 20:48