简体   繁体   中英

ASP.NET Core MVC route based localization with areas

I have created a project in ASP.NET Core and wanted the language to be detected based on the url: https://localhost:7090/en

If controllers and actions are used in the url, everything works as planned. However, when the registration or login page is called, it does not work (default asp.net identity registration page).

Works: https://localhost:7090/en/Home/Index

Does not work: https://localhost:7090/en/Identity/Account/Register

In the startup, I configured the following for MVC routing:

builder.Services
    .AddLocalization()
    .AddMvc(options => options.EnableEndpointRouting = false);

builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = CultureHelper.GetSupportedCultures();
    options.DefaultRequestCulture = new RequestCulturne("en");
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;

    var provider = new RouteDataRequestCultureProvider
    {
        RouteDataStringKey = "culture",
        UIRouteDataStringKey = "culture",
        Options = options
    };
    options.RequestCultureProviders = new[] { provider };

});

builder.Services.Configure<RouteOptions>(options =>
{
    options.ConstraintMap.Add("culture", typeof(LanguageRouteConstraint));
});


var options = app.Services.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value); 
app.UseMvc(routes =>
{
    app.MapRazorPages();

    routes.MapRoute(
        name: "LocalizedDefault",
        template: "{culture:culture}/{controller=Home}/{action=Index}/{id?}"
    );
});

The language constraint is then used to set the CurrentCulture and CurrentUICulture.

Here is a code snippet for calling the login/register pages:

<li class="nav-item">
    <a class="nav-link" asp-area="Identity" asp-page="/Account/Register">
        @Language.register
    </a>
</li>
<li class="nav-item">
    <a class="nav-link" asp-area="Identity" asp-page="/Account/Login">
        @Language.login
    </a>
</li>

I've tried pretty much everything I've found on Google, but nothing seems to work....

I just think knowing that it does not work because of the pages

[UPDATE] I was able to get the url to be valid with the following code:

builder.Services
.AddLocalization(options => options.ResourcesPath = "Resources")
.AddMvc(options => options.EnableEndpointRouting = false)
.AddRazorPagesOptions(options =>
{
    options.Conventions.Add(new LanguageRouteModelConversion());
 });

public class LanguageRouteModelConversion : IPageRouteModelConvention
{
    public void Apply(PageRouteModel pageRouteModel)
    {
        var selectorModels = new List<SelectorModel>();
     
        foreach (var selector in pageRouteModel.Selectors.ToList())
        {
            var template = selector.AttributeRouteModel?.Template;
            selectorModels.Add(new SelectorModel()
            {
                AttributeRouteModel = new AttributeRouteModel
                {
                    Template = "/{culture}/" + template
                }
            });
        }

        foreach (var model in selectorModels)
            pageRouteModel.Selectors.Add(model);
    }
}

But i still don't know how to call the page properly

You said you have no Account folder in Identity directory. If so then how you do you expect register,login page router will work?

 builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
     .AddEntityFrameworkStores<YourDbContextName>();

Then Scaffold Register, Login, LogOut page etc. After scaffolded, you will find a separate Account folder in Pages folder. and Your Account folder actually contains login,register page. It should resolve your issue.

builder.Services
.AddLocalization(options => options.ResourcesPath = "Resources")
.AddMvc(options => options.EnableEndpointRouting = false)
.AddRazorPagesOptions(options =>
{
    options.Conventions.AddAreaFolderRouteModelConvention("Identity", "/", pageRouteModel =>
    {
        foreach (var selectorModel in pageRouteModel.Selectors)
            selectorModel.AttributeRouteModel.Template = "{culture:culture}/" + selectorModel.AttributeRouteModel.Template;
    });
});

This did the trick for me, i finally figured it out...

Add the culture param to the URL asp-route-culture=...

@{ var culture= System.Globalization.CultureInfo.CurrentCulture.Name }
<li class="nav-item">
    <a class="nav-link" asp-area="Identity" asp-page="/Account/Register" asp-route-culture="@culture">
        @Language.register
    </a>
</li>
<li class="nav-item">
    <a class="nav-link" asp-area="Identity" asp-page="/Account/Login" asp-route-culture="@culture">
        @Language.login
    </a>
</li>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM