We have built an ASP.NET Core 2.1 website where URLs like www.example.org/uk and www.example.org/de determine what resx
file and content to show. After upgrading to ASP.NET Core 2.2, pages load but all links generated produce blank/empty href's.
For example, a link this:
<a asp-controller="Home" asp-action="Contact">@Res.ContactUs</a>
will in 2.2 produce an empty href like so:
<a href="">Contact us</a>
But in 2.1 we get correct href:
<a href="/uk/contact">Contact us</a>
We are using a Constraint Map to manage the URL-based language feature - here is the code:
Startup.cs
// configure route options {lang}, e.g. /uk, /de, /es etc
services.Configure<RouteOptions>(options =>
{
options.LowercaseUrls = true;
options.AppendTrailingSlash = false;
options.ConstraintMap.Add("lang", typeof(LanguageRouteConstraint));
});
...
app.UseMvc(routes =>
{
routes.MapRoute(
name: "LocalizedDefault",
template: "{lang:lang}/{controller=Home}/{action=Index}/{id?}");
}
LanguageRouteConstraint.cs
public class LanguageRouteConstraint : IRouteConstraint
{
private readonly AppLanguages _languageSettings;
public LanguageRouteConstraint(IHostingEnvironment hostingEnvironment)
{
var builder = new ConfigurationBuilder()
.SetBasePath(hostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
IConfigurationRoot configuration = builder.Build();
_languageSettings = new AppLanguages();
configuration.GetSection("AppLanguages").Bind(_languageSettings);
}
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
if (!values.ContainsKey("lang"))
{
return false;
}
var lang = values["lang"].ToString();
foreach (Language lang_in_app in _languageSettings.Dict.Values)
{
if (lang == lang_in_app.Icc)
{
return true;
}
}
return false;
}
}
I narrowed down the problem but can't find a way to solve it;
Basically in 2.2. some parameters are not set in the above IRouteConstraint Match
method, e.g.
httpContext = null
route = {Microsoft.AspNetCore.Routing.NullRouter)
In 2.1
httpContext = {Microsoft.AspNetCore.Http.DefaultHttpContext}
route = {{lang:lang}/{controller=Home}/{action=Index}/{id?}}
The only difference I made between 2.1 and 2.2 is that I changed
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
to the following (due to https://github.com/aspnet/AspNetCore/issues/4206)
var builder = new ConfigurationBuilder()
.SetBasePath(hostingEnvironment.ContentRootPath) // using IHostingEnvironment
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
Any ideas?
Update According to https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-2.2#parameter-transformer-reference ASP.NET Core 2.2 uses EndpointRouting whereas 2.1 uses IRouter basic logic. That explains my problem. Now, my question would then what will code look like for 2.2 to use the new EndpointRouting?
asp-route-lang="@this.Context.GetRouteValue("lang")"
– Clincher