.NET Framework 4.8 Windows服务API:404请求不触发OnActionExecuted问题
问题分析与解决方案
核心原因
ActionFilterAttribute(即你编写的Logger过滤器)仅在路由成功匹配到具体Action方法时才会执行。当输入错误URL触发404时,Web API的路由系统找不到对应的Action,自然不会触发OnActionExecuting或OnActionExecuted方法。
解决方案
要全局处理404错误,需使用异常过滤器或消息处理器,以下是两种可行方案:
方案一:自定义ExceptionFilter捕获404异常
创建异常过滤器,专门捕获路由未匹配时抛出的404异常,并替换响应内容:
public class NotFoundExceptionFilter : ExceptionFilterAttribute { public override void OnException(HttpActionExecutedContext context) { var httpResponseEx = context.Exception as HttpResponseException; if (httpResponseEx != null && httpResponseEx.Response.StatusCode == HttpStatusCode.NotFound) { var customResponse = new MessageCode().GetStatusCode("400", "Bad request", "Request not supported"); context.Response = context.Request.CreateResponse(HttpStatusCode.BadRequest, customResponse); } base.OnException(context); } }
在WebApiConfig中注册过滤器,同时启用属性路由(你的代码遗漏了这一步,否则RoutePrefix和Route特性不生效):
public static void Register(HttpConfiguration config) { config.Filters.Add(new Logger()); config.Filters.Add(new NotFoundExceptionFilter()); // 启用属性路由(必须添加,否则控制器上的路由特性无效) config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); }
方案二:自定义消息处理器(全局覆盖所有404场景)
消息处理器可拦截所有请求和响应,无论路由是否匹配,都能处理404响应:
public class NotFoundHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var response = await base.SendAsync(request, cancellationToken); if (response.StatusCode == HttpStatusCode.NotFound) { var customResponse = new MessageCode().GetStatusCode("400", "Bad request", "Request not supported"); return request.CreateResponse(HttpStatusCode.BadRequest, customResponse); } return response; } }
在WebApiConfig中注册消息处理器:
public static void Register(HttpConfiguration config) { config.Filters.Add(new Logger()); config.MessageHandlers.Add(new NotFoundHandler()); config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); }
关键注意点
- 必须启用属性路由:控制器使用了
RoutePrefix和Route特性,若不调用config.MapHttpAttributeRoutes(),这些配置不会生效,可能导致正常URL也返回404。 - 方案差异:ExceptionFilter仅捕获异常形式的404,MessageHandler可处理所有类型的404(包括Action主动返回的404)。
内容的提问来源于stack exchange,提问作者dhasarathan
相关产品推荐
相关产品推荐

