NopCommerce源码架构详解-路由相关源码分析

刚开始研究nop的同学要找到里面一个Url对应Controller相关代码,可能会有点晕,因为NopCommerce为了对seo友好。

NopCommerce源码架构详解概述

文章目录

概述

NopCommerce源码架构详解-路由相关源码分析。

内容

刚开始研究nop的同学要找到里面一个Url对应Controller相关代码,可能会有点晕。因为NopCommerce为了对seo友好,对其Url做了一些处理,自定义了路由规则,同时为了支持插件机制,加了一些自己的类进行扩展。本文就来分析一个NopCommerce路由相关源码设计思路,同样我们也先来看看相关的类图:

2020-04-23-02-13-38

上面就是NopCommerce路由相关功能主要的类、接口及关系。有以下类:

1、mvcApplication

2、IRoutePublisher、RoutePublisher

3、IRouteProvider、RouteProvider、GenericUrlRouteProvider

其中RoutePublisher是用来发布RouteProvider、GenericUrlRouteProvider里面配置的路由规则的,二者都有一个抽象的接口。接下来我们就来看看这些类或接口中代码是如何实现的:

Nop.Web.MvcApplication

 public static void RegisterRoutes(RouteCollection routes)
{
     routes.IgnoreRoute("favicon.ico");
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

     //注册自定义的路由规则及插件相关路由
     var routePublisher = EngineContext.Current.Resolve<IRoutePublisher>();
     routePublisher.RegisterRoutes(routes);

     routes.MapRoute(
          "Default", // Route name
          "{controller}/{action}/{id}", // URL with parameters
          new { controller = "Home", action = "Index", id = UrlParameter.Optional },
          new[] { "Nop.Web.Controllers" }
     );
}

EngineContext.Current.Resolve()这名代码表示,从Ioc容器Autofac中获取接口IRoutePublisher所依赖的具体实现类。如果对Nop的依赖注入原理还不是很了解,可以参考我之前的文章NopCommerce源码架构详解-Autofac依赖注入分析

在Nop.Web.Framework.DependencyRegistrar中有以下代码:

 builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().SingleInstance();

Nop.Web.Framework.Mvc.Routes.RoutePublisher

我们找到这个RoutePublisher类(Nop.Web.Framework.Mvc.Routes.RoutePublisher)其中关键的代码如下:

 public virtual void RegisterRoutes(RouteCollection routes)
{
     //通过typeFinder找出所有(包括插件)实现了接口IRouteProvider相关的类型
     var routeProviderTypes = typeFinder.FindClassesOfType<IRouteProvider>();
     var routeProviders = new List<IRouteProvider>();
     foreach (var providerType in routeProviderTypes)
     {
          //Ignore not installed plugins
          var plugin = FindPlugin(providerType);
          if (plugin != null && !plugin.Installed)
               continue;
          //采用反射动态创建IRouteProvider的具体类的实例
          var provider = Activator.CreateInstance(providerType) as IRouteProvider;
          routeProviders.Add(provider);
     }
     routeProviders = routeProviders.OrderByDescending(rp => rp.Priority).ToList();
     //依次调用RouteProvider的RegisterRoutes方法,注册路由规则
     routeProviders.ForEach(rp => rp.RegisterRoutes(routes));
}

Nop.Web.Infrastructure.RouteProvider

现在我们来看看一个具体的RouteProvider里面都有些什么东东。在项目Nop.Web根目录下面有一个文件夹Infrastructure,里面有一个RouteProvider类,如下图:

