8

Sử dụng con đường tiêu chuẩn:WebAPI Nhiều hành động được tìm thấy với GetAll() và GetByIds (int [] id)

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

Với những hành động này:

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

Và chắc yêu cầu /api/values ​​, Tôi nhận ngoại lệ này:

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 

Tôi đã quay bánh xe của mình đang cố gắng để f giải quyết xung quanh điều này. Tôi tin rằng GetAllHành động GetByIds được coi là Nhiều tại đây, nhưng không phải vì GetByIds có chữ ký khác.

Có một công việc xung quanh việc này không liên quan đến việc thêm {action} vào tuyến đường không?

+0

bạn có thể đăng các WebAPI Route.Config? – Fals

+0

Đã thêm @Fals, đó là các bit chuẩn – Levitikon

Trả lời

6

Cảm ơn mọi người đã nhập. Sau khi kick tùy chọn xung quanh, cách duy nhất tôi tìm thấy để làm điều này, là kết hợp các hành động GetAll và GetByIds và chuyển đổi trường hợp độ dài của id.

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

Đây cũng là giải pháp duy nhất tôi tìm thấy cho API Web 2. Tuy nhiên, trong trường hợp của tôi, tôi phải kiểm tra 'ids == null' thay vì' ids.Length == 0'. Tôi không chắc liệu đây có phải là sự thay đổi được thực hiện trong Web API 2 hay không, nhưng nếu tôi gọi 'api/values' mà không có bất kỳ giá trị nào cho 'ids', mảng là' null' chứ không phải là rỗng. – Nick

2

Hiện tại chúng tôi không có hỗ trợ ngoài hộp để thu thập ràng buộc các giá trị đến từ Uri. Dưới đây là vấn đề liên quan đến điều đó và cũng là vấn đề hành động định hướng:

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

Thật không may, tôi không thể nghĩ ra một việc xung quanh liên quan đến vấn đề lựa chọn hành động (không có '{action}') bản thân ngay cả khi bạn giải quyết vấn đề về mô hình liên kết với bộ sưu tập bằng cách sử dụng liên kết thông số tùy chỉnh như sau:

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

Đây là một hack. Tại sao bạn sử dụng WebAPI nếu bạn không thú vị trong việc xây dựng một API tài nguyên? Đặt hành động trong URL phá hủy tính trực giao của động từ và URL mà HTTP/REST có ý định có; bạn cũng có thể sử dụng MVC, được xây dựng cho loại RPC này. –

+0

Ngoài ra, bạn thực sự không nên đăng các khối mã mà không có một số loại văn bản giải thích. –

2

tôi khuyên bạn nên thuộc tính định tuyến:

[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"; 
    } 
Các vấn đề liên quan