将Razor页面路由到/example.com/en/ format

问题描述 投票:0回答:2

我的网站上有三种语言。我正试图让我的剃刀页面路由到文化/本地化,如下所示:

https://localhost:44396/en/
https://localhost:44396/ru/

在这一点上,我已经使用过去两天谷歌搜索的方法注释了数百行代码,似乎没有任何工作。该网站大多是静态的,所以现在除了文化之外没有其他需要路由的东西。

asp.net-mvc asp.net-core routing .net-core razor-pages
2个回答
1
投票

这是一种可以执行此操作的方法,不需要在所有页面上放置中间件属性。这在全球有效。

在Startup.cs的ConfigureServices方法中,添加以下内容:

services.AddMvc().AddRazorPagesOptions(options => {
     options.Conventions.AddFolderRouteModelConvention("/", model => {
         foreach (var selector in model.Selectors) {
             selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{lang=en}", selector.AttributeRouteModel.Template);
         }
     });
 });

services.Configure<RequestLocalizationOptions>(options => {
    var defaultCulture = new CultureInfo("en");
    var supportedCultures = new CultureInfo[] {
        defaultCulture,
        new CultureInfo("fr")
    };

    options.DefaultRequestCulture = new RequestCulture(defaultCulture);
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;

    options.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider() {
        RouteDataStringKey = "lang",
        UIRouteDataStringKey = "lang",
        Options = options
    });
});

这将设置全局路线,您支持的文化,并将主要文化提供者设置为来自路线。 (这仍然使其他提供程序保持不变,因此失败Route值,它仍然可以基于查询字符串,Cookie或语言标题设置文化。)

现在,在您的Configure方法中(仍在Startup.cs中),添加以下内容:

var routeBuilder = new RouteBuilder(app) {
    DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
};
routeBuilder.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices));
var router = routeBuilder.Build();

app.Use(async (context, next) => {
    var routeContext = new RouteContext(context);
    await router.RouteAsync(routeContext);

    context.Features[typeof(IRoutingFeature)] = new RoutingFeature() {
        RouteData = routeContext.RouteData
    };

    await next();
});

var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);
app.UseMvc();

这里有一些诡计。首先,我们必须在调用app.UseRequestLocalization之前调用app.UseMvc,否则我们的程序将在我们改变当前文化之前运行。但问题是,app.UseMvc()是设置RouteData的那个。因此,在您调用它之前,路由值都是空白的。因此,当RouteDataRequestCultureProvider去尝试观察{lang}是什么时,它会变回空,因此总是默认你到en。赶上22。

因此,我们只需在我们自己的自定义中间件中手动填充RouteData。这样,RouteDataRequestCultureProvider可以看到它,并且一切都会运行良好。

(我承认这不是最有效的,因为你只是复制了app.UseMvc()本身也会做的路由工作,但我将采取那个不明显的延迟来确保我的所有页面都已本地化。)


0
投票

我会告诉你我做了什么工作。唯一的区别是我使用5个字符的语言代码,但我想这不是很难改变的。

确保安装了以下nuget库

Microsoft.AspNetCore.Localization.Routing

在Startup.cs的ConfigureServices方法中,我们在servcies.AddMvc()下键入以下代码;

services.AddMvc()
    .AddRazorPagesOptions(options =>
    {
        options.Conventions.AuthorizeFolder("/Account/Manage");
        options.Conventions.AuthorizePage("/Account/Logout");
        options.Conventions.AddFolderRouteModelConvention("/", model =>
        {
            foreach (var selector in model.Selectors)
            {
                var attributeRouteModel = selector.AttributeRouteModel;
                attributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{lang=el-GR}", attributeRouteModel.Template);
            }
        });
    });

IList<CultureInfo> supportedCultures = new List<CultureInfo>
{
    new CultureInfo("en-US"),
    new CultureInfo("fr-FR"),
    new CultureInfo("el-GR"),
};

var MyOptions = new RequestLocalizationOptions()
{
    DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US"),
    SupportedCultures = supportedCultures,
    SupportedUICultures = supportedCultures
};
MyOptions.RequestCultureProviders = new[]
{
     new RouteDataRequestCultureProvider() { RouteDataStringKey = "lang", Options = MyOptions }        // requires nuget package Microsoft.AspNetCore.Localization.Routing
};

services.AddSingleton(MyOptions);

我们添加以下类

using Microsoft.AspNetCore.Builder;
public class LocalizationPipeline
{
    public void Configure(IApplicationBuilder app, RequestLocalizationOptions options)
    {
        app.UseRequestLocalization(options);
    }
}

现在,您必须在PageModel类上添加以下行:

[MiddlewareFilter(typeof(LocalizationPipeline))]
public class ContactModel : PageModel
{
    public void OnGet()
    {

    }
}

我希望它有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.