ASP.NET Core中如何处理读取失败的额外请求头?
问题背景
将原有ASP.NET MVC项目并行迁移至.NET 6的ASP.NET Core MVC后,部分客户请求返回500错误,但原项目可正常处理这些请求,且无法区分差异请求。新旧项目均部署在Windows Server 2022 Datacenter的IIS上。
已在Configure(WebApplication app)方法开头添加app.UseExceptionHandler()和自定义异常捕获中间件,但无法捕获到触发500错误的异常。
IIS日志片段
#Fields: date time s-ip cs-uri-stem cs-uri-query c-ip sc-status sc-bytes time-taken tag1 2024-02-07 04:05:16 192.168.1.2 /home/CheckThreadPool - 192.168.0.1 200 252 1 tag1 2024-02-07 04:08:06 192.168.1.2 /api/search - 192.168.0.1 500 145 47 -
自定义异常捕获代码
public static void Configure(WebApplication app) { app.UseExceptionHandler(errorApp => { errorApp.Run(async context => { context.Response.Headers["tag1"] = "tag1"; var error = context.Features.Get<IExceptionHandlerFeature>(); if (error != null) { var ex = error.Error; await context.Response.WriteAsync(ex.Message, Encoding.UTF8); } }); }); app.Use(async (context, next) => { try { context.Response.Headers["tag1"] = "tag1"; await next.Invoke(); } catch (Exception ex) { } }); // other code }
异常根源分析
从事件查看器中捕获到未处理异常:
Category: Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer
EventId: 2Connection ID "18158513698363146269", Request ID "4000001e-0000-fc00-b63f-84710c7967bb": An unhandled exception was thrown by the application.
Exception:
System.InvalidOperationException: Operation is not valid due to the current state of the object.at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.StringUtilities.GetAsciiOrUTF8StringNonNullCharacters(ReadOnlySpan
1 span, Encoding defaultEncoding) at Microsoft.AspNetCore.HttpSys.Internal.HeaderEncoding.GetString(Byte* pBytes, Int32 byteCount, Boolean useLatin1) at Microsoft.AspNetCore.HttpSys.Internal.NativeRequestContext.GetUnknownHeadersHelper(IDictionary2 unknownHeaders, Int64 fixup, HTTP_REQUEST* request)
at Microsoft.AspNetCore.HttpSys.Internal.NativeRequestContext.GetUnknownHeaders(IDictionary2 unknownHeaders) at Microsoft.AspNetCore.HttpSys.Internal.RequestHeaders.get_Extra() at Microsoft.AspNetCore.HttpSys.Internal.RequestHeaders.get_Item(String key) at Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.<>c.<StartActivity>b__21_0(Object carrier, String fieldName, String& fieldValue, IEnumerable1& fieldValues)
at System.Diagnostics.LegacyPropagator.ExtractTraceIdAndState(Object carrier, PropagatorGetterCallback getter, String& traceId, String& traceState)
at Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.StartActivity(HttpContext httpContext, Boolean loggingEnabled, Boolean diagnosticListenerActivityCreationEnabled, Boolean& hasDiagnosticListener)
at Microsoft.AspNetCore.Hosting.HostingApplication.CreateContext(IFeatureCollection contextFeatures)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()
结合ASP.NET Core源码逻辑,问题本质是请求头中包含null字符或无法通过UTF-8编码转换为有效字符串。ASP.NET Core在解析这类请求头时会抛出InvalidOperationException,且该异常发生在自定义中间件执行之前,因此无法被代码中的异常捕获逻辑处理。
解决方法
通过排查IIS配置,发现问题源于一个仅兼容.NET Framework的旧模块,该模块会修改请求头并插入无效字符。删除该模块后,项目可正常处理所有请求。
其他排查方向(供类似场景参考)
- 检查客户端请求是否存在异常请求头(如包含非UTF-8字符、null字节),协调客户端修复请求格式;
- 若无法修改客户端请求,可尝试在IIS中添加URL重写规则,过滤或替换无效请求头;
- 升级ASP.NET Core版本,后续版本可能对这类异常场景提供更友好的处理机制。
内容的提问来源于stack exchange,提问作者leonardzheng

