为何本地无法查看ASP.NET枚举模型绑定异常?
问题描述
我有一个运行在Azure App Service中的ASP.NET Web应用。通过分析器追踪,发现以下三类.NET异常:
Requested value 'Asc' was not found. Asc is not a valid value for SortOrder. The parameter conversion from type 'System.String' to type 'Enums.SortOrder' failed. See the inner exception for more information.
对应的堆栈跟踪:
mscorlib.ni![COLD] System.Enum+EnumResult.SetFailure mscorlib.ni!System.Enum.Parse system.ni! system.web.http!System.Web.Http.ValueProviders.ValueProviderResult.ConvertSimpleType system.web.http!System.Web.Http.ValueProviders.ValueProviderResult.UnwrapPossibleListType system.web.http!System.Web.Http.ValueProviders.ValueProviderResult.ConvertTo system.web.http!System.Web.Http.ModelBinding.Binders.TypeConverterModelBinder.BindModel system.web.http!System.Web.Http.Controllers.HttpActionContextExtensions.Bind system.web.http!System.Web.Http.ModelBinding.Binders.CompositeModelBinder.BindModel system.web.http!System.Web.Http.ModelBinding.ModelBinderParameterBinding.ExecuteBindingAsync system.web.http!System.Web.Http.Controllers.HttpActionBinding+<ExecuteBindingAsyncCore>d__12.MoveNext mscorlib!System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start system.web.http!System.Web.Http.Controllers.HttpActionBinding.ExecuteBindingAsyncCore system.web.http!System.Web.Http.Controllers.HttpActionBinding.ExecuteBindingAsync system.web.http!System.Web.Http.Controllers.ActionFilterResult+<ExecuteAsync>d__5.MoveNext mscorlib!System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.__Canon].Start system.web.http!System.Web.Http.Controllers.ActionFilterResult.ExecuteAsync system.web.http!System.Web.Http.ApiController.ExecuteAsync system.web.http!System.Web.Http.Dispatcher.HttpControllerDispatcher+<SendAsync>d__15.MoveNext mscorlib!System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.__Canon].Start system.web.http!System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync system.net.http.ni! system.web.http!System.Web.Http.Dispatcher.HttpRoutingDispatcher.SendAsync system.net.http.ni! autofac.integration.webapi!Autofac.Integration.WebApi.CurrentRequestHandler.SendAsync system.net.http.ni! Rend.invgen.invoicegateway.api!Rend.invgen.InvoiceGateway.Api.Handlers.RequestResponseLogHandler.SendNextAsync Rend.invgen.invoicegateway.api!Rend.invgen.InvoiceGateway.Api.Handlers.RequestResponseLogHandler+<>c__DisplayClass0_0.<SendAsync>b__0 mscorlib.ni!System.Threading.Tasks.Task.Execute mscorlib.ni!System.Threading.Tasks.Task.ExecutionContextCallback mscorlib.ni!System.Threading.ExecutionContext.Run mscorlib.ni!System.Threading.Tasks.Task.ExecuteWithThreadLocal mscorlib.ni!System.Threading.Tasks.Task.ExecuteEntry mscorlib.ni!System.Threading.Tasks.SynchronizationContextTaskScheduler.PostCallback system.web.ni! mscorlib.ni!System.Threading.Tasks.Task.Execute mscorlib.ni!System.Threading.Tasks.Task.ExecutionContextCallback mscorlib.ni!System.Threading.ExecutionContext.Run mscorlib.ni!System.Threading.Tasks.Task.ExecuteWithThreadLocal mscorlib.ni!System.Threading.Tasks.Task.ExecuteEntry mscorlib.ni!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem mscorlib.ni!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback
引发问题的Action方法:
public async Task<IHttpActionResult> GetAsync(SortOrder sort = SortOrder.Ascending) { // sort something }
当传入Asc这类参数时会触发异常,但绑定失败时会使用默认值Ascending。疑问:为何本地运行应用并传入Asc或Desc时,不会抛出异常,也无法在调试窗口中看到这些异常?
原因分析与解答
这是因为ASP.NET Web API的模型绑定机制在处理枚举参数绑定失败时,会内部捕获异常并回退到使用默认值,但这些异常会被性能分析器(如Azure Application Insights)捕获到,而本地调试时默认的异常捕获配置不会显示这些被框架内部处理的异常。具体细节如下:
- 框架内部异常处理逻辑:Web API的
TypeConverterModelBinder在尝试将字符串转换为枚举类型失败时,会抛出异常,但后续的模型绑定流程会捕获这个异常,然后检查参数是否有默认值。如果有默认值,就会使用默认值继续执行请求,不会将异常抛给上层或返回给客户端。 - 本地调试与生产环境的差异:
- 本地调试时,Visual Studio的默认异常设置不会捕获框架内部处理的异常(这类异常属于“已处理异常”),除非你手动开启“捕获所有异常”(包括已处理的)。
- Azure上的性能分析器(如Application Insights)会追踪所有抛出的异常,不管是否被框架内部处理,所以会记录下这些绑定失败时的异常。
- 本地验证方式:如果想在本地看到这些异常,可以:
- 在Visual Studio中打开“异常设置”(Ctrl+Alt+E),勾选“Common Language Runtime Exceptions”下的“Thrown”选项,这样调试时框架内部抛出的异常会被中断捕获。
- 自定义一个日志过滤器,在模型绑定阶段记录这些异常。
内容的提问来源于stack exchange,提问作者David Klempfner
相关产品推荐
相关产品推荐

