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

时间:2018-05-29 09:49:16

标签: asp.net-mvc asp.net-core routing .net-core razor-pages

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

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

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

2 个答案:

答案 0 :(得分: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()本身也会做的路由工作,但是我会采取明显的延迟来确保我的所有页面都已本地化。)

答案 1 :(得分: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()
    {

    }
}

我希望它有所帮助。