【问题标题】:Remove route from RouteCollection in Asp.Net Core and add new with same route name (nopCommerce-4.00)从 Asp.Net Core 中的 RouteCollection 中删除路由并添加具有相同路由名称的新路由(nopCommerce-4.00)
【发布时间】:2018-12-08 00:42:48
【问题描述】:

我想从 RouteCollection 中删除现有路由,并希望通过插件在 nopCommerce 4.00 中添加具有相同路由名称的新路由

现有路线名称:

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

我想换成

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

我尝试了几种方法,但都没有运气。

【问题讨论】:

    标签: asp.net-core routes asp.net-core-2.0 route-provider nopcommerce-4.0


    【解决方案1】:

    就我而言,我必须替换 robots.txt 一代。 我在插件中创建了一个新的公共控制器,并在此处复制原始操作:

    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
    }
    

    在此之后,我为我的插件创建了一个RouteProvider,并将原来的路由替换为我自己的。

    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" }
            );
        }
    }
    

    就是这样。

    在这个实现之后,路由工作正常,get请求登陆我自己的控制器,就像原来的一样。

    现在,我可以用自己的逻辑替换生成逻辑了。

    希望对你有帮助。

    【讨论】:

    • 您好 Antal,感谢您的分享。我会检查并更新你。
    • @antal 我正在使用 nop 4.1 如何在管理视图中覆盖 "Admin/Order/Edit/{id}"
    • @RajeshRajendiran - 对于 nopCommerce 4.10 中的管理区域,您可以使用 ControllerFactory - MVC 功能并调用您的自定义控制器而不是默认的 nopCommerce。
    【解决方案2】:

    在你的插件的RouteProvider.cs 中写下这些代码(根据你的名字):

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

    以下代码适用于我自己的 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", });
    

    【讨论】:

    • 如果您只是手动添加一个路由,这将起作用。但我相信 routeBuilder 代码在 ASP.NET 的基于反射的注册之前运行。因此,如果您尝试删除属于控制器的路由,这似乎不起作用。
    • 亲爱的@Suamere 感谢您的评论,您是对的,但是所有控制器和操作的 nopCommerce 默认路由在 RouteProvider.cs 中声明为 基于约定 of Nop.Web 所以它适用于所有现有操作。
    • 4.30 怎么样?我找不到任何解决方案。
    • @AntalIstván 我也不能。如果您找到了解决方案,请通知我。
    【解决方案3】:

    通过快速检查代码,我发现在 nopCommerce 4.3 中有两种可能的方法来处理这个问题。

    首先,您可以创建一个 IRouteProvider,添加与您希望“删除”的路由具有相同签名的路由,并确保提供程序的优先级大于 1。

    这样做基本上会覆盖 Nop 中内置的默认路由。这是我的首选方法。

        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;
        }
    

    上面代码的关键是优先级值。此路由将首先添加到列表中,因此优先于默认路由。使用此技术无需删除默认路由。

    第二种可能的方法不起作用,因为 endpointRouteBuilder.DataSources[n].Endpoints 集合是只读的。因此,据我所知,您无法在添加映射后从该列表中删除它们。

    【讨论】:

    • 我发现使用第一种技术的一件事是它可能会对您正在覆盖的控制器产生意想不到的后果。在我的情况下,我必须指定调用是一个 [HttpGet] 以便以后发布我不想覆盖的帖子保留。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    • 2011-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    相关资源
    最近更新 更多