8

Использование стандартного маршрута:WebAPI несколько действий были обнаружены GETALL() и GetByIds (INT [] ид)

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

С помощью этих действий:

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"; 
    } 

И сделать запрос на /апи/значение, я получаю это исключение:

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 

Я спиннинг моих колес пытается е ind решение вокруг этого. Я считаю, что GetAll и Действия GetByIds считаются действительными Несколько здесь, но это не потому, что у GetByIds есть другая подпись.

Есть ли работа для этого, которая не предполагает добавления {action} к маршруту?

+0

Не могли бы вы опубликовать WebAPI Route.Config? – Fals

+0

Добавлено @Fals, это стандартные биты – Levitikon

ответ

6

Спасибо за ввод всех. После того, как вы выбрали опцию, единственный способ, которым я нашел это, - объединить действие GetAll и GetByIds и переключить регистр длины идентификаторов.

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"; 
     } 
    } 
+0

Это тоже единственное решение, которое я нашел для Web API 2. Однако в моем случае я должен проверить на 'ids == null', а не на' ids.Length == 0'. Я не уверен, что это было изменение в Web API 2, но если я буду называть 'api/values' без каких-либо значений для' ids', массив будет 'null', а не пустым. – Nick

2

В настоящее время у нас нет поддержки в ящике для привязки коллекции значений, исходящих от Uri. Ниже вопрос о том, что и также проблемах действий многозначных:

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

К сожалению, я не могу думать о работе вокруг связанной с проблемой выбора действий (без «{действия}») себя, даже если вы решить проблему привязки модели к сборке, используя привязку настраиваемого параметра, как показано ниже:

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 
    { 
    } 
} 
0
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 } 
     ); 
+1

Это взломать. Почему вы используете WebAPI, если вам не интересно создавать API-интерфейс ресурса? Приведение действия в URL-адрес уничтожает ортогональность глагола и URL-адреса, которые должен иметь HTTP/REST; вы можете просто использовать MVC, который создается для такого рода RPC. –

+0

Кроме того, вы действительно не должны размещать блоки кода без какого-либо объяснительного текста. –

2

Я бы рекомендовал атрибут маршрутизации:

[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"; 
    }