I'm building a Razor web application using .NET6 and I have 3 different cultures. For SEO purpose, I'm trying to have a page name who's different depending from the culture.
Like for example:
en: https://www.website.com/en/contact-us fr: https://www.website.com/fr/contactez-nous
I found a cool article about friendly routes but it has to be done via .AddPageRoute in the Pipeline and I don't see how could I make it match depending on the culture (like one for each culture). I tried this but it looks like it only take care of the last one:
options.Conventions.AddPageRoute("/Contact", "/contact-us");
options.Conventions.AddPageRoute("/Contact", "/contactez-nous");
This is my Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions.AddFolderRouteModelConvention("/", model =>
{
foreach (var selector in model.Selectors)
{
selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{culture?}", selector.AttributeRouteModel.Template);
}
});
});
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.Insert(0, new RouteDataRequestCultureProvider()
{
RouteDataStringKey = "culture",
UIRouteDataStringKey = "culture",
Options = opt
});
});
builder.Services.Configure<RouteOptions>(opt =>
{
opt.LowercaseUrls = true;
opt.AppendTrailingSlash = true;
});
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();
}
var options = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Contact.cshtml
@page "/Contact"
@model client.Pages.Contact
@{
ViewData["Title"] = "Contact";
}
<h1>@ViewData["Title"]</h1>
<div>
<form method="post">
<div>
<label>Name</label>
<input type="text" asp-for="ContactModel.FullName" placeholder="Full name">
<span asp-validation-for="ContactModel.FullName" ></span>
</div>
<div>
<label>Email</label>
<input type="email" asp-for="ContactModel.Email" placeholder="[email protected]">
<span asp-validation-for="ContactModel.Email" ></span>
</div>
<div>
<label>Message</label>
<textarea asp-for="ContactModel.Message" cols="30" rows="10"></textarea>
<span asp-validation-for="ContactModel.Message" ></span>
</div>
<button type="submit">Submit</button>
</form>
</div>
Anchor from _Layout.cshtml
<a asp-area="" asp-page="/Contact"
asp-route-culture="@CultureInfo.CurrentCulture.Name">Contact</a>
How can I achieve this? Do I have to do something with the selector.AttributeRouteModel.Template?
CodePudding user response:
I recommend to use url rewrite as described in https://docs.microsoft.com/en-us/aspnet/core/fundamentals/url-rewriting?view=aspnetcore-6.0#extension-and-options
That way, every page is mapped to its english spelled route. Translations are rewritten to the english version by the specified rewrite options.