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

ASP.NET Core API中如何对格式错误的URL段返回404状态码

在ASP.NET 6.0中保持Guid参数类型时将格式错误请求返回404的方案

先看原控制器代码:

[ApiController]
public class FooController
{
    [HttpGet("foo/{guid}")]
    public Guid Get(Guid guid) => guid;
}

当请求合法Guid时返回200,但请求/foo/bar这类格式错误的路径时,默认返回400 Bad Request。我们需要在保持Guid参数类型的前提下,让这类请求返回404 Not Found。

以下是几种可行方案:

方案一:自定义Guid模型绑定器

创建一个针对Guid类型的模型绑定器,当绑定失败时直接返回404响应:

public class GuidNotFoundBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueProviderResult == ValueProviderResult.None)
        {
            return Task.CompletedTask;
        }

        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
        string value = valueProviderResult.FirstValue;

        if (!Guid.TryParse(value, out Guid result))
        {
            // 绑定失败,返回404
            bindingContext.Result = ModelBindingResult.Failed();
            bindingContext.HttpContext.Response.StatusCode = StatusCodes.Status404NotFound;
            return Task.CompletedTask;
        }

        bindingContext.Result = ModelBindingResult.Success(result);
        return Task.CompletedTask;
    }
}

然后创建对应的绑定器提供程序:

public class GuidNotFoundBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context.Metadata.ModelType == typeof(Guid))
        {
            return new BinderTypeModelBinder(typeof(GuidNotFoundBinder));
        }
        return null;
    }
}

最后在Program.cs中注册这个绑定器:

builder.Services.AddControllers(options =>
{
    options.ModelBinderProviders.Insert(0, new GuidNotFoundBinderProvider());
});

方案二:使用Action过滤器拦截模型验证错误

利用ApiController自动触发的模型验证,在过滤器中捕获Guid转换错误并替换为404:

public class GuidValidationToNotFoundFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            // 检查是否有Guid转换相关的错误
            var hasGuidParseError = context.ModelState.Values
                .Any(v => v.Errors.Any(e => e.Exception is FormatException && 
                                            e.Exception.Message.Contains("Guid")));

            if (hasGuidParseError)
            {
                context.Result = new NotFoundResult();
            }
        }
    }

    public void OnActionExecuted(ActionExecutedContext context) { }
}

在Program.cs中注册过滤器:

builder.Services.AddControllers(options =>
{
    options.Filters.Add<GuidValidationToNotFoundFilter>();
});

方案三:自定义路由约束

定义一个Guid路由约束,只有当路径段是合法Guid时才匹配该路由,否则路由不命中,自然返回404:

public class GuidRouteConstraint : IRouteConstraint
{
    public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (values.TryGetValue(routeKey, out var value) && value is string stringValue)
        {
            return Guid.TryParse(stringValue, out _);
        }
        return false;
    }
}

在Program.cs中注册约束:

builder.Services.AddRouting(options =>
{
    options.ConstraintMap.Add("guid", typeof(GuidRouteConstraint));
});

然后修改控制器的路由,使用自定义约束:

[ApiController]
public class FooController
{
    [HttpGet("foo/{guid:guid}")] // 使用自定义的guid约束
    public Guid Get(Guid guid) => guid;
}

这样当路径段不是合法Guid时,这个路由不会被匹配,ASP.NET会返回404。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 12:24:18