NopCommerce Url分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | using System; using System.Web; using System.Web.Routing; using Nop.Core; using Nop.Core.Data; using Nop.Core.Infrastructure; using Nop.Services.Events; using Nop.Services.Seo; using Nop.Web.Framework.Localization; namespace Nop.Web.Framework.Seo { /// <summary> /// Provides properties and methods for defining a SEO friendly route, and for getting information about the route. /// </summary> public partial class GenericPathRoute : LocalizedRoute { #region Constructors /// <summary> /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern and handler class. /// </summary> /// <param name="url">The URL pattern for the route.</param> /// <param name="routeHandler">The object that processes requests for the route.</param> public GenericPathRoute( string url, IRouteHandler routeHandler) : base (url, routeHandler) { } /// <summary> /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern, handler class and default parameter values. /// </summary> /// <param name="url">The URL pattern for the route.</param> /// <param name="defaults">The values to use if the URL does not contain all the parameters.</param> /// <param name="routeHandler">The object that processes requests for the route.</param> public GenericPathRoute( string url, RouteValueDictionary defaults, IRouteHandler routeHandler) : base (url, defaults, routeHandler) { } /// <summary> /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern, handler class, default parameter values and constraints. /// </summary> /// <param name="url">The URL pattern for the route.</param> /// <param name="defaults">The values to use if the URL does not contain all the parameters.</param> /// <param name="constraints">A regular expression that specifies valid values for a URL parameter.</param> /// <param name="routeHandler">The object that processes requests for the route.</param> public GenericPathRoute( string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler) : base (url, defaults, constraints, routeHandler) { } /// <summary> /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern, handler class, default parameter values, /// constraints,and custom values. /// </summary> /// <param name="url">The URL pattern for the route.</param> /// <param name="defaults">The values to use if the URL does not contain all the parameters.</param> /// <param name="constraints">A regular expression that specifies valid values for a URL parameter.</param> /// <param name="dataTokens">Custom values that are passed to the route handler, but which are not used to determine whether the route matches a specific URL pattern. The route handler might need these values to process the request.</param> /// <param name="routeHandler">The object that processes requests for the route.</param> public GenericPathRoute( string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler) : base (url, defaults, constraints, dataTokens, routeHandler) { } #endregion #region Methods /// <summary> /// Returns information about the requested route. /// </summary> /// <param name="httpContext">An object that encapsulates information about the HTTP request.</param> /// <returns> /// An object that contains the values from the route definition. /// </returns> public override RouteData GetRouteData(HttpContextBase httpContext) { RouteData data = base .GetRouteData(httpContext); if (data != null && DataSettingsHelper.DatabaseIsInstalled()) { var urlRecordService = EngineContext.Current.Resolve<IUrlRecordService>(); var slug = data.Values[ "generic_se_name" ] as string ; //performance optimization. //we load a cached verion here. it reduces number of SQL requests for each page load var urlRecord = urlRecordService.GetBySlugCached(slug); //comment the line above and uncomment the line below in order to disable this performance "workaround" //var urlRecord = urlRecordService.GetBySlug(slug); if (urlRecord == null ) { //no URL record found //var webHelper = EngineContext.Current.Resolve<IWebHelper>(); //var response = httpContext.Response; //response.Status = "302 Found"; //response.RedirectLocation = webHelper.GetStoreLocation(false); //response.End(); //return null; data.Values[ "controller" ] = "Common" ; data.Values[ "action" ] = "PageNotFound" ; return data; } //ensre that URL record is active if (!urlRecord.IsActive) { //URL record is not active. let's find the latest one var activeSlug = urlRecordService.GetActiveSlug(urlRecord.EntityId, urlRecord.EntityName, urlRecord.LanguageId); if ( string .IsNullOrWhiteSpace(activeSlug)) { //no active slug found //var webHelper = EngineContext.Current.Resolve<IWebHelper>(); //var response = httpContext.Response; //response.Status = "302 Found"; //response.RedirectLocation = webHelper.GetStoreLocation(false); //response.End(); //return null; data.Values[ "controller" ] = "Common" ; data.Values[ "action" ] = "PageNotFound" ; return data; } //the active one is found var webHelper = EngineContext.Current.Resolve<IWebHelper>(); var response = httpContext.Response; response.Status = "301 Moved Permanently" ; response.RedirectLocation = string .Format( "{0}{1}" , webHelper.GetStoreLocation( false ), activeSlug); response.End(); return null ; } //ensure that the slug is the same for the current language //otherwise, it can cause some issues when customers choose a new language but a slug stays the same var workContext = EngineContext.Current.Resolve<IWorkContext>(); var slugForCurrentLanguage = SeoExtensions.GetSeName(urlRecord.EntityId, urlRecord.EntityName, workContext.WorkingLanguage.Id); if (!String.IsNullOrEmpty(slugForCurrentLanguage) && !slugForCurrentLanguage.Equals(slug, StringComparison.InvariantCultureIgnoreCase)) { //we should make not null or "" validation above because some entities does not have SeName for standard (ID=0) language (e.g. news, blog posts) var webHelper = EngineContext.Current.Resolve<IWebHelper>(); var response = httpContext.Response; //response.Status = "302 Found"; response.Status = "302 Moved Temporarily" ; response.RedirectLocation = string .Format( "{0}{1}" , webHelper.GetStoreLocation( false ), slugForCurrentLanguage); response.End(); return null ; } //process URL switch (urlRecord.EntityName.ToLowerInvariant()) { case "product" : { data.Values[ "controller" ] = "Product" ; data.Values[ "action" ] = "ProductDetails" ; data.Values[ "productid" ] = urlRecord.EntityId; data.Values[ "SeName" ] = urlRecord.Slug; } break ; case "category" : { data.Values[ "controller" ] = "Catalog" ; data.Values[ "action" ] = "Category" ; data.Values[ "categoryid" ] = urlRecord.EntityId; data.Values[ "SeName" ] = urlRecord.Slug; } break ; case "manufacturer" : { data.Values[ "controller" ] = "Catalog" ; data.Values[ "action" ] = "Manufacturer" ; data.Values[ "manufacturerid" ] = urlRecord.EntityId; data.Values[ "SeName" ] = urlRecord.Slug; } break ; case "vendor" : { data.Values[ "controller" ] = "Catalog" ; data.Values[ "action" ] = "Vendor" ; data.Values[ "vendorid" ] = urlRecord.EntityId; data.Values[ "SeName" ] = urlRecord.Slug; } break ; case "newsitem" : { data.Values[ "controller" ] = "News" ; data.Values[ "action" ] = "NewsItem" ; data.Values[ "newsItemId" ] = urlRecord.EntityId; data.Values[ "SeName" ] = urlRecord.Slug; } break ; case "blogpost" : { data.Values[ "controller" ] = "Blog" ; data.Values[ "action" ] = "BlogPost" ; data.Values[ "blogPostId" ] = urlRecord.EntityId; data.Values[ "SeName" ] = urlRecord.Slug; } break ; case "topic" : { data.Values[ "controller" ] = "Topic" ; data.Values[ "action" ] = "TopicDetails" ; data.Values[ "topicId" ] = urlRecord.EntityId; data.Values[ "SeName" ] = urlRecord.Slug; } break ; default : { //no record found //generate an event this way developers could insert their own types EngineContext.Current.Resolve<IEventPublisher>() .Publish( new CustomUrlRecordEntityNameRequested(data, urlRecord)); } break ; } } return data; } #endregion } } |
using System.Web; using System.Web.Routing; using Nop.Core.Data; using Nop.Core.Domain.Localization; using Nop.Core.Infrastructure; namespace Nop.Web.Framework.Localization { /// <summary> /// Provides properties and methods for defining a localized route, and for getting information about the localized route. /// </summary> public class LocalizedRoute : Route { #region Fields private bool? _seoFriendlyUrlsForLanguagesEnabled; #endregion #region Constructors /// <summary> /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern and handler class. /// </summary> /// <param name="url">The URL pattern for the route.</param> /// <param name="routeHandler">The object that processes requests for the route.</param> public LocalizedRoute(string url, IRouteHandler routeHandler) : base(url, routeHandler) { } /// <summary> /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern, handler class and default parameter values. /// </summary> /// <param name="url">The URL pattern for the route.</param> /// <param name="defaults">The values to use if the URL does not contain all the parameters.</param> /// <param name="routeHandler">The object that processes requests for the route.</param> public LocalizedRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler) : base(url, defaults, routeHandler) { } /// <summary> /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern, handler class, default parameter values and constraints. /// </summary> /// <param name="url">The URL pattern for the route.</param> /// <param name="defaults">The values to use if the URL does not contain all the parameters.</param> /// <param name="constraints">A regular expression that specifies valid values for a URL parameter.</param> /// <param name="routeHandler">The object that processes requests for the route.</param> public LocalizedRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler) : base(url, defaults, constraints, routeHandler) { } /// <summary> /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern, handler class, default parameter values, /// constraints,and custom values. /// </summary> /// <param name="url">The URL pattern for the route.</param> /// <param name="defaults">The values to use if the URL does not contain all the parameters.</param> /// <param name="constraints">A regular expression that specifies valid values for a URL parameter.</param> /// <param name="dataTokens">Custom values that are passed to the route handler, but which are not used to determine whether the route matches a specific URL pattern. The route handler might need these values to process the request.</param> /// <param name="routeHandler">The object that processes requests for the route.</param> public LocalizedRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler) : base(url, defaults, constraints, dataTokens, routeHandler) { } #endregion #region Methods /// <summary> /// Returns information about the requested route. /// </summary> /// <param name="httpContext">An object that encapsulates information about the HTTP request.</param> /// <returns> /// An object that contains the values from the route definition. /// </returns> public override RouteData GetRouteData(HttpContextBase httpContext) { if (DataSettingsHelper.DatabaseIsInstalled() && this.SeoFriendlyUrlsForLanguagesEnabled) { string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath; string applicationPath = httpContext.Request.ApplicationPath; if (virtualPath.IsLocalizedUrl(applicationPath, false)) { //In ASP.NET Development Server, an URL like "http://localhost/Blog.aspx/Categories/BabyFrog" will return //"~/Blog.aspx/Categories/BabyFrog" as AppRelativeCurrentExecutionFilePath. //However, in II6, the AppRelativeCurrentExecutionFilePath is "~/Blog.aspx" //It seems that IIS6 think we're process Blog.aspx page. //So, I'll use RawUrl to re-create an AppRelativeCurrentExecutionFilePath like ASP.NET Development Server. //Question: should we do path rewriting right here? string rawUrl = httpContext.Request.RawUrl; var newVirtualPath = rawUrl.RemoveLanguageSeoCodeFromRawUrl(applicationPath); if (string.IsNullOrEmpty(newVirtualPath)) newVirtualPath = "/"; newVirtualPath = newVirtualPath.RemoveApplicationPathFromRawUrl(applicationPath); newVirtualPath = "~" + newVirtualPath; httpContext.RewritePath(newVirtualPath, true); } } RouteData data = base.GetRouteData(httpContext); return data; } /// <summary> /// Returns information about the URL that is associated with the route. /// </summary> /// <param name="requestContext">An object that encapsulates information about the requested route.</param> /// <param name="values">An object that contains the parameters for a route.</param> /// <returns> /// An object that contains information about the URL that is associated with the route. /// </returns> public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { VirtualPathData data = base.GetVirtualPath(requestContext, values); if (data != null && DataSettingsHelper.DatabaseIsInstalled() && this.SeoFriendlyUrlsForLanguagesEnabled) { string rawUrl = requestContext.HttpContext.Request.RawUrl; string applicationPath = requestContext.HttpContext.Request.ApplicationPath; if (rawUrl.IsLocalizedUrl(applicationPath, true)) { data.VirtualPath = string.Concat(rawUrl.GetLanguageSeoCodeFromUrl(applicationPath, true), "/", data.VirtualPath); } } return data; } public virtual void ClearSeoFriendlyUrlsCachedValue() { _seoFriendlyUrlsForLanguagesEnabled = null; } #endregion #region Properties protected bool SeoFriendlyUrlsForLanguagesEnabled { get { if (!_seoFriendlyUrlsForLanguagesEnabled.HasValue) _seoFriendlyUrlsForLanguagesEnabled = EngineContext.Current.Resolve<LocalizationSettings>().SeoFriendlyUrlsForLanguagesEnabled; return _seoFriendlyUrlsForLanguagesEnabled.Value; } } #endregion } }
using System.Runtime.CompilerServices; namespace System.Web.Routing { // // 摘要: // 提供用于定义路由及获取路由相关信息的属性和方法。 [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")] public class Route : RouteBase { // // 摘要: // 使用指定的 URL 模式和处理程序类初始化 System.Web.Routing.Route 类的新实例。 // // 参数: // url: // 路由的 URL 模式。 // // routeHandler: // 处理路由请求的对象。 public Route(string url, IRouteHandler routeHandler); // // 摘要: // 使用指定的 URL 模式、默认参数值和处理程序类初始化 System.Web.Routing.Route 类的新实例。 // // 参数: // url: // 路由的 URL 模式。 // // defaults: // 用于 URL 中缺失的任何参数的值。 // // routeHandler: // 处理路由请求的对象。 public Route(string url, RouteValueDictionary defaults, IRouteHandler routeHandler); // // 摘要: // 使用指定的 URL 模式、默认参数值、约束和处理程序类初始化 System.Web.Routing.Route 类的新实例。 // // 参数: // url: // 路由的 URL 模式。 // // defaults: // 要在 URL 不包含所有参数时使用的值。 // // constraints: // 一个用于指定 URL 参数的有效值的正则表达式。 // // routeHandler: // 处理路由请求的对象。 public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler); // // 摘要: // 使用指定的 URL 模式、默认参数值、约束、自定义值和处理程序类初始化 System.Web.Routing.Route 类的新实例。 // // 参数: // url: // 路由的 URL 模式。 // // defaults: // 要在 URL 不包含所有参数时使用的值。 // // constraints: // 一个用于指定 URL 参数的有效值的正则表达式。 // // dataTokens: // 传递到路由处理程序但未用于确定该路由是否匹配特定 URL 模式的自定义值。 这些值会传递到路由处理程序,以便用于处理请求。 // // routeHandler: // 处理路由请求的对象。 public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler); // // 摘要: // 获取或设置为 URL 参数指定有效值的表达式的词典。 // // 返回结果: // 一个包含参数名称和表达式的对象。 public RouteValueDictionary Constraints { get; set; } // // 摘要: // 获取或设置传递到路由处理程序但未用于确定该路由是否匹配 URL 模式的自定义值。 // // 返回结果: // 一个包含自定义值的对象。 public RouteValueDictionary DataTokens { get; set; } // // 摘要: // 获取或设置要在 URL 不包含所有参数时使用的值。 // // 返回结果: // 一个包含参数名称和默认值的对象。 public RouteValueDictionary Defaults { get; set; } // // 摘要: // 获取或设置处理路由请求的对象。 // // 返回结果: // 处理请求的对象。 public IRouteHandler RouteHandler { get; set; } // // 摘要: // 获取或设置路由的 URL 模式。 // // 返回结果: // 用于匹配路由和 URL 的模式。 // // 异常: // T:System.ArgumentException: // 以下任一值: 以 ~ 或 / 开头的值。 包含 ? 字符的值。 “全部捕捉”参数不在末尾。 // // T:System.Exception: // 没有使用分隔符或文字常量分隔 URL 分段。 public string Url { get; set; } // // 摘要: // 返回有关所请求路由的信息。 // // 参数: // httpContext: // 一个对象,封装有关 HTTP 请求的信息。 // // 返回结果: // 一个对象,其中包含路由定义中的值。 public override RouteData GetRouteData(HttpContextBase httpContext); // // 摘要: // 返回与路由关联的 URL 的相关信息。 // // 参数: // requestContext: // 一个对象,封装有关所请求的路由的信息。 // // values: // 一个包含路由参数的对象。 // // 返回结果: // 一个包含与路由关联的 URL 的相关信息的对象。 public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values); // // 摘要: // 确定参数值是否与该参数的约束匹配。 // // 参数: // httpContext: // 一个对象,封装有关 HTTP 请求的信息。 // // constraint: // 用于测试 parameterName 的正则表达式或对象。 // // parameterName: // 要测试的参数的名称。 // // values: // 要测试的值。 // // routeDirection: // 一个指定 URL 路由是否处理传入请求或构造 URL 的值。 // // 返回结果: // 如果参数值与约束匹配,则为 true;否则为 false。 // // 异常: // T:System.InvalidOperationException: // constraint 不是包含正则表达式的字符串。 protected virtual bool ProcessConstraint(HttpContextBase httpContext, object constraint, string parameterName, RouteValueDictionary values, RouteDirection routeDirection); } }
using System; using System.Web.Mvc; using System.Web.Routing; namespace Nop.Web.Framework.Seo { public static class GenericPathRouteExtensions { //Override for localized route public static Route MapGenericPathRoute(this RouteCollection routes, string name, string url) { return MapGenericPathRoute(routes, name, url, null /* defaults */, (object)null /* constraints */); } public static Route MapGenericPathRoute(this RouteCollection routes, string name, string url, object defaults) { return MapGenericPathRoute(routes, name, url, defaults, (object)null /* constraints */); } public static Route MapGenericPathRoute(this RouteCollection routes, string name, string url, object defaults, object constraints) { return MapGenericPathRoute(routes, name, url, defaults, constraints, null /* namespaces */); } public static Route MapGenericPathRoute(this RouteCollection routes, string name, string url, string[] namespaces) { return MapGenericPathRoute(routes, name, url, null /* defaults */, null /* constraints */, namespaces); } public static Route MapGenericPathRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces) { return MapGenericPathRoute(routes, name, url, defaults, null /* constraints */, namespaces); } public static Route MapGenericPathRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) { if (routes == null) { throw new ArgumentNullException("routes"); } if (url == null) { throw new ArgumentNullException("url"); } var route = new GenericPathRoute(url, new MvcRouteHandler()) { Defaults = new RouteValueDictionary(defaults), Constraints = new RouteValueDictionary(constraints), DataTokens = new RouteValueDictionary() }; if ((namespaces != null) && (namespaces.Length > 0)) { route.DataTokens["Namespaces"] = namespaces; } routes.Add(name, route); return route; } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)