如何在 mvc core 3.1 中显示 seo 友好 url?

How to show seo friendly url in mvc core 3.1?

我正在开发 mvc 核心 3.1 应用程序。 Seo 要求是显示带有主站点的产品名称而不是完整的 url.

我原来的url是

www.abc.com/Fashion/ProductDetail?productId=5088&productName=AliviaBlack&brandId=3

要求是

www.abc.com/alivia-black 

我试过使用属性路由进行跟踪

endpoints.MapControllerRoute(
           name: "SpecificRoute",
           pattern: "/{productName}",
           defaults: new { controller = "Fashion", action = "ProductDetail", id= "{productId}" });

在查看页面中

 <a asp-route-productId="@product.ProductId"
                       asp-route-productName="@Common.FilterURL(product.ProductName)"
                       asp-route-brandId="@product.FashionBrand.FashionBrandId" asp-route="SpecificRoute">

结果是

www.abc.com/alivia-black?productId=5223&brandId=4

问号后面的参数怎么去掉

首先,URI 需要有弹性。您说您当前的要求是具有这样的 URI:

www.abc.com/alivia-black

即:

{host}/{productName}

这是一个非常糟糕的 URI 模板,因为:

  • 它不会唯一地 标识产品(因为您可能有多个同名产品)。
  • 如果您重命名产品或替换具有相同名称的产品,它将破坏来自外部网站的现有 link。这种情况 在任何产品数据库中都经常发生
  • 因为您将 {productName} 放在 URI 结构的“根”中,这意味着除了查看产品(例如如何你会有一个 /contact-us 页面吗?如果你有一个名为 contact-us 的产品怎么办?)

我强调在 URI 中包含所请求实体的不可变键(在本例中为您的 productId 值)并将其用作主要参考非常重要,因此 productName 在处理传入的 HTTP 请求时可以忽略。这就是 Whosebug 和 Amazon 的 URI 的工作方式(您可以 trim 在 Whosebug 的问题 ID 后关闭文本,它仍然有效:例如




I strongly recommend you read this article on the W3.org's website all about designing good URIs, as well as other guidance from that group's homepage.


我建议你使用一个更好的 URI 模板,比如这个:

{host}/products/{productId}/{productName}

这会给你一个像这样的 URI:

abc.com/products/5088/alivablack

在 ASP.NET MVC(和 ASP.NET 核心)中处理这样的 link 是微不足道的,只需在控制器操作上设置路由模板:

[Route( "/products/{productId:int}/{productName?}" )]
public async Task<IActionResult> ShowProduct( Int32 productId, String? productName = null )
{
    // Use `productId` to lookup the product.
    // Disregard `productName` unless you want to use it as a fallback to search your database if `productId` doesn't work.
}

至于生成 URI,我建议反对 使用 TagHelpers(例如 <a asp-route-),因为它们不提供您可以充分控制 URI 的呈现方式,您可以定义一个 UrlHelper 扩展方法(确保您 @import 将命名空间 .cshtml 页面(或将其添加到 ViewStart ):

public static class MyUrls
{
    public static String ShowProduct( this IUrlHelper u, Int32 productId, String productName )
    {
        const String ACTION_NAME = nameof(ProductsController.ShowProduct);
        const String CONTROLLER_NAME = "Products"; // Unfortunately we can't use `nameof` here due to the "Controller" suffix in the type-name.

        String url = u.Action( action: ACTION_NAME, controller: CONTROLLER_NAME, values: new { productId = productId, productName = productName } );
        return url;
    }
}

然后就可以这样使用了:

<a href="@Urls.ShowProduct( 5088, "aliviablack" )">View AliviaBlack</a>

您还可以让 ShowProduct 直接接受您的 Product 对象之一,然后将值传递给另一个接受标量的重载(上面定义的):

    public static String ShowProduct( this IUrlHelper u, Product product )
    {
        String url = ShowProduct( u, productId: product.ProductId, productName: product.ProductName );
        return url;
    }

然后你可以像这样使用它(假设 product 在范围内):

<a href="@Urls.ShowProduct( product )">@product.ProductName</a>