You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Razor Pages如何将未知路由重定向至自定义404页面?

问题场景

我的应用里有3组页面,对应3种路由模式:

  • 路径含1个额外部分:比如{domain}/en/about-us/,这类页面的@page指令不带路由参数;
  • 路径含2个额外部分:比如{domain}/en/product/{permalink}/,这类页面的@page指令带id参数,格式为@page "{id}/";
  • 路径含3个额外部分:比如{domain}/en/{category-permalink1}/{subcategory-permalink2}/{subsubcategory-permalink3}/,这类页面的@page指令格式为@page "/{maincat}/{subcat?}/{subsubcat?}/"。

目前正常路由都能工作,但当URL添加了额外部分(比如{domain}/{language_code}/{part2}/{part3}/{part4}/{part5})时,不会重定向到我自定义的404页面,反而跳转到系统默认的404页面。我之前尝试在RouteValueRequestCultureProvider里加逻辑处理,但没成功:

public class RouteValueRequestCultureProvider : IRequestCultureProvider
{
    private readonly CultureInfo[] _cultures;

    public RouteValueRequestCultureProvider(CultureInfo[] cultures)
    {
        _cultures = cultures;
    }

    /// <summary>
    /// get {culture} route value from path string, 
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns>ProviderCultureResult depends on path {culture} route parameter, or default culture</returns>
    public Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
    {
        var defaultCulture = "en";

        var path = httpContext.Request.Path;
        var routeValues = httpContext.Request.Path.Value.Split('/');
        var pathParts = routeValues.Where(p => !string.IsNullOrEmpty(p)).ToArray();

        if (pathParts.Length > 4)
        {
            httpContext.Response.StatusCode = 404;
            httpContext.Response.Redirect("/en/not-found/", true);
        }

        return Task.FromResult(new ProviderCultureResult(routeValues[1]));
    }
}
解决办法

方法1:用Blazor通配符路由捕获无效请求(推荐)

Blazor支持通配符路由,可以专门做一个页面来捕获所有不匹配现有路由的请求,再重定向到自定义404:

  1. 创建NotFoundCatchAll.razor页面,路由设为通配符:
@page "/{*path}"
@inject NavigationManager NavManager

@code {
    protected override void OnInitialized()
    {
        // 提取当前URL里的语言部分,没有的话用默认值en
        var pathSegments = NavManager.Uri.Split('/').Where(s => !string.IsNullOrEmpty(s)).ToArray();
        var culture = pathSegments.Length > 0 ? pathSegments[0] : "en";
        
        // 重定向到自定义404页面,forceLoad确保服务器端处理
        NavManager.NavigateTo($"/{culture}/not-found/", forceLoad: true);
    }
}
  1. 确保你的自定义404页面(比如CustomNotFound.razor)路由正确:
@page "/{culture}/not-found/"
<h1>404 - 页面不存在</h1>
<p>您访问的路径无效,请检查后重试。</p>

这样所有不符合你3种路由模式的URL,都会被这个通配符页面捕获,然后跳转到你的自定义404。

方法2:服务器端中间件处理

如果需要在服务器层面拦截无效路由,写个自定义中间件:

public class InvalidRouteMiddleware
{
    private readonly RequestDelegate _next;

    public InvalidRouteMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var pathParts = context.Request.Path.Value.Split('/')
            .Where(p => !string.IsNullOrEmpty(p))
            .ToArray();

        // 合法路径的部分数:2(语言+1段)、3(语言+2段)、4(语言+3段)
        if (pathParts.Length > 4)
        {
            var culture = pathParts.Length > 0 ? pathParts[0] : "en";
            context.Response.StatusCode = StatusCodes.Status404NotFound;
            await context.Response.RedirectAsync($"/{culture}/not-found/");
            return;
        }

        await _next(context);
    }
}

然后在Program.cs里注册这个中间件,注意顺序要放在UseRouting之后,UseEndpoints之前:

app.UseRouting();
// 插入自定义中间件
app.UseMiddleware<InvalidRouteMiddleware>();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
    endpoints.MapBlazorHub();
    endpoints.MapFallbackToPage("/_Host");
});

为什么之前的方法没用?

RouteValueRequestCultureProvider的职责只是解析请求的文化信息,不是处理路由跳转。你在这个阶段修改响应,后续的路由中间件还会继续处理,可能会覆盖你设置的状态码或者重定向操作。另外,代码里routeValues[1]还可能因为路径过短抛出索引越界异常,得加判断。

内容的提问来源于stack exchange,提问作者Mehdi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 11:54:22