ASP.NET Core中UriFormatException被异常处理器捕获的解决咨询
解决ASP.NET Core中爬虫引发的UriFormatException问题
问题背景
已为ASP.NET Core应用添加全局异常处理逻辑,但爬虫访问不存在的端点时,会触发未处理的UriFormatException(错误信息:Invalid URI: The hostname could not be parsed.),这类异常会污染遥测数据,需要修复或优雅屏蔽,同时忽略针对未定义端点的无效流量。
异常详情
记录的异常
Unhandled exception | UriString: https:///favicon.ico | Exception: System.UriFormatException: Invalid URI: The hostname could not be parsed.
堆栈跟踪
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind, UriCreationOptions& creationOptions) at System.Uri..ctor(String uriString) at Microsoft.AspNet.OData.Routing.ODataPathRouteConstraint.Match(HttpContext httpContext, IRouter route, String routeKey, RouteValueDictionary values, RouteDirection routeDirection) at Microsoft.AspNetCore.Routing.RouteConstraintMatcher.Match(IDictionary`2 constraints, RouteValueDictionary routeValues, HttpContext httpContext, IRouter route, RouteDirection routeDirection, ILogger logger) at Microsoft.AspNetCore.Routing.RouteBase.RouteAsync(RouteContext context) at Microsoft.AspNetCore.Routing.RouteCollection.RouteAsync(RouteContext context) at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
现有异常处理器代码
app.UseExceptionHandler(exceptionHandlerApp => { exceptionHandlerApp.Run(async context => { context.Response.StatusCode = StatusCodes.Status500InternalServerError; IExceptionHandlerPathFeature exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>(); string uriString = null; uriString = context.Request.GetEncodedUrl(); Logger.EmitLog( "Unhandled exception", "UriString", uriString, "Exception", exceptionHandlerPathFeature?.Error); }); });
解决方案
1. 前置拦截无效请求
在路由中间件(包括OData路由)之前添加自定义中间件,提前拦截Host为空的无效请求,避免进入后续路由逻辑:
// 放在app.UseRouting()之前 app.Use(async (context, next) => { // 检查请求Host是否合法(比如爬虫构造的https:///favicon.ico这类无Host的URI) if (string.IsNullOrEmpty(context.Request.Host.Host)) { context.Response.StatusCode = StatusCodes.Status400BadRequest; await context.Response.WriteAsync("Invalid request URI"); return; } await next(); });
2. 在异常处理器中针对性忽略该异常
修改现有异常处理逻辑,识别并跳过来自OData路由约束的UriFormatException,避免记录到遥测数据:
app.UseExceptionHandler(exceptionHandlerApp => { exceptionHandlerApp.Run(async context => { var exceptionFeature = context.Features.Get<IExceptionHandlerPathFeature>(); var exception = exceptionFeature?.Error; // 过滤掉OData路由引发的UriFormatException if (exception is UriFormatException && exception.StackTrace?.Contains("Microsoft.AspNet.OData.Routing.ODataPathRouteConstraint") == true) { context.Response.StatusCode = StatusCodes.Status400BadRequest; await context.Response.WriteAsync("Invalid request URI"); return; } // 处理其他真正的未处理异常 context.Response.StatusCode = StatusCodes.Status500InternalServerError; string uriString = context.Request.GetEncodedUrl(); Logger.EmitLog( "Unhandled exception", "UriString", uriString, "Exception", exception); }); });
3. 配置全局404处理
为不存在的端点配置404响应,避免无效请求触发500异常:
// 放在路由中间件之后 app.UseStatusCodePages(async context => { var response = context.HttpContext.Response; if (response.StatusCode == StatusCodes.Status404NotFound) { await response.WriteAsync("Requested endpoint not found"); } });
4. 优化OData路由配置
如果应用使用OData,可以调整路由约束,避免对无效URI进行解析:
- 确保OData路由仅针对合法的API前缀(比如
/odata) - 在OData路由注册前添加路径检查,过滤非OData路径的请求
组合建议
优先使用前置拦截无效请求+全局404处理的组合,从源头减少无效请求进入后续逻辑;再用异常处理器作为兜底,确保漏网的UriFormatException不会污染遥测数据。
内容的提问来源于stack exchange,提问作者hpatel
相关产品推荐
相关产品推荐

