Search code examples
asp.net-coreasp.net-core-routingasp.net-core-localizationasp.net-core-7.0

Redirect to `error/404` on invalid culture or invalid route


On an NET Core 7 Razor Pages project I am using route localization.

In Program.cs I have the following:

  builder.Services.Configure<RequestLocalizationOptions>(x => {
    x.DefaultRequestCulture = new RequestCulture("pt");
    x.SupportedCultures = new List<CultureInfo> { new CultureInfo("en"), new CultureInfo("pt") };
    x.SupportedUICultures = new List<CultureInfo> { new CultureInfo("en"), new CultureInfo("pt") };
    x.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider { 
      RouteDataStringKey = "culture",
      UIRouteDataStringKey = "culture",
      Options = x
    }); 
  });

WebApplication application = builder.Build();

application.UseStatusCodePagesWithReExecute("/error/{0}");

application.UseRequestLocalization();

// ...

My Razor Pages are as follows:

@page "/{culture?}/contact"
@model ContactModel

So when culture is defined the page would be in that culture.

When is it not defined then the page gets the default culture, e.g., "PT".

The problem is handling the errors. I am using Status Code redirect:

application.UseStatusCodePagesWithReExecute("/error/{0}");

If, for example, I visit a non existent page then I am redirected to /error/4o4:

@page "/errors/{code?}"
@model ErrorModel

However if I try to access "/abc" that is not a valid culture or a valid page I am not redirected to /error/4o4.

I should be redirected to /error/4o4 if I access a route that starts with a invalid culture or a invalid page route.

How can I do this?


Solution

  • However if I try to access "/abc" that is not a valid culture or a valid page I am not redirected to /error/4o4

    I am not sure why you are not redirecting to the non-existent page. I have tried to reproduce your issue and I am getting the expected error page as you can see below:

    enter image description here

    Possible Reason:

    Make sure you have register below attribute on your program.cs file:

    builder.Services.AddRazorPages();
    
    app.UseRouting();
    
    app.MapRazorPages();
    

    Note: Not sure if you already have these. In addtion, please check the page name spelled correctly @page "/errors/{code?}" then it would be like application.UseStatusCodePagesWithReExecute("/errors/{0}");

    I should be redirected to /error/4o4 if I access a route that starts with a invalid culture or a invalid page route.How can I do this?

    This is the main point I am interested in. There is no straight forward solution for this. However, I have a workaround for you.

    Implementation:

    To meet your requirement, I will consider two things:

    1. I will check the route parameter on HttpContext
    2. Based on HttpContext value I will check the CultureInfo

    Using Middleware We can do that:

    Middleware:

    public class CheckCultureAndRouteThenRedirect
        {
            private readonly RequestDelegate next;
            public CheckCultureAndRouteThenRedirect(RequestDelegate next)
            {
                this.next = next;
            }
            public async Task InvokeAsync(HttpContext context)
    
    
           
            {
              
                var routeURL = context.Request.Path.ToString();
                var host = context.Request.Host;
                var fullRoute= host + routeURL;
                if (routeURL != "/" && !routeURL.Contains("error"))
                {
                    Uri requestedRoute = new Uri(fullRoute);
    
                    string[] firstRoute = requestedRoute.Segments;
                    string cultureRequested = firstRoute[1];
                    var culture = cultureRequested.TrimEnd('/');
    
    
                    CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
    
                    if (!cultureInfo.Name.Contains(culture))
                    {
    
                        context.Response.Redirect("/error/404");
                        await context.Response.CompleteAsync();
    
                    }
                }
    
                await next(context);
            }
        }
    

    Note:

    Make sure you have registered the middlware in program.cs file as below:

    app.UseMiddleware<CheckCultureAndRouteThenRedirect>();
    

    Output:

    enter image description here