WebApi Multiple actions were found with GetAll() and GetByIds(int[] ids)

匿名 (未验证) 提交于 2019-12-03 08:41:19

问题:

Using the standard route:

        config.Routes.MapHttpRoute(             name: "DefaultApi",             routeTemplate: "api/{controller}/{id}",             defaults: new { id = RouteParameter.Optional }         ); 

With these actions:

public class ValuesController : ApiController {     // GET api/values     public string GetAll()     {         return "all";     }      // GET api/values/5     public string GetById(int id)     {         return "single";     }      // GET api/values?ids=1&ids=2     public string GetByIds([FromUri] int[] ids)     {         return "multiple";     } 

And make a request to /api/values, I get this exception:

Multiple actions were found that match the request:  System.String GetAll() on type MvcApplication4.Controllers.ValuesController System.String GetByIds(Int32[]) on type MvcApplication4.Controllers.ValuesController 

I've been spinning my wheels trying to find a solution around this. It's my belief that the GetAll and GetByIds actions are considered Multiple here, but they aren't because the GetByIds has a different signature.

Is there a work around for this that doesn't involve adding {action} to the route?

回答1:

Thanks for the input everyone. After kicking options around, the only way I found to do this, is to combine the GetAll and GetByIds action and switch case the length of ids.

public class ValuesController : ApiController {     // GET api/values/5     public string GetById(int id)     {         return "single";     }      // GET api/values     // GET api/values?ids=1&ids=2     public string GetByIds([FromUri] int[] ids)     {         switch (ids.Length)         {             case 0:                 return "all";              default:                 return "multiple";         }     } 


回答2:

We currently do not have out of box support for binding collection of values coming from Uri. Following is the issue regarding that and also the action disambiguation problem:

http://aspnetwebstack.codeplex.com/workitem/322

Unfortunately, i cannot think of a work around related to the Action selection problem(without the '{action}') itself even though you solve the problem of modelbinding to collection using a custom parameter binding like below:

public string GetByIds(int[] ids)     {         return "multiple";     } ------------------------  config.ParameterBindingRules.Insert(0, typeof(int[]), (paramDesc) => new SampleParameterBinding(paramDesc));  -------------------------  public class SampleParameterBinding : HttpParameterBinding {     public SampleParameterBinding(HttpParameterDescriptor desc)         : base(desc)     {     }      public override bool WillReadBody     {         get         {             return false;         }     }      public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)     {         HttpRequestMessage currentRequest = actionContext.Request;          NameValueCollection nvc = currentRequest.RequestUri.ParseQueryString();          //TODO: ERROR CHECKS         int[] ids = nvc["ids"].Split(',').Select(str => Int32.Parse(str)).ToArray();          // Set the binding result here         SetValue(actionContext, ids);          // now, we can return a completed task with no result         TaskCompletionSource<AsyncVoid> tcs = new TaskCompletionSource<AsyncVoid>();         tcs.SetResult(default(AsyncVoid));         return tcs.Task;     }      private struct AsyncVoid     {     } } 


回答3:

I'd recommend attribute routing:

[RoutePrefix("api")] public class ValuesController : ApiController {     // GET api/values     // GET api/values?ids=1&ids=2     [Route("values")]     public string GetCollection([FromUri] IList<int> ids)     {         if (ids == null)         {           return "all";         }         return "multiple";     }      // GET api/values/5     [Route("values/{id:int}")]     public string GetById(int id)     {         return "single";     } 


回答4:

public static class WebApiConfig {     public static void Register(HttpConfiguration config)     {         config.Routes.MapHttpRoute(             name: "DefaultApi",             routeTemplate: "api/{controller}/{action}/{id}",             defaults: new { id = RouteParameter.Optional }         ); 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!