Kilerz159753
Kilerz159753

Reputation: 73

Include culture in razor page url - custom routes

I currently have 3 different cultures.

Actually, my url looks like www.website.com/services, no mater what culture is selected (the culture value is stored in a cookie).

What I would like to do is display the culture directly in the url like this: www.website.com/en/services.

How can I achieve that in .NET6 and with only Razor pages?

Program class

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;
});

builder.Services.AddHttpContextAccessor();

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

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

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

app.UseRouting();

app.UseAuthorization();

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

app.MapRazorPages();

app.Run();

Upvotes: 2

Views: 978

Answers (1)

Dimitris Maragkos
Dimitris Maragkos

Reputation: 11322

You need to create a custom IPageRouteModelConvention:

public class CultureTemplatePageRouteModelConvention : IPageRouteModelConvention
{
    public void Apply(PageRouteModel model)
    {
        var selectorCount = model.Selectors.Count;

        for (var i = 0; i < selectorCount; i++)
        {
            var selector = model.Selectors[i];

            model.Selectors.Add(new SelectorModel
            {
                AttributeRouteModel = new AttributeRouteModel
                {
                    Order = -1,
                    Template = AttributeRouteModel.CombineTemplates("{culture?}", selector.AttributeRouteModel.Template),
                }
            });
        }
    }
}

Then register it using:

builder.Services.AddRazorPages()
    .AddRazorPagesOptions(options =>
    {
        options.Conventions.Add(new CultureTemplatePageRouteModelConvention());
    });

Finally configure RequestLocalizationOptions:

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;
    
    // add this line
    opt.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider());
});

To add the culture to your links you can use the asp-route-culture attribute:

<a asp-route-culture="@Request.RouteValues["culture"]" asp-page="/Contact">Contact</a>

More info about the anchor tag helper and the asp-route-{value} attribute: https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/built-in/anchor-tag-helper?view=aspnetcore-6.0#asp-route-value

Source: https://www.mikesdotnetting.com/article/348/razor-pages-localisation-seo-friendly-urls

Upvotes: 3

Related Questions