一.nop中的路由注冊
在Global.asax,Application_Start()方法中會進(jìn)行路由注冊,代碼如下。
1 public static void RegisterRoutes(RouteCollection routes) 2 { 3 routes.IgnoreRoute("favicon.ico"); 4 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 5 6 //register custom routes (plugins, etc) 7 var routePublisher = EngineContext.Current.Resolve<IRoutePublisher>(); 8 routePublisher.RegisterRoutes(routes); 9 10 routes.MapRoute( 11 "Default", // Route name 12 "{controller}/{action}/{id}", // URL with parameters 13 new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 14 new[] { "Nop.Web.Controllers" } 15 ); 16 }
我們會發(fā)現(xiàn)調(diào)用了IRutePublisher接口,該接口由Nop.Web.Framework.Mvc.Routes.RoutePublisher類實現(xiàn)。
并通過RegisterRoutes(RouteCollection routes)方法進(jìn)行路由注冊。代碼如下:
1 /// <summary> 2 /// Register routes 3 /// </summary> 4 /// <param name="routes">Routes</param> 5 public virtual void RegisterRoutes(RouteCollection routes) 6 { 7 //ITypeFinder接口獲取所有IRouteProvider接口實現(xiàn)類的Type對象 8 var routeProviderTypes = typeFinder.FindClassesOfType<IRouteProvider>(); 9 var routeProviders = new List<IRouteProvider>(); 10 foreach (var providerType in routeProviderTypes) 11 { 12 //Ignore not installed plugins 13 var plugin = FindPlugin(providerType);//PluginManager.ReferencedPlugins中查找該Type對象 14 if (plugin != null && !plugin.Installed)//插件不為空未安裝則跳出本次循環(huán) 15 continue; 16 17 var provider = Activator.CreateInstance(providerType) as IRouteProvider;//實例化IRouteProvider接口對象 18 routeProviders.Add(provider); 19 } 20 routeProviders = routeProviders.OrderByDescending(rp => rp.Priority).ToList();//排序 21 routeProviders.ForEach(rp => rp.RegisterRoutes(routes));//遍歷并調(diào)用RegisterRoutes(routes)進(jìn)行路由注冊 22 }
該方法做了如下工作:
第一步:通過ITyperFinder接口找到所有實現(xiàn)了IRouteProvider接口的類類型。保存在routeProviderTypes集合中
第二步:遍歷routeProviderTypes集合,通過PluginManager類找到未安裝IRouteProvider類類型。并從routeProviderTypes集合中排除掉。
第三步:實例化IRouteProvider實現(xiàn)類。
第四步:調(diào)用IRouteProvider實現(xiàn)類RegisterRoutes(routes)方法進(jìn)行路由注冊。
下圖為主要接口之間的調(diào)用關(guān)系
通過上述分析nop路由注冊主要是通過IRouteProvider接口實現(xiàn)的,現(xiàn)在我們看看項目中實現(xiàn)該接口的類都有哪些。
下圖紅色是在Nop.Web項目中,其他都是在nop插件中。
接下來我們看下路由的注冊順序如下圖,我們看到最先匹配的Nop.Web.Infrastructure.RouteProvider中的路由注冊。
二.啟用支持多語言的SEO友好鏈接
nop支持SEO友好鏈接,管理后臺->設(shè)置管理->綜合設(shè)置->啟用支持多語言的SEO友好鏈接 選中就可以支持了。
啟用后URL格式為: http://www.yourStore.com/en/ 或 http://www.yourStore.com/zh/ (SEO比較友好)
那該功能怎么實現(xiàn)的呢?接下來我們看看nop是如何通過路由擴(kuò)展實現(xiàn)的。
(Nop.Web.Framework.WebWorkContext在多語言中也會用到,這里先不講它,我們只說路由)
我們先看下Nop.Web.Infrastructure.RouteProvider中的路由注冊代碼
Nop.Web.Infrastructure.RouteProvider
Nop.Web.Framework.Localization.LocalizedRouteExtensions類中對RouteCollection routes添加了MapLocalizedRoute的擴(kuò)展方法
1 routes.MapLocalizedRoute("HomePage", 2 "", 3 new { controller = "Home", action = "Index" }, 4 new[] { "Nop.Web.Controllers" });
Nop.Web.Framework.Localization.LocalizedRoute繼承Route類進(jìn)行擴(kuò)展多語言Seo的支持
1 public static Route MapLocalizedRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) 2 { 3 if (routes == null) 4 { 5 throw new ArgumentNullException("routes"); 6 } 7 if (url == null) 8 { 9 throw new ArgumentNullException("url"); 10 } 11 //LocalizedRoute 進(jìn)行了多語言Seo優(yōu)化
12 var route = new LocalizedRoute(url, new MvcRouteHandler()) 13 { 14 Defaults = new RouteValueDictionary(defaults), 15 Constraints = new RouteValueDictionary(constraints), 16 DataTokens = new RouteValueDictionary() 17 }; 18 19 if ((namespaces != null) && (namespaces.Length > 0)) 20 { 21 route.DataTokens["Namespaces"] = namespaces; 22 } 23 24 routes.Add(name, route); 25 26 return route; 27 }
LocalizedRoute對路由進(jìn)行了擴(kuò)展,主要重寫了GetRouteData,和GetVirtualPath這兩個方法。
GetRouteData:解析Url,它的作用簡單理解是通過url匹配到正確的路由。
開啟多語言Seo后URL格式為: http://www.yourStore.com/en/ 或 http://www.yourStore.com/zh/ (SEO比較友好),
LocalizedRoute重寫GetRouteData方法,會去掉en或zh后,匹配正確的路由位置。
例如輸入http://localhost:15536/en,會正確的匹配到http://localhost:15536/
1 routes.MapLocalizedRoute("HomePage", 2 "", 3 new { controller = "Home", action = "Index" }, 4 new[] { "Nop.Web.Controllers" });
GetVirtualPath:生成Url,我們在Razor視圖中常會看到<a href="@Url.Action("Index", "Home")">首頁</a>這種標(biāo)簽,
GetVirtualPath負(fù)責(zé)將"@Url.Action("Index", "Home")"生成支持多語言Seo的url字符串http://www.yourStore.com/en/ ,自動會加上en或zh。
更好的理解GetRouteData和GetVirtualPath,可自行搜索下。
三.搜索引擎友好名稱實現(xiàn)
除了對多語言Seo友好鏈接支持,nop還支持Seo友好鏈接的支持。
我們發(fā)現(xiàn)Nop.Web.Infrastructure.GenericUrlRouteProvider類主要用于Seo友好鏈接的路由注冊,代碼如下:
Nop.Web.Infrastructure.GenericUrlRouteProvider
我們發(fā)現(xiàn)多了MapGenericPathRoute的擴(kuò)展
1 //generic URLs 2 routes.MapGenericPathRoute("GenericUrl", 3 "{generic_se_name}", 4 new {controller = "Common", action = "GenericUrl"}, 5 new[] {"Nop.Web.Controllers"});
我們來看看MapGenericPathRoute方法來自Nop.Web.Framework.Seo.GenericPathRouteExtensions類中。
通過Nop.Web.Framework.Seo.GenericPathRoute完成Seo友好鏈接的路由擴(kuò)展
1 public static Route MapGenericPathRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) 2 { 3 if (routes == null) 4 { 5 throw new ArgumentNullException("routes"); 6 } 7 if (url == null) 8 { 9 throw new ArgumentNullException("url"); 10 } 11 //GenericPathRoute中實現(xiàn)Seo友好鏈接路由 12 var route = new GenericPathRoute(url, new MvcRouteHandler()) 13 { 14 Defaults = new RouteValueDictionary(defaults), 15 Constraints = new RouteValueDictionary(constraints), 16 DataTokens = new RouteValueDictionary() 17 }; 18 19 if ((namespaces != null) && (namespaces.Length > 0)) 20 { 21 route.DataTokens["Namespaces"] = namespaces; 22 } 23 24 routes.Add(name, route); 25 26 return route; 27 }
GenericPathRoute對路由進(jìn)行擴(kuò)展,只重寫了GetRouteData方法用于解析url,幫助路由到正確的執(zhí)行位置。代碼如下:
GetRouteData
路由匹配到支持Seo友好鏈接會重定向鏈接新的路由位置,nop 3.9目前支持下圖中的路由
提示:數(shù)據(jù)庫UrlRecord表對Seo友情鏈接提供支持。
四.總結(jié)
1.繼承IRouteProvider對路由進(jìn)行擴(kuò)展。(注意路由注冊順序,ASP.NET MVC 只匹配第一次成功的路由信息)
2.多語言Seo友好鏈接通過LocalizedRoute類進(jìn)行路由擴(kuò)展(MapLocalizedRoute擴(kuò)展中調(diào)用)
3.頁面Seo友好鏈接通過GenericPathRoute類進(jìn)行路由擴(kuò)展(MapGenericPathRoute擴(kuò)展中調(diào)用)
文中有錯誤的理解和不正確的觀點,請留言,一起交流共同進(jìn)步。
本文地址:http://www.cnblogs.com/yaoshangjin/p/7228177.html
本文為大波浪原創(chuàng)、轉(zhuǎn)載請注明出處。
如果您認(rèn)為這篇文章還不錯或者有所收獲,可以點擊下方的【關(guān)注】按鈕,因為你的支持是我繼續(xù)寫作,分享的最大動力!
作者:大波浪
來源:http://www.cnblogs.com/yaoshangjin/
聲明: 本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。如果您發(fā)現(xiàn)博客中出現(xiàn)了錯誤,或者有更好的建議、想法,請及時與我聯(lián)系?。∪绻胝椅宜较陆涣?,可以私信或者加我QQ。
http://www.cnblogs.com/yaoshangjin/p/7228177.html