Using Net Core 7 I have Razor Pages with a culture
route parameter:
@page "/{culture:validculture}/about"
I created a custom route constraint to check if culture
has a valid value.
When the culture
value is invalid I am redirected to a 404 error page.
public class CultureRouteConstraint : IRouteConstraint {
private readonly RequestLocalizationOptions _options;
public CultureRouteConstraint(IOptionsSnapshot<RequestLocalizationOptions> options) {
_options = options.Value;
}
public Boolean Match(HttpContext? httpContext, IRouter? route, String routeKey, RouteValueDictionary values, RouteDirection routeDirection) {
String? culture = Convert.ToString(value, CultureInfo.InvariantCulture);
List<String>? cultures = _options.SupportedCultures?.Select(x => x.TwoLetterISOLanguageName).ToList();
if (culture != null && cultures != null)
return cultures.Contains(culture, StringComparer.InvariantCultureIgnoreCase);
}
}
This works great if I hardcode de valid cultures, e.g:
List<String>? cultures = new() { "en", "pt" };
But if I inject RequestLocalizationOptions
I get the error:
RouteCreationException: An error occurred while trying to create an instance of 'CultureRouteConstraint'.
Maybe I need to use a Middleware for this? How can I do this?
Just because IOptionsSnapshot Is registered as Scoped and therefore can't be injected into a Singleton service.
You could try with IOptions (Not Options<>)instead If you don't have to update the options for different request),For Example,I tried as below and it works well in my case:
In program.cs:
builder.Services.Configure<RequestLocalizationOptions>(opts =>
{
var supportedcultures = new List<CultureInfo>()
{
new CultureInfo("en-US"),
new CultureInfo("zh-CN")
};
opts.SupportedCultures = supportedcultures;
opts.SupportedUICultures= supportedcultures;
});
builder.Services.AddRazorPages();
builder.Services.AddRouting(options =>
options.ConstraintMap.Add("validculture", typeof(CultureRouteConstraint)));
var app = builder.Build();
The constraint:
public class CultureRouteConstraint : IRouteConstraint
{
private readonly RequestLocalizationOptions _options;
public CultureRouteConstraint(IOptions<RequestLocalizationOptions> options)
{
_options = options.Value;
}
public Boolean Match(HttpContext? httpContext, IRouter? route, String routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
String? culture = Convert.ToString(values["culture"], CultureInfo.InvariantCulture);
List<String>? cultures = _options.SupportedCultures?.Select(x => x.TwoLetterISOLanguageName).ToList();
if (culture != null && cultures != null)
return cultures.Contains(culture, StringComparer.InvariantCultureIgnoreCase);
else
return false;
}
}
The Result:
You could also check the document related