具有本地化支持的 SEO 友好路由

SEO Friendly Route with localization support

在学习了几个教程之后,主要是 this one 我设法在我的 Asp.Net Core 3.1 网站中实现了本地化支持,但现在路由似乎无法正常工作。这是我的路线:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "TVShowsDetails",
        pattern: "tvshows/{id:int}/{*title}",
        defaults: new { controller = "tvshows", action = "details", id = 0 }
    );

    endpoints.MapControllerRoute(
        name: "LocalizedDefault",
        pattern: "{lang:lang}/{controller=Home}/{action=Index}/{id?}"
    );

    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{*catchall}",
        defaults: new { controller = "Home", action = "RedirectToDefaultLanguage", lang = "et" });

    endpoints.MapRazorPages();
});

现在,当我使用此代码创建 link 时:<a asp-controller="TVShows" asp-action="details" asp-route-id="@id" asp-route-title="@title"> 由于某种原因,它创建的 link 是这样的:https://localhost:44349/en/tvshows/details/1?title=title。有趣的是,如果我转到此 link: https://localhost:44349/en/tvshows/1/title,它会显示相同的页面。我试过 href="Url.Action(...)" 但结果相同。

但是,如果我删除模式开头的 {lang:lang}/,它会生成正确的 link,但没有语言部分 (https://localhost:44349/tvshows/details/1?title=title),但我需要生成 links 使用当前语言,所以我缺少什么?

编辑

经过几次尝试,这个成功了:

endpoints.MapControllerRoute(
    name: "tvshowdetails",
    pattern: "{lang:lang}/{controller=tvshows}/{action=details}/{id?}/{title}"
);

但是,我不想在其中显示操作名称 (details)。这会产生以下 link:

https://localhost:44349/en/tvshows/details/1/breaking-bad

我想要以下 link,但是:

https://localhost:44349/en/tvshows/1/breaking-bad

从 .NET Core 3.0 开始,URL 生成方案似乎存在一些问题,如 the routing documentation. Basically, the route values from the current request are not being included in the URL generation. This post 中所述,还表明它发生在 "the destination page is different to the source page."[=14 时=]

文档建议在遇到此问题时使用传统路由。虽然我没有为 .NET Core 3.0 项目这样做的经验,但我确实有一个几年前的 .NET Core 2.0 项目也使用本地化路由,所以我希望它能起作用。

或者,您可以将当前语言参数显式传递给定位标记助手。从您的原始示例中,我可以使用以下路由(请注意 TVShowsDetails 路由添加的语言参数)

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "TVShowsDetails",
        pattern: "{lang:lang}/tvshows/{id:int}/{*title}",
        defaults: new { controller = "tvshows", action = "details", id = 0 }
    );

    endpoints.MapControllerRoute(
        name: "LocalizedDefault",
        pattern: "{lang:lang}/{controller=Home}/{action=Index}/{id?}"
    );

    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{*catchall}",
        defaults: new { controller = "Home", action = "RedirectToDefaultLanguage", lang = "et" });

    endpoints.MapRazorPages();
});

然后使用

生成link
<a asp-controller="tvshows"
   asp-action="details"
   asp-route-lang="@Context.Request.RouteValues["lang"]"
   asp-route-id="@id"
   asp-route-title="@title">