asp.net-coreasp.net-core-middlewareasp.net-core-routingasp.net-core-7.0

How to create a Net Core Middleware to validate a route parameter


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?


Solution

  • 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:

    enter image description here

    You could also check the document related