如何在尊重路由配置的同时解析 Kentico Cloud 中的内容项链接?

How to resolve content item links in Kentico Cloud while respecting routes configuration?

ASP.NET Core 2.2 网站显示来自 Kentico Cloud CMS 的数据。一些项目包含富文本字段。这些字段可能包含指向其他内容项的链接。这些链接应由网站解析为 url。

这个 docs 建议这是通过实现 IContentLinkUrlResolver 接口来完成的。但是,对于我们网站的目的而言,该示例太虚伪了。我们的解析器需要知道请求的上下文(比如当前的 UI 文化,因为站点是多语言环境)和路由定义,因为这是唯一定义 url 应该是什么样子的地方。

事实上,解析器需要能够调用 Url.Action,因为它能够在视图内部调用。

url 解析器应该尊重路由和当前的 ui 文化。它的逻辑预计是这样的:

if (the linked content item type is Page)
{
    Url.Action("Page", "Home", new [] { codename = content item’s codename });
}
else if (the linked content item type is PageFont)
{
    Url.Action("Font", "Home", new [] { codename = content item’s codename });
}
else
{
    throw an error about an unsupported content type.
}

规则定义为:

var localizationOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();

app.UseRouter(routes =>
{
    routes.MapMiddlewareRoute("{culture=en-US}/{*mvcRoute}", subApp =>
    {
        subApp.UseRequestLocalization(localizationOptions.Value);

        subApp.UseMvc(mvcRoutes =>
        {
            mvcRoutes.MapRoute(
                name: "areas",
                template: "{culture=en-US}/{area:exists}/{controller=Home}/{action=Index}/{id?}");

            mvcRoutes.MapRoute(
                name: "sitemap",
                defaults: new { controller = "Sitemap", action = "Index" },
                template: "sitemap.xml");

            mvcRoutes.MapRoute(
                name: "font",
                defaults: new { controller = "Home", action = "Font" },
                template: "{culture=en-US}/font/{codename}");

            mvcRoutes.MapRoute(
                name: "page",
                defaults: new { controller = "Home", action = "Page" },
                template: "{culture=en-US}/{codename}");

            mvcRoutes.MapRoute(
                name: "default",
                template: "{culture=en-US}/{controller=Home}/{action=Index}/{id?}");
        });
    });
});

如何解析与站点配置中的路由有关的链接?

这应该能够在视图中解析类似于 Url.Action 的网址:

Startup.cs中:

services
    .TryAddSingleton<IActionContextAccessor, ActionContextAccessor>();

services
    .AddSingleton<IContentLinkUrlResolver, RoutesContentLinkUrlResolver>()
    .AddDeliveryClient( ... )
;

RoutesContentLinkUrlResolver.cs中:

private readonly IUrlHelperFactory urlHelperFactory;
private readonly IActionContextAccessor actionContextAccessor;

public RoutesContentLinkUrlResolver(IUrlHelperFactory urlHelperFactory, IActionContextAccessor actionContextAccessor)
{
    this.urlHelperFactory = urlHelperFactory;
    this.actionContextAccessor = actionContextAccessor;
}

public string ResolveLinkUrl(ContentLink link)
{
    IUrlHelper Url = urlHelperFactory.GetUrlHelper(actionContextAccessor.ActionContext);

    switch (link.ContentTypeCodename)
    {
        case "Page":
            return Url.Action("Page", "Home", new { codename = link.Codename });
    }
}

尽可能晚地检索 IUrlHelper 的实例,以确保它具有最新的运行时值。 IUrlHelperFactory 的默认实现使用缓存来提高性能:UrlHelperFactory line 44.