Reputation: 6249
We are developing an MVC4 API application and have run across a strange issue that we have no explanation for.
The API controller has two methods:
[AllowAnonymous]
[AcceptVerbs("Post", "Get")]
public ArtifactContent Post(string userName, string password, string id) ...
and
[AllowAnonymous]
[AcceptVerbs("Get")]
public HttpResponseMessage Get(string userName, string password, string id, EnumType contentType) ...
Although the two methods clearly have different method signatures, we are getting the following error message:
{"Message":"An error has occurred.","ExceptionMessage":"Multiple actions were found that match the request: [XXX].Models.ArtifactContent Post(System.String, System.String, System.String) on type [XXX].API.ArtifactContentController\r\nSystem.Net.Http.HttpResponseMessage Get(System.String, System.String, System.String, ArtifactContentTypes) on type [XXX].API.ArtifactContentController","ExceptionType":"System.InvalidOperationException","StackTrace":" at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)\r\n at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)\r\n at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)"}
We can work around the error by making one of these two changes, but I really want to know why .NET is throwing the error when the two signature are clearly different:
Get
AcceptVerbs
attribute from the Post
methodGet
method to accept the Enum as an integerUpvotes: 4
Views: 1255
Reputation: 27187
This is a known behavior/issue/bug in ASP.NET Web API
.
In short, the action selector (IHttpActionSelector
), will not take into account Enums
when trying to match the incoming HTTP request to a relevant action inside the controller.
The reason is by default only primitive types (i.e. int
, string
etc) are picked from RouteData
to find a matching action. Enum
is not one of those, so it's ignored and therefore, even though your actions have different signatures from the compiler perspective, in the eyes of the action selector they are identical.
You can track the progress of the potential fix here - http://aspnetwebstack.codeplex.com/workitem/312
For the time being, as you said yourself, the best workaround is to pass enum
as int
or string
(and cast to enum
).
Upvotes: 5