一、導圖和基礎介紹

本文主要介紹NopCommerce的路由機制,網上有一篇不錯的文章,有興趣的可以看看NopCommerce源碼架構詳解--對seo友好Url的路由機制實作源碼分析
SEO,Search Engine Optimization,中文叫做搜尋引擎優化,主要是為了提高網站關鍵詞排名,提高通路量。SEO是一個很廣的話題,我們這裡主要了解NopCommerce的友好Url機制(它是實作SEO的一個步驟)。
二、承上啟下
我的NopCommerce之旅(6): 應用啟動中介紹在應用啟動時,進行了常見的MVC物件的注冊,包括Area、Route。這裡通過調用公共接口方法,調用了所有實作了公共接口的類,實作對所有路由的注冊。
1 //Registering some regular mvc stuff
2 AreaRegistration.RegisterAllAreas();
3 RegisterRoutes(RouteTable.Routes);
1 //register custom routes (plugins, etc)
2 var routePublisher = EngineContext.Current.Resolve<IRoutePublisher>();
3 routePublisher.RegisterRoutes(routes);
1 /// <summary>
2 /// Register routes
3 /// </summary>
4 /// <param name="routes">Routes</param>
5 public virtual void RegisterRoutes(RouteCollection routes)
6 {
7 var routeProviderTypes = typeFinder.FindClassesOfType<IRouteProvider>();
8 var routeProviders = new List<IRouteProvider>();
9 foreach (var providerType in routeProviderTypes)
10 {
11 //Ignore not installed plugins
12 var plugin = FindPlugin(providerType);
13 if (plugin != null && !plugin.Installed)
14 continue;
15
16 var provider = Activator.CreateInstance(providerType) as IRouteProvider;
17 routeProviders.Add(provider);
18 }
19 routeProviders = routeProviders.OrderByDescending(rp => rp.Priority).ToList();
20 routeProviders.ForEach(rp => rp.RegisterRoutes(routes));//根據順序,注冊路由
21 }
三、公共接口
Nop.Web.Framework.Mvc.Routes.IRouteProvider,核心路由、友好路由以及Plugin等實作該接口進行路由注冊。
Nop.Web.Framework.Mvc.Routes.IRoutePublisher
四、注冊實作
1.核心路由注冊,包括首頁、部件、登入注冊、購物車等,代碼位置為Nop.Web.Infrastructure.RouteProvider。
1 public void RegisterRoutes(RouteCollection routes)
2 {
3 //We reordered our routes so the most used ones are on top. It can improve performance.
4
5 //home page
6 routes.MapLocalizedRoute("HomePage",
7 "",
8 new { controller = "Home", action = "Index" },
9 new[] { "Nop.Web.Controllers" });
10
11 //widgets
12 //we have this route for performance optimization because named routes are MUCH faster than usual Html.Action(...)
13 //and this route is highly used
14 routes.MapRoute("WidgetsByZone",
15 "widgetsbyzone/",
16 new { controller = "Widget", action = "WidgetsByZone" },
17 new[] { "Nop.Web.Controllers" });
18
19 //login
20 routes.MapLocalizedRoute("Login",
21 "login/",
22 new { controller = "Customer", action = "Login" },
23 new[] { "Nop.Web.Controllers" });
24 //register
25 routes.MapLocalizedRoute("Register",
26 "register/",
27 new { controller = "Customer", action = "Register" },
28 new[] { "Nop.Web.Controllers" });
29 //logout
30 routes.MapLocalizedRoute("Logout",
31 "logout/",
32 new { controller = "Customer", action = "Logout" },
33 new[] { "Nop.Web.Controllers" });
34
35 //shopping cart
36 routes.MapLocalizedRoute("ShoppingCart",
37 "cart/",
38 new { controller = "ShoppingCart", action = "Cart" },
39 new[] { "Nop.Web.Controllers" });
40 //wishlist
41 routes.MapLocalizedRoute("Wishlist",
42 "wishlist/{customerGuid}",
43 new { controller = "ShoppingCart", action = "Wishlist", customerGuid = UrlParameter.Optional },
44 new[] { "Nop.Web.Controllers" });
45
46 //customer account links
47 routes.MapLocalizedRoute("CustomerInfo",
48 "customer/info",
49 new { controller = "Customer", action = "Info" },
50 new[] { "Nop.Web.Controllers" });
51 ...
52
53 //contact us
54 routes.MapLocalizedRoute("ContactUs",
55 "contactus",
56 new { controller = "Common", action = "ContactUs" },
57 new[] { "Nop.Web.Controllers" });
58 //sitemap
59 routes.MapLocalizedRoute("Sitemap",
60 "sitemap",
61 new { controller = "Common", action = "Sitemap" },
62 new[] { "Nop.Web.Controllers" });
63
64 //product search
65 routes.MapLocalizedRoute("ProductSearch",
66 "search/",
67 new { controller = "Catalog", action = "Search" },
68 new[] { "Nop.Web.Controllers" });
69 routes.MapLocalizedRoute("ProductSearchAutoComplete",
70 "catalog/searchtermautocomplete",
71 new { controller = "Catalog", action = "SearchTermAutoComplete" },
72 new[] { "Nop.Web.Controllers" });
73
74 //change currency (AJAX link)
75 routes.MapLocalizedRoute("ChangeCurrency",
76 "changecurrency/{customercurrency}",
77 new { controller = "Common", action = "SetCurrency" },
78 new { customercurrency = @"\d+" },
79 new[] { "Nop.Web.Controllers" });
80 //change language (AJAX link)
81 routes.MapLocalizedRoute("ChangeLanguage",
82 "changelanguage/{langid}",
83 new { controller = "Common", action = "SetLanguage" },
84 new { langid = @"\d+" },
85 new[] { "Nop.Web.Controllers" });
86 //change tax (AJAX link)
87 routes.MapLocalizedRoute("ChangeTaxType",
88 "changetaxtype/{customertaxtype}",
89 new { controller = "Common", action = "SetTaxType" },
90 new { customertaxtype = @"\d+" },
91 new[] { "Nop.Web.Controllers" });
92
93 //recently viewed products
94 routes.MapLocalizedRoute("RecentlyViewedProducts",
95 "recentlyviewedproducts/",
96 new { controller = "Product", action = "RecentlyViewedProducts" },
97 new[] { "Nop.Web.Controllers" });
98 //new products
99 routes.MapLocalizedRoute("NewProducts",
100 "newproducts/",
101 new { controller = "Product", action = "NewProducts" },
102 new[] { "Nop.Web.Controllers" });
103 //blog
104 routes.MapLocalizedRoute("Blog",
105 "blog",
106 new { controller = "Blog", action = "List" },
107 new[] { "Nop.Web.Controllers" });
108 //news
109 routes.MapLocalizedRoute("NewsArchive",
110 "news",
111 new { controller = "News", action = "List" },
112 new[] { "Nop.Web.Controllers" });
113
114 //forum
115 routes.MapLocalizedRoute("Boards",
116 "boards",
117 new { controller = "Boards", action = "Index" },
118 new[] { "Nop.Web.Controllers" });
119
120 //compare products
121 routes.MapLocalizedRoute("CompareProducts",
122 "compareproducts/",
123 new { controller = "Product", action = "CompareProducts" },
124 new[] { "Nop.Web.Controllers" });
125
126 //product tags
127 routes.MapLocalizedRoute("ProductTagsAll",
128 "producttag/all/",
129 new { controller = "Catalog", action = "ProductTagsAll" },
130 new[] { "Nop.Web.Controllers" });
131
132 //manufacturers
133 routes.MapLocalizedRoute("ManufacturerList",
134 "manufacturer/all/",
135 new { controller = "Catalog", action = "ManufacturerAll" },
136 new[] { "Nop.Web.Controllers" });
137 //vendors
138 routes.MapLocalizedRoute("VendorList",
139 "vendor/all/",
140 new { controller = "Catalog", action = "VendorAll" },
141 new[] { "Nop.Web.Controllers" });
142
143
144 //add product to cart (without any attributes and options). used on catalog pages.
145 routes.MapLocalizedRoute("AddProductToCart-Catalog",
146 "addproducttocart/catalog/{productId}/{shoppingCartTypeId}/{quantity}",
147 new { controller = "ShoppingCart", action = "AddProductToCart_Catalog" },
148 new { productId = @"\d+", shoppingCartTypeId = @"\d+", quantity = @"\d+" },
149 new[] { "Nop.Web.Controllers" });
150 //add product to cart (with attributes and options). used on the product details pages.
151 routes.MapLocalizedRoute("AddProductToCart-Details",
152 "addproducttocart/details/{productId}/{shoppingCartTypeId}",
153 new { controller = "ShoppingCart", action = "AddProductToCart_Details" },
154 new { productId = @"\d+", shoppingCartTypeId = @"\d+" },
155 new[] { "Nop.Web.Controllers" });
156
157 //product tags
158 routes.MapLocalizedRoute("ProductsByTag",
159 "producttag/{productTagId}/{SeName}",
160 new { controller = "Catalog", action = "ProductsByTag", SeName = UrlParameter.Optional },
161 new { productTagId = @"\d+" },
162 new[] { "Nop.Web.Controllers" });
163 //comparing products
164 routes.MapLocalizedRoute("AddProductToCompare",
165 "compareproducts/add/{productId}",
166 new { controller = "Product", action = "AddProductToCompareList" },
167 new { productId = @"\d+" },
168 new[] { "Nop.Web.Controllers" });
169 //product email a friend
170 routes.MapLocalizedRoute("ProductEmailAFriend",
171 "productemailafriend/{productId}",
172 new { controller = "Product", action = "ProductEmailAFriend" },
173 new { productId = @"\d+" },
174 new[] { "Nop.Web.Controllers" });
175 //reviews
176 routes.MapLocalizedRoute("ProductReviews",
177 "productreviews/{productId}",
178 new { controller = "Product", action = "ProductReviews" },
179 new[] { "Nop.Web.Controllers" });
180 //back in stock notifications
181 routes.MapLocalizedRoute("BackInStockSubscribePopup",
182 "backinstocksubscribe/{productId}",
183 new { controller = "BackInStockSubscription", action = "SubscribePopup" },
184 new { productId = @"\d+" },
185 new[] { "Nop.Web.Controllers" });
186 //downloads
187 routes.MapRoute("GetSampleDownload",
188 "download/sample/{productid}",
189 new { controller = "Download", action = "Sample" },
190 new { productid = @"\d+" },
191 new[] { "Nop.Web.Controllers" });
192
193
194
195 //checkout pages
196 routes.MapLocalizedRoute("Checkout",
197 "checkout/",
198 new { controller = "Checkout", action = "Index" },
199 new[] { "Nop.Web.Controllers" });
200 ...
201
202 //subscribe newsletters
203 routes.MapLocalizedRoute("SubscribeNewsletter",
204 "subscribenewsletter",
205 new { controller = "Newsletter", action = "SubscribeNewsletter" },
206 new[] { "Nop.Web.Controllers" });
207
208 //email wishlist
209 routes.MapLocalizedRoute("EmailWishlist",
210 "emailwishlist",
211 new { controller = "ShoppingCart", action = "EmailWishlist" },
212 new[] { "Nop.Web.Controllers" });
213
214 //login page for checkout as guest
215 routes.MapLocalizedRoute("LoginCheckoutAsGuest",
216 "login/checkoutasguest",
217 new { controller = "Customer", action = "Login", checkoutAsGuest = true },
218 new[] { "Nop.Web.Controllers" });
219 //register result page
220 routes.MapLocalizedRoute("RegisterResult",
221 "registerresult/{resultId}",
222 new { controller = "Customer", action = "RegisterResult" },
223 new { resultId = @"\d+" },
224 new[] { "Nop.Web.Controllers" });
225 //check username availability
226 routes.MapLocalizedRoute("CheckUsernameAvailability",
227 "customer/checkusernameavailability",
228 new { controller = "Customer", action = "CheckUsernameAvailability" },
229 new[] { "Nop.Web.Controllers" });
230
231 //passwordrecovery
232 routes.MapLocalizedRoute("PasswordRecovery",
233 "passwordrecovery",
234 new { controller = "Customer", action = "PasswordRecovery" },
235 new[] { "Nop.Web.Controllers" });
236 //password recovery confirmation
237 routes.MapLocalizedRoute("PasswordRecoveryConfirm",
238 "passwordrecovery/confirm",
239 new { controller = "Customer", action = "PasswordRecoveryConfirm" },
240 new[] { "Nop.Web.Controllers" });
241
242 //topics
243 routes.MapLocalizedRoute("TopicPopup",
244 "t-popup/{SystemName}",
245 new { controller = "Topic", action = "TopicDetailsPopup" },
246 new[] { "Nop.Web.Controllers" });
247
248 //blog
249 routes.MapLocalizedRoute("BlogByTag",
250 "blog/tag/{tag}",
251 new { controller = "Blog", action = "BlogByTag" },
252 new[] { "Nop.Web.Controllers" });
253 routes.MapLocalizedRoute("BlogByMonth",
254 "blog/month/{month}",
255 new { controller = "Blog", action = "BlogByMonth" },
256 new[] { "Nop.Web.Controllers" });
257 //blog RSS
258 routes.MapLocalizedRoute("BlogRSS",
259 "blog/rss/{languageId}",
260 new { controller = "Blog", action = "ListRss" },
261 new { languageId = @"\d+" },
262 new[] { "Nop.Web.Controllers" });
263
264 //news RSS
265 routes.MapLocalizedRoute("NewsRSS",
266 "news/rss/{languageId}",
267 new { controller = "News", action = "ListRss" },
268 new { languageId = @"\d+" },
269 new[] { "Nop.Web.Controllers" });
270
271 //set review helpfulness (AJAX link)
272 routes.MapRoute("SetProductReviewHelpfulness",
273 "setproductreviewhelpfulness",
274 new { controller = "Product", action = "SetProductReviewHelpfulness" },
275 new[] { "Nop.Web.Controllers" });
276
277 //customer account links
278 routes.MapLocalizedRoute("CustomerReturnRequests",
279 "returnrequest/history",
280 new { controller = "ReturnRequest", action = "CustomerReturnRequests" },
281 new[] { "Nop.Web.Controllers" });
282 ...
283 //customer profile page
284 routes.MapLocalizedRoute("CustomerProfile",
285 "profile/{id}",
286 new { controller = "Profile", action = "Index" },
287 new { id = @"\d+" },
288 new[] { "Nop.Web.Controllers" });
289 routes.MapLocalizedRoute("CustomerProfilePaged",
290 "profile/{id}/page/{page}",
291 new { controller = "Profile", action = "Index" },
292 new { id = @"\d+", page = @"\d+" },
293 new[] { "Nop.Web.Controllers" });
294
295 //orders
296 routes.MapLocalizedRoute("OrderDetails",
297 "orderdetails/{orderId}",
298 new { controller = "Order", action = "Details" },
299 new { orderId = @"\d+" },
300 new[] { "Nop.Web.Controllers" });
301 ...
302 //order downloads
303 routes.MapRoute("GetDownload",
304 "download/getdownload/{orderItemId}/{agree}",
305 new { controller = "Download", action = "GetDownload", agree = UrlParameter.Optional },
306 new { orderItemId = new GuidConstraint(false) },
307 new[] { "Nop.Web.Controllers" });
308 ...
309
310 //contact vendor
311 routes.MapLocalizedRoute("ContactVendor",
312 "contactvendor/{vendorId}",
313 new { controller = "Common", action = "ContactVendor" },
314 new[] { "Nop.Web.Controllers" });
315 //apply for vendor account
316 routes.MapLocalizedRoute("ApplyVendorAccount",
317 "vendor/apply",
318 new { controller = "Vendor", action = "ApplyVendor" },
319 new[] { "Nop.Web.Controllers" });
320
321 //poll vote AJAX link
322 routes.MapLocalizedRoute("PollVote",
323 "poll/vote",
324 new { controller = "Poll", action = "Vote" },
325 new[] { "Nop.Web.Controllers" });
326
327 //comparing products
328 routes.MapLocalizedRoute("RemoveProductFromCompareList",
329 "compareproducts/remove/{productId}",
330 new { controller = "Product", action = "RemoveProductFromCompareList" },
331 new[] { "Nop.Web.Controllers" });
332 routes.MapLocalizedRoute("ClearCompareList",
333 "clearcomparelist/",
334 new { controller = "Product", action = "ClearCompareList" },
335 new[] { "Nop.Web.Controllers" });
336
337 //new RSS
338 routes.MapLocalizedRoute("NewProductsRSS",
339 "newproducts/rss",
340 new { controller = "Product", action = "NewProductsRss" },
341 new[] { "Nop.Web.Controllers" });
342
343 //get state list by country ID (AJAX link)
344 routes.MapRoute("GetStatesByCountryId",
345 "country/getstatesbycountryid/",
346 new { controller = "Country", action = "GetStatesByCountryId" },
347 new[] { "Nop.Web.Controllers" });
348
349 //EU Cookie law accept button handler (AJAX link)
350 routes.MapRoute("EuCookieLawAccept",
351 "eucookielawaccept",
352 new { controller = "Common", action = "EuCookieLawAccept" },
353 new[] { "Nop.Web.Controllers" });
354
355 //authenticate topic AJAX link
356 routes.MapLocalizedRoute("TopicAuthenticate",
357 "topic/authenticate",
358 new { controller = "Topic", action = "Authenticate" },
359 new[] { "Nop.Web.Controllers" });
360
361 //product attributes with "upload file" type
362 routes.MapLocalizedRoute("UploadFileProductAttribute",
363 "uploadfileproductattribute/{attributeId}",
364 new { controller = "ShoppingCart", action = "UploadFileProductAttribute" },
365 new { attributeId = @"\d+" },
366 new[] { "Nop.Web.Controllers" });
367 //checkout attributes with "upload file" type
368 routes.MapLocalizedRoute("UploadFileCheckoutAttribute",
369 "uploadfilecheckoutattribute/{attributeId}",
370 new { controller = "ShoppingCart", action = "UploadFileCheckoutAttribute" },
371 new { attributeId = @"\d+" },
372 new[] { "Nop.Web.Controllers" });
373
374 //forums
375 routes.MapLocalizedRoute("ActiveDiscussions",
376 "boards/activediscussions",
377 new { controller = "Boards", action = "ActiveDiscussions" },
378 new[] { "Nop.Web.Controllers" });
379 ...
380
381 //private messages
382 routes.MapLocalizedRoute("PrivateMessages",
383 "privatemessages/{tab}",
384 new { controller = "PrivateMessages", action = "Index", tab = UrlParameter.Optional },
385 new[] { "Nop.Web.Controllers" });
386 ...
387
388 //activate newsletters
389 routes.MapLocalizedRoute("NewsletterActivation",
390 "newsletter/subscriptionactivation/{token}/{active}",
391 new { controller = "Newsletter", action = "SubscriptionActivation" },
392 new { token = new GuidConstraint(false) },
393 new[] { "Nop.Web.Controllers" });
394
395 //robots.txt
396 routes.MapRoute("robots.txt",
397 "robots.txt",
398 new { controller = "Common", action = "RobotsTextFile" },
399 new[] { "Nop.Web.Controllers" });
400
401 //sitemap (XML)
402 routes.MapLocalizedRoute("sitemap.xml",
403 "sitemap.xml",
404 new { controller = "Common", action = "SitemapXml" },
405 new[] { "Nop.Web.Controllers" });
406
407 //store closed
408 routes.MapLocalizedRoute("StoreClosed",
409 "storeclosed",
410 new { controller = "Common", action = "StoreClosed" },
411 new[] { "Nop.Web.Controllers" });
412
413 //install
414 routes.MapRoute("Installation",
415 "install",
416 new { controller = "Install", action = "Index" },
417 new[] { "Nop.Web.Controllers" });
418
419 //page not found
420 routes.MapLocalizedRoute("PageNotFound",
421 "page-not-found",
422 new { controller = "Common", action = "PageNotFound" },
423 new[] { "Nop.Web.Controllers" });
424 }
View Code
2.SEO友好路由注冊,包括産品、種類、生産商、供應商、新聞、部落格、主題等具體資訊的路由,代碼位置為Nop.Web.Infrastructure.GenericUrlRouteProvider。
經過優化過的友好Url為http://localhost/apple-macbook-pro-13-inch,而經過解析後通路的實際http://localhost/Product/ProductDetails/{productId}。
1 public void RegisterRoutes(RouteCollection routes)
2 {
3 //generic URLs
4 routes.MapGenericPathRoute("GenericUrl",
5 "{generic_se_name}",
6 new {controller = "Common", action = "GenericUrl"},
7 new[] {"Nop.Web.Controllers"});
8
9 //define this routes to use in UI views (in case if you want to customize some of them later)
10 routes.MapLocalizedRoute("Product",
11 "{SeName}",
12 new { controller = "Product", action = "ProductDetails" },
13 new[] {"Nop.Web.Controllers"});
14
15 routes.MapLocalizedRoute("Category",
16 "{SeName}",
17 new { controller = "Catalog", action = "Category" },
18 new[] { "Nop.Web.Controllers" });
19
20 routes.MapLocalizedRoute("Manufacturer",
21 "{SeName}",
22 new { controller = "Catalog", action = "Manufacturer" },
23 new[] { "Nop.Web.Controllers" });
24
25 routes.MapLocalizedRoute("Vendor",
26 "{SeName}",
27 new { controller = "Catalog", action = "Vendor" },
28 new[] { "Nop.Web.Controllers" });
29
30 routes.MapLocalizedRoute("NewsItem",
31 "{SeName}",
32 new { controller = "News", action = "NewsItem" },
33 new[] { "Nop.Web.Controllers" });
34
35 routes.MapLocalizedRoute("BlogPost",
36 "{SeName}",
37 new { controller = "Blog", action = "BlogPost" },
38 new[] { "Nop.Web.Controllers" });
39
40 routes.MapLocalizedRoute("Topic",
41 "{SeName}",
42 new { controller = "Topic", action = "TopicDetails" },
43 new[] { "Nop.Web.Controllers" });
44
45
46
47 //the last route. it's used when none of registered routes could be used for the current request
48 //but it this case we cannot process non-registered routes (/controller/action)
49 //routes.MapLocalizedRoute(
50 // "PageNotFound-Wildchar",
51 // "{*url}",
52 // new { controller = "Common", action = "PageNotFound" },
53 // new[] { "Nop.Web.Controllers" });
54 }
View Code
五、友好Url解析
NopCommerce中通過繼承Route類,重寫RouteData GetRouteData(HttpContextBase httpContext)方法來擷取真正路由。代碼位置為Nop.Web.Framework.Localization.LocalizedRoute和Nop.Web.Framework.Seo.GenericPathRoute。
GenericPathRoute類的GetRouteData()方法是我們要講的重點,它實作了友好Url的解析。下面是方法代碼的分析:
1.擷取Url的辨別值。
擷取請求中generic_se_name的值。
1 public override RouteData GetRouteData(HttpContextBase httpContext)
2 {
3 RouteData data = base.GetRouteData(httpContext);
4 if (data != null && DataSettingsHelper.DatabaseIsInstalled())
5 {
6 var urlRecordService = EngineContext.Current.Resolve<IUrlRecordService>();
7 var slug = data.Values["generic_se_name"] as string;//擷取辨別值,如"apple-macbook-pro-13-inch" 8 ...
9 }
10 return data;
11 }
2.根據辨別解析實際路由資訊
2.1 從緩存中讀取該辨別關聯的值,值包括通路的controller和Id
1 public override RouteData GetRouteData(HttpContextBase httpContext)
2 {
3 ...
4 var slug = data.Values["generic_se_name"] as string;
5 //performance optimization.
6 //we load a cached verion here. it reduces number of SQL requests for each page load
7 var urlRecord = urlRecordService.GetBySlugCached(slug);
8 ...
9 }
1 /// <summary>
2 /// Find URL record (cached version).
3 /// This method works absolutely the same way as "GetBySlug" one but caches the results.
4 /// Hence, it's used only for performance optimization in public store
5 /// </summary>
6 /// <param name="slug">Slug</param>
7 /// <returns>Found URL record</returns>
8 public virtual UrlRecordForCaching GetBySlugCached(string slug)
9 {
10 if (String.IsNullOrEmpty(slug))
11 return null;
12
13 if (_localizationSettings.LoadAllUrlRecordsOnStartup)
14 {
15 //load all records (we know they are cached)
16 var source = GetAllUrlRecordsCached();
17 var query = from ur in source
18 where ur.Slug.Equals(slug, StringComparison.InvariantCultureIgnoreCase)
19 select ur;
20 var urlRecordForCaching = query.FirstOrDefault();
21 return urlRecordForCaching;
22 }
23
24 //gradual loading
25 string key = string.Format(URLRECORD_BY_SLUG_KEY, slug);
26 return _cacheManager.Get(key, () =>
27 {
28 var urlRecord = GetBySlug(slug);//從資料庫讀取
29 if (urlRecord == null)
30 return null;
31
32 var urlRecordForCaching = Map(urlRecord);
33 return urlRecordForCaching;
34 });
35 }
2.2 若緩存中不存在則讀取資料庫資料,資料庫表為[dbo].[UrlRecord]
1 /// <summary>
2 /// Find URL record
3 /// </summary>
4 /// <param name="slug">Slug</param>
5 /// <returns>Found URL record</returns>
6 public virtual UrlRecord GetBySlug(string slug)
7 {
8 if (String.IsNullOrEmpty(slug))
9 return null;
10
11 var query = from ur in _urlRecordRepository.Table
12 where ur.Slug == slug
13 select ur;
14 var urlRecord = query.FirstOrDefault();
15 return urlRecord;
16 }
2.3 根據讀取的值的EntityName,傳回路由資訊。
1 //process URL
2 switch (urlRecord.EntityName.ToLowerInvariant())
3 {
4 case "product":
5 {
6 data.Values["controller"] = "Product";
7 data.Values["action"] = "ProductDetails";
8 data.Values["productid"] = urlRecord.EntityId;
9 data.Values["SeName"] = urlRecord.Slug;
10 ...
3.通路路由資訊
轉載于:https://www.cnblogs.com/devilsky/p/5368570.html