You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET6 Razor Pages实现URL含自定义文化路由的方法

在.NET6 Razor Pages中实现URL带文化标识的本地化方案

要实现URL中显示文化标识(如www.website.com/en/services),需要从路由配置、文化提取、链接生成三个核心部分调整,以下是具体步骤:

1. 修改路由配置,支持文化前缀

更新MapRazorPages的路由模板,为所有页面添加可选的文化前缀参数,并添加约束确保只有支持的文化码能通过:

app.MapRazorPages()
   .AddRazorPagesOptions(options =>
   {
       // 为所有页面路由添加文化前缀约束
       options.Conventions.AddAreaPageRoute("", "/{culture:regex(^en$|^fr$|^nl$)}/", "");
       options.Conventions.AddPageRoute("/{culture:regex(^en$|^fr$|^nl$)}/", "");
   });

2. 自定义URL文化提取提供器

默认的请求本地化不会从URL提取文化,需要自定义RequestCultureProvider,优先从URL的culture参数中获取文化值:

2.1 实现自定义文化提供器

在项目中添加如下类:

public class UrlRequestCultureProvider : RequestCultureProvider
{
    public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
    {
        if (httpContext == null)
            throw new ArgumentNullException(nameof(httpContext));

        var culture = httpContext.Request.RouteValues["culture"]?.ToString();
        if (!string.IsNullOrEmpty(culture) && 
            SupportedCultures.Any(c => c.Name.Equals(culture, StringComparison.OrdinalIgnoreCase)))
        {
            return Task.FromResult(new ProviderCultureResult(culture, culture));
        }

        // URL中无有效文化时,返回null,将使用后续提供器(如Cookie)
        return Task.FromResult<ProviderCultureResult>(null);
    }

    public IList<CultureInfo> SupportedCultures { get; set; }
}

2.2 注册自定义提供器

在Program.cs的本地化配置中,将自定义提供器添加到最前面,确保优先从URL提取文化:

builder.Services.Configure<RequestLocalizationOptions>(opt =>
{
    var supportedCultures = new List<CultureInfo>
    {
        new CultureInfo("en"),
        new CultureInfo("fr"),
        new CultureInfo("nl")
    };
    opt.DefaultRequestCulture = new RequestCulture("en");
    opt.SupportedCultures = supportedCultures;
    opt.SupportedUICultures = supportedCultures;

    // 移除默认提供器,添加自定义URL提供器
    opt.RequestCultureProviders.Clear();
    opt.RequestCultureProviders.Add(new UrlRequestCultureProvider
    {
        SupportedCultures = supportedCultures,
        Options = opt
    });
    // 保留Cookie提供器作为 fallback
    opt.RequestCultureProviders.Add(new CookieRequestCultureProvider());
});

3. 生成带文化标识的URL链接

在Razor页面中,生成链接时需要传入当前文化参数,确保URL包含文化前缀:

3.1 直接在页面中生成链接

<a href="@Url.Page("/Services", new { culture = CultureInfo.CurrentCulture.Name })">服务页面</a>

3.2 扩展方法简化调用(可选)

创建一个URL扩展方法,自动携带当前文化:

public static class UrlHelperExtensions
{
    public static string PageWithCulture(this IUrlHelper urlHelper, string pageName, object routeValues = null)
    {
        var currentCulture = CultureInfo.CurrentCulture.Name;
        var routeDict = new RouteValueDictionary(routeValues);
        routeDict["culture"] = currentCulture;
        return urlHelper.Page(pageName, routeDict);
    }
}

在页面中使用:

<a href="@Url.PageWithCulture("/Services")">服务页面</a>

4. 处理无文化前缀的URL重定向(可选)

如果需要将不带文化的URL(如www.website.com/services)重定向到默认文化的URL,可添加一个中间件:

app.Use(async (context, next) =>
{
    var culture = context.Request.RouteValues["culture"]?.ToString();
    if (string.IsNullOrEmpty(culture))
    {
        var defaultCulture = "en";
        var newPath = $"/{defaultCulture}{context.Request.Path}{context.Request.QueryString}";
        context.Response.Redirect(newPath);
        return;
    }
    await next();
});

注意:此中间件需要放在UseRouting之后,UseAuthorization之前。

修改后的完整Program.cs代码

using System.Globalization;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.Razor;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddMvc().AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix).AddDataAnnotationsLocalization();
builder.Services.Configure<RequestLocalizationOptions>(opt =>
{
    var supportedCultures = new List<CultureInfo>
    {
        new CultureInfo("en"),
        new CultureInfo("fr"),
        new CultureInfo("nl")
    };
    opt.DefaultRequestCulture = new RequestCulture("en");
    opt.SupportedCultures = supportedCultures;
    opt.SupportedUICultures = supportedCultures;

    opt.RequestCultureProviders.Clear();
    opt.RequestCultureProviders.Add(new UrlRequestCultureProvider
    {
        SupportedCultures = supportedCultures,
        Options = opt
    });
    opt.RequestCultureProviders.Add(new CookieRequestCultureProvider());
});

builder.Services.AddHttpContextAccessor();
builder.Services.AddLocalization(opt => { opt.ResourcesPath = "Resources"; });

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

// 无文化前缀重定向中间件
app.Use(async (context, next) =>
{
    var culture = context.Request.RouteValues["culture"]?.ToString();
    if (string.IsNullOrEmpty(culture))
    {
        var defaultCulture = "en";
        var newPath = $"/{defaultCulture}{context.Request.Path}{context.Request.QueryString}";
        context.Response.Redirect(newPath);
        return;
    }
    await next();
});

app.UseAuthorization();

app.UseRequestLocalization(app.Services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);

app.MapRazorPages()
   .AddRazorPagesOptions(options =>
   {
       options.Conventions.AddAreaPageRoute("", "/{culture:regex(^en$|^fr$|^nl$)}/", "");
       options.Conventions.AddPageRoute("/{culture:regex(^en$|^fr$|^nl$)}/", "");
   });

app.Run();

public class UrlRequestCultureProvider : RequestCultureProvider
{
    public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
    {
        if (httpContext == null)
            throw new ArgumentNullException(nameof(httpContext));

        var culture = httpContext.Request.RouteValues["culture"]?.ToString();
        if (!string.IsNullOrEmpty(culture) && 
            SupportedCultures.Any(c => c.Name.Equals(culture, StringComparison.OrdinalIgnoreCase)))
        {
            return Task.FromResult(new ProviderCultureResult(culture, culture));
        }

        return Task.FromResult<ProviderCultureResult>(null);
    }

    public IList<CultureInfo> SupportedCultures { get; set; }
}

内容的提问来源于stack exchange,提问作者Kilerz159753

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 21:36:28