Home > Software design >  ASP.NET Core MVC route based localization with areas
ASP.NET Core MVC route based localization with areas

Time:12-04

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 >
    <a  asp-area="Identity" asp-page="/Account/Register">
        @Language.register
    </a>
</li>
<li >
    <a  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

CodePudding user response:

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.

CodePudding user response:

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...

  • Related