I have an ASP.NET web app running in an Azure app service.
After doing a profiler trace, I noticed these three .NET exceptions:
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.
They all have this stack trace:
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
My action method which is causing this issue looks like this:
public async Task<IHttpActionResult> GetAsync(SortOrder sort = SortOrder.Ascending)
{
// sort something
}
This action method is called using arguments such as Asc
.
Even though this seems to cause .NET exceptions, the default value of Ascending
gets used if it can't bind a value.
My question is, why am I unable to view the Requested value Asc was not found
exceptions locally?
When I run the app locally and pass Asc
and Desc
, no Exceptions are thrown, and I can't see any Exceptions in the Debug window either.
By default, Binding an Enum
expects the integer value corresponding to the value.
If you want to supply a string
value, you must tell the modelbinder that by adding an attribute to your Enum
type declaration, like this:
[ModelBinder(BinderType = typeof(EnumModelBinder))]
public enum SortOrder
{
}
or you can add an attribute to your property in the model, like this:
[BindProperty(BinderType = typeof(EnumModelBinder))]
public SortOrder MySortOrder {get;set;}
Now the modelbinder should be able to handle strings. Of course the strings must match the enum values exact.
BTW: Modelbinding, that fails, does not throw exceptions, it simply ignores the values, meaning properties will get their default values.