How to redirect to homepage when url response status code is 400 using middleware in C# .Net Core 5 Blazor Server Side App

Solution for How to redirect to homepage when url response status code is 400 using middleware in C# .Net Core 5 Blazor Server Side App
is Given Below:

I am trying to access a page that is returning a 400 status code and then to subsequently redirect the user to homepage via middleware. Here is an example url that will throw a 400: https://testsite.com/%C3%85%C2%81%C3%83%C2%B3d%C3%85%C2%BA_Voivodeship

Note that tacking on “/%C3%85%C2%81%C3%83%C2%B3d%C3%85%C2%BA_Voivodeship” to a request on your blazor server side app/.net mvc application will throw a 400 error.

The url mentioned is present in a sitemap along with many other urls returning a 400 status code. Merely removing the urls from the sitemap is not sufficient in a practical, useful context because search engines have already read them and will continue requesting them. On top of this SEO concern, there is the obvious, but unfortunately not mentioned enough, extremely poor user experience of serving out a “Bad Request – Invalid URL
HTTP Error 400. The request URL is invalid.” error message for any user-facing application. This just leaves the user stranded.

So, this issue does need to be dealt with when requested in order to course correct the user to a location where they could do something and also to help search engines that crawl websites to strongly indicate that a specific url should not be crawled any longer through a redirect(yes, for those uninformed of technical SEO, this is the correct, best-practice way to handle this scenario).

I tried to accomplish this by placing a app.use in the Configure method of Startup.cs but it never actually hits the code if you use a url like mentioned above. I am able to break; however, for any ordinary request like a 200 status code one. So, it would seem, this is not the right approach to take. Any ideas?

 app.Use(async (context, next) =>
            {
                var statusCode = context.Response.StatusCode;

                // Redirect to homepage of site when 400 status code
                if (statusCode == 400)
                {
                    context.Response.Redirect("/");
                    return;   // short circuit
                }
                await next();
            });

The HTTP status code 400 and corresponding message are generated by HTTP.SYS. HTTP.SYS performs URL validation and can reject the request. In such case the returned web page looks like

Bad Request – Invalid URL


HTTP Error 400. The request URL is invalid.

As the specified URL is blocked by HTTP.SYS, request never comes to application. Please see the similar question %09 in a URL causes IIS (HTTP.SYS?) to return HTTP 400 immediately for additional details. In the current case, HTTP.SYS does not like %81, %83, %85 characters.
And the corresponding messages can be found in the HTTP.SYS log located at %SystemRoot%System32LogFilesHTTPERR.

If by some reason URL cannot be changed, the HTTP.SYS behavior can be configured via AllowRestrictedChars DWORD registry key located under HKEY_LOCAL_MACHINESystemCurrentControlSetServicesHTTPParameters as described in Http.sys registry settings for Windows article.

If nonzero, Http.sys accepts hex-escaped chars in request URLs that decode to U+0000 – U+001F and U+007F – U+009F ranges.

The HTTP service must be restarted for the changes to take effect.

Additionally to HTTP.SYS configuration change, the middleware code needs a little improvement. The execution of the next delegate needs to be moved to the very top of the method.

app.Use(
  async (context, next) =>
  {
    await next();

    if (context.Response.StatusCode == 400)
    {
      context.Response.Redirect("/");
    }
  });

Also, as mentioned in the comments, the position of the middleware is important. The HttpResponse.Redirect method simply sets the HTTP status code to 301 or 302 and specifies the Location header. If a response has already been sent to the client by other middleware or application code, the HttpResponse.Redirect method will throw an exception.

Whether a middleware executes or not depends on positioning of middleware. If you have placed it after other middleware, they are short-circuiting it.

If you want this middleware to execute always, place it above other middleware, and put your custom code after calling next

 app.Use(async (context, next) =>
        {
           
            // Call next first and then apply your custom code
            await next();

            var statusCode = context.Response.StatusCode;

            // Redirect to homepage of site when 400 status code
            if (statusCode == 400)
            {
                context.Response.Redirect("/");
                return;   // short circuit
            }
           
        });