【问题标题】:Localized page names with ASP.NET Core 2.1使用 ASP.NET Core 2.1 的本地化页面名称
【发布时间】:2018-09-13 16:02:23
【问题描述】:

创建 Razor 页面时,例如“Events.cshtml”,将其模型名称设置为

@page
@model EventsModel

在这种情况下,页面的名称是“事件”,并且 URL 看起来像

http://example.com/Events

为了能够在挪威语中使用页面名称,我在“Startup.cs”中添加了以下内容

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
    .AddRazorPagesOptions(options => {
        options.Conventions.AddPageRoute("/Events", "/hvaskjer");
        options.Conventions.AddPageRoute("/Companies", "/bedrifter");
        options.Conventions.AddPageRoute("/Contact", "/kontakt");
});

有了这个,我也可以使用这样的 URL 并仍然提供“事件”页面

http://example.com/hvaskjer

我计划支持更多语言,我想知道,这是设置本地化页面名称/路线的推荐方法吗?还是有更合适、正确的方法来完成相同的操作。

我的意思是,对于上面的示例,有 10 种语言的 15 页,使用 options.Conventions.AddPageRoute("/Page", "/side"); 150 次会变得/感觉混乱。

【问题讨论】:

  • 如果它听起来不像是“真实”路由,但使用 IIS url 重写模块或此中间件 docs.microsoft.com/en-us/aspnet/core/fundamentals/… 可能会更好
  • @numbtongue 感谢您的评论。因为该应用程序可能在其他环境中运行,例如IIS,我需要避免这样的解决方案。使用中间件进行重写感觉不如我已经使用的合适,并且希望有一个内置选项来解决这个问题。
  • 如果你能把它们放在一个你可以指定 的 web.config 中会很好(虽然可能会让未来的开发者感到困惑)stackoverflow.com/a/40220739/3254405
  • @numbtongue 我不想在“web.config”中存储数百个路径标签,它们是根据所选语言从数据库中存储和读取的,并且很容易更改。跨度>
  • 可能只为 .com 和 .no 等域创建路由,从那里你会知道要使用哪个路径..

标签: asp.net-core asp.net-core-2.1 razor-pages


【解决方案1】:

您可以使用IPageRouteModelConvention 接口执行此操作。它提供对PageRouteModel 的访问,您可以在其中有效地添加更多路由模板以匹配特定页面。

这是一个基于以下服务和模型的非常简单的概念证明:

public interface ILocalizationService
{
    List<LocalRoute> LocalRoutes();
}
public class LocalizationService : ILocalizationService
{
    public List<LocalRoute> LocalRoutes()
    {
        var routes = new List<LocalRoute>
        {
            new LocalRoute{Page = "/Pages/Contact.cshtml", Versions = new List<string>{"kontakt", "contacto", "contatto" } }
        };
        return routes;
    }
}

public class LocalRoute
{
    public string Page { get; set; }
    public List<string> Versions { get; set; }
}

它所做的只是提供特定页面的选项列表。 IPageRouteModelConvention 实现如下所示:

public class LocalizedPageRouteModelConvention : IPageRouteModelConvention
{
    private ILocalizationService _localizationService;

    public LocalizedPageRouteModelConvention(ILocalizationService localizationService)
    {
        _localizationService = localizationService;
    }

    public void Apply(PageRouteModel model)
    {
        var route = _localizationService.LocalRoutes().FirstOrDefault(p => p.Page == model.RelativePath);
        if (route != null)
        {
            foreach (var option in route.Versions)
            {
                model.Selectors.Add(new SelectorModel()
                {
                    AttributeRouteModel = new AttributeRouteModel
                    {
                        Template = option
                    }
                });
            }
        }
    }
}

在启动时,Razor Pages 为应用程序构建路由。为框架找到的每个可导航页面执行Apply 方法。如果当前页面的相对路径与您的数据中的一个匹配,则会为每个选项添加一个额外的模板。

你在ConfigureServices注册新约定:

services.AddMvc().AddRazorPagesOptions(options =>
{
    options.Conventions.Add(new LocalizedPageRouteModelConvention(new LocalizationService()));
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

【讨论】:

  • 非常感谢,正是我想要的。我确实找到了IPageRouteModelConvention,尽管我对 ASP.Net Core 太陌生了,无法弄清楚操作方法:)
  • 巧合的是,我有一篇关于这个接口的博客文章的草稿几乎准备好了。我可能会将此用例作为其应用程序的附加示例。
  • 我认为你应该这样做,因为我相信这一定是关于如何完成我所要求的问题的一个非常常见的问题,并且像你提供的那样简单但非常容易理解的示例,提供了一个非常好的了解它的工作原理。
  • 我刚刚发现,如果一个页面有一个像@page "{edit?}/{id?}" 这样的指令,一个可以/需要添加它以使其全部工作,例如new LocalRoute{Page = "/Pages/Events.cshtml", Versions = new List&lt;string&gt;{"hvaskjer/{edit?}/{id?}" } }
  • @MikeBrind 你提到的那篇博客文章怎么样?发布了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-13
  • 2019-05-06
  • 2019-04-17
  • 2021-07-04
  • 1970-01-01
  • 2020-06-16
相关资源
最近更新 更多