URL NOPCommerce 中的路由
URL Routing in NOP Commerce
我想弄清楚这是如何工作的,例如,如果我调出一个类别页面:http://localhost:15536/desktops 它会触发 CatalogController 中的以下 Action 方法:
public virtual IActionResult Category(int categoryId, CatalogPagingFilteringModel command)
那么它是如何传递正确的类别 ID (int) 但它不是 URL 的一部分这是如何工作的?
在Nopcommerce中,有一个名为UrlRecord
的实体,你可以在Nop.Core\Domain\Seo\UrlRecord.cs中找到它:
public partial class UrlRecord : BaseEntity
{
public int EntityId { get; set; }
public string EntityName { get; set; }
public string Slug { get; set; }
public bool IsActive { get; set; }
public int LanguageId { get; set; }
}
EntityName
表示这个UrlRecord
用于哪个实体(i.g。产品或类别等)。 EntityId
表示指向实体的Id
(i.g。Id
of Product
)。 Slug
表示使用 URL 我们可以到达预期的实体。在您的示例中,EntityName
是 "Category",EntityId
是类别的 Id
,Slug
是 "desktop"。
那么,Nopcommerce 如何将这些 Slug
路由到正确的 Controller 和 Action?为了弄清楚这一点,我们必须查看位于 Nop.Web.Framework\Seo\GenericPathRoute.cs 中的 GenericPathRoute
class。此 class 已注册为 IRouteBuilder
的自定义 Route
。不管 asp.net 核心路由和 Nopcommerce 细节,GenericPathRoute
的 RouteAsync
方法在每个请求开始时被调用。如果我们看一下这个方法,我们可以看到这个部分(在这个部分之前,urlRecord
是由 Slug
从数据库中获取的,所以我们知道什么是实体及其 Id
, 所以我们可以使用正确的参数将它路由到所需的控制器和操作):
var currentRouteData = new RouteData(context.RouteData);
switch (urlRecord.EntityName.ToLowerInvariant())
{
case "product":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Product";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "ProductDetails";
currentRouteData.Values[NopPathRouteDefaults.ProductIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "producttag":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Catalog";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "ProductsByTag";
currentRouteData.Values[NopPathRouteDefaults.ProducttagIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "category":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Catalog";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "Category";
currentRouteData.Values[NopPathRouteDefaults.CategoryIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "manufacturer":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Catalog";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "Manufacturer";
currentRouteData.Values[NopPathRouteDefaults.ManufacturerIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "vendor":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Catalog";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "Vendor";
currentRouteData.Values[NopPathRouteDefaults.VendorIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "newsitem":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "News";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "NewsItem";
currentRouteData.Values[NopPathRouteDefaults.NewsItemIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "blogpost":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Blog";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "BlogPost";
currentRouteData.Values[NopPathRouteDefaults.BlogPostIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "topic":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Topic";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "TopicDetails";
currentRouteData.Values[NopPathRouteDefaults.TopicIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
default:
//no record found, thus generate an event this way developers could insert their own types
EngineContext.Current.Resolve<IEventPublisher>()
?.Publish(new CustomUrlRecordEntityNameRequestedEvent(currentRouteData, urlRecord));
break;
}
context.RouteData = currentRouteData;
我们可以在这里看到它改变了这个请求的routeData,关于EntityName
。我们可以在这里看到,此功能仅适用于此 switch/case 命令中命名的实体。
我想弄清楚这是如何工作的,例如,如果我调出一个类别页面:http://localhost:15536/desktops 它会触发 CatalogController 中的以下 Action 方法:
public virtual IActionResult Category(int categoryId, CatalogPagingFilteringModel command)
那么它是如何传递正确的类别 ID (int) 但它不是 URL 的一部分这是如何工作的?
在Nopcommerce中,有一个名为UrlRecord
的实体,你可以在Nop.Core\Domain\Seo\UrlRecord.cs中找到它:
public partial class UrlRecord : BaseEntity
{
public int EntityId { get; set; }
public string EntityName { get; set; }
public string Slug { get; set; }
public bool IsActive { get; set; }
public int LanguageId { get; set; }
}
EntityName
表示这个UrlRecord
用于哪个实体(i.g。产品或类别等)。 EntityId
表示指向实体的Id
(i.g。Id
of Product
)。 Slug
表示使用 URL 我们可以到达预期的实体。在您的示例中,EntityName
是 "Category",EntityId
是类别的 Id
,Slug
是 "desktop"。
那么,Nopcommerce 如何将这些 Slug
路由到正确的 Controller 和 Action?为了弄清楚这一点,我们必须查看位于 Nop.Web.Framework\Seo\GenericPathRoute.cs 中的 GenericPathRoute
class。此 class 已注册为 IRouteBuilder
的自定义 Route
。不管 asp.net 核心路由和 Nopcommerce 细节,GenericPathRoute
的 RouteAsync
方法在每个请求开始时被调用。如果我们看一下这个方法,我们可以看到这个部分(在这个部分之前,urlRecord
是由 Slug
从数据库中获取的,所以我们知道什么是实体及其 Id
, 所以我们可以使用正确的参数将它路由到所需的控制器和操作):
var currentRouteData = new RouteData(context.RouteData);
switch (urlRecord.EntityName.ToLowerInvariant())
{
case "product":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Product";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "ProductDetails";
currentRouteData.Values[NopPathRouteDefaults.ProductIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "producttag":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Catalog";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "ProductsByTag";
currentRouteData.Values[NopPathRouteDefaults.ProducttagIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "category":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Catalog";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "Category";
currentRouteData.Values[NopPathRouteDefaults.CategoryIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "manufacturer":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Catalog";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "Manufacturer";
currentRouteData.Values[NopPathRouteDefaults.ManufacturerIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "vendor":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Catalog";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "Vendor";
currentRouteData.Values[NopPathRouteDefaults.VendorIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "newsitem":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "News";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "NewsItem";
currentRouteData.Values[NopPathRouteDefaults.NewsItemIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "blogpost":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Blog";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "BlogPost";
currentRouteData.Values[NopPathRouteDefaults.BlogPostIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
case "topic":
currentRouteData.Values[NopPathRouteDefaults.ControllerFieldKey] = "Topic";
currentRouteData.Values[NopPathRouteDefaults.ActionFieldKey] = "TopicDetails";
currentRouteData.Values[NopPathRouteDefaults.TopicIdFieldKey] = urlRecord.EntityId;
currentRouteData.Values[NopPathRouteDefaults.SeNameFieldKey] = urlRecord.Slug;
break;
default:
//no record found, thus generate an event this way developers could insert their own types
EngineContext.Current.Resolve<IEventPublisher>()
?.Publish(new CustomUrlRecordEntityNameRequestedEvent(currentRouteData, urlRecord));
break;
}
context.RouteData = currentRouteData;
我们可以在这里看到它改变了这个请求的routeData,关于EntityName
。我们可以在这里看到,此功能仅适用于此 switch/case 命令中命名的实体。