2020-04-23-02-13-57
 public void RegisterRoutes(RouteCollection routes)
{
    //We reordered our routes so the most used ones are on top. It can improve performance.

    //home page
    routes.MapLocalizedRoute("HomePage",
                    "",
                    new { controller = "Home", action = "Index" },
                    new[] { "Nop.Web.Controllers" });

    //widgets
    //we have this route for performance optimization because named routes are MUCH faster than usual Html.Action(...)
    //and this route is highly used
    routes.MapRoute("WidgetsByZone",
                    "widgetsbyzone/",
                    new { controller = "Widget", action = "WidgetsByZone" },
                    new[] { "Nop.Web.Controllers" });

    //login
    routes.MapLocalizedRoute("Login",
                    "login/",
                    new { controller = "Customer", action = "Login" },
                    new[] { "Nop.Web.Controllers" });
    //register
    routes.MapLocalizedRoute("Register",
                    "register/",
                    new { controller = "Customer", action = "Register" },
                    new[] { "Nop.Web.Controllers" });
    //logout
    routes.MapLocalizedRoute("Logout",
                    "logout/",
                    new { controller = "Customer", action = "Logout" },
                    new[] { "Nop.Web.Controllers" });

    //shopping cart
    routes.MapLocalizedRoute("ShoppingCart",
                    "cart/",
                    new { controller = "ShoppingCart", action = "Cart" },
                    new[] { "Nop.Web.Controllers" });
    //wishlist
    routes.MapLocalizedRoute("Wishlist",
                    "wishlist/{customerGuid}",
                    new { controller = "ShoppingCart", action = "Wishlist", customerGuid = UrlParameter.Optional },
                    new[] { "Nop.Web.Controllers" });

    //customer
    routes.MapLocalizedRoute("CustomerInfo",
                    "customer/info",
                    new { controller = "Customer", action = "Info" },
                    new[] { "Nop.Web.Controllers" });
    //....省略剩余代码
}

RouteProvider的方法RegisterRoutes就是真正自定义路由规则。我们如果要找一个Url对应的Controller就要先在这里面查找一下,才好定位到是哪一个Controller。至于插件的路由我接下来会用专门一篇文章来介绍Nop的插件机制。

Nop.Web.Infrastructure.GenericUrlRouteProvider

GenericUrlRouteProvider和Nop.Web.Infrastructure.RouteProvider是相同级别的都是实现了接口IRouteProvider,区别GenericUrlRouteProvider定义的一般公用的Url规则。如下代码:

 public partial class GenericUrlRouteProvider : IRouteProvider
{
    public void RegisterRoutes(RouteCollection routes)
    {
        //generic URLs
        routes.MapGenericPathRoute("GenericUrl",
                                   "{generic_se_name}",
                                   new {controller = "Common", action = "GenericUrl"},
                                   new[] {"Nop.Web.Controllers"});

        //define this routes to use in UI views (in case if you want to customize some of them later)
        routes.MapLocalizedRoute("Product",
                                 "{SeName}",
                                 new { controller = "Product", action = "ProductDetails" },
                                 new[] {"Nop.Web.Controllers"});

        routes.MapLocalizedRoute("Category",
                        "{SeName}",
                        new { controller = "Catalog", action = "Category" },
                        new[] { "Nop.Web.Controllers" });

        routes.MapLocalizedRoute("Manufacturer",
                        "{SeName}",
                        new { controller = "Catalog", action = "Manufacturer" },
                        new[] { "Nop.Web.Controllers" });

        routes.MapLocalizedRoute("Vendor",
                        "{SeName}",
                        new { controller = "Catalog", action = "Vendor" },
                        new[] { "Nop.Web.Controllers" });

        routes.MapLocalizedRoute("NewsItem",
                        "{SeName}",
                        new { controller = "News", action = "NewsItem" },
                        new[] { "Nop.Web.Controllers" });

        routes.MapLocalizedRoute("BlogPost",
                        "{SeName}",
                        new { controller = "Blog", action = "BlogPost" },
                        new[] { "Nop.Web.Controllers" });

        routes.MapLocalizedRoute("Topic",
                        "{SeName}",
                        new { controller = "Topic", action = "TopicDetails" },
                        new[] { "Nop.Web.Controllers" });     
    }

    public int Priority
    {
        get
        {
            //it should be the last route
            //we do not set it to -int.MaxValue so it could be overriden (if required)
            return -1000000;
        }
    }
}

可以看到上面定义了商品列表、商品详情及新闻等相关的Url规则。

原文出处:蓝狐软件工作室【蓝狐】

原文链接:http://m.lanhusoft.com/Article/349.html

本文观点不代表 .Net中文网 立场,转载请联系原作者。

发表评论

登录后才能评论