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 是类别的 IdSlug 是 "desktop"。

那么,Nopcommerce 如何将这些 Slug 路由到正确的 Controller 和 Action?为了弄清楚这一点,我们必须查看位于 Nop.Web.Framework\Seo\GenericPathRoute.cs 中的 GenericPathRoute class。此 class 已注册为 IRouteBuilder 的自定义 Route。不管 asp.net 核心路由和 Nopcommerce 细节,GenericPathRouteRouteAsync 方法在每个请求开始时被调用。如果我们看一下这个方法,我们可以看到这个部分(在这个部分之前,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 命令中命名的实体。