2015-09-10 24 views
5

Tôi có một ứng dụng MVC với một vài trang đơn giản sẽ chủ yếu chạy trên các cuộc gọi API Web. Để đơn giản, tôi muốn đưa chúng vào cùng một dự án. Tôi có thể khởi chạy và điều hướng đến trang của mình tốt, nhưng khi tôi cố gắng gọi API của mình thông qua Ajax, tôi vẫn nhận được lỗi 404 - không thể tìm thấy hàm API.Không thể gọi Trình điều khiển WebAPI thông qua AJAX, khi được lưu trữ với MVC

Đây là tập tin javascript của tôi:

$(document).ready(function() { 
    //set the login button to call our test API function 
    document.getElementById("login_submit").addEventListener("click", GetUser); 

}); 

function GetUser() { 
    var response = $.ajax({   
     url: '/api/User', 
     method: 'GET', 
     contentType: 'application/json; charset=utf-8', 
     success: function (data) { 
      alert("Success!"); 
     }, 
     error: function (request, status, error) { 
      alert(error); 
     } 
    }); 
} 

Và đây là bộ điều khiển của tôi:

namespace MyProject.Controllers.API 
{ 
    public class UserController : ApiController 
    { 
     // GET api/<controller> 
     [HttpGet]   
     public IEnumerable<string> Get() 
     { 
      return new string[] { "value1", "value2" }; 
     } 

     // GET api/<controller>/5 
     [HttpGet]   
     public string Get(int id) 
     { 
      return "value"; 
     } 
    } 
} 

API điều khiển trong thư mục riêng của họ (gọi là "API") bên trong thư mục Controller của tôi trong tôi dự án - đó là lý do tại sao không gian tên chứa "API" trên bộ điều khiển mẫu này.

Khi tôi sử dụng F12 trên trình duyệt để nắm bắt những yêu cầu nhận được gửi đi, tôi có thể thấy rằng cuộc gọi của tôi có thông tin sau:

Request URL: http://localhost:50035/api/User 
Request Method: GET 
Status Code: 404/Not Found 

Bây giờ tôi hiểu là điều này nên tìm API với tên UserController và tìm hàm bằng thẻ [HttpGet] không có đối số, sau đó trả về mảng chuỗi ("value1", "value2"). Thay vào đó nó không tìm thấy gì cả.

Là một lưu ý cuối cùng, đây là cấu hình định tuyến của tôi (và có, nó đã được khởi tạo trên Global.asax):

public static class WebApiConfig 
    { 
     public static void Register(HttpConfiguration config) 
     { 
      // Web API configuration and services 

      // Web API routes 
      config.MapHttpAttributeRoutes(); 

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

UPDATE:

Dựa trên những phản hồi Tôi đã nhận được cho đến nay, tôi đã di chuyển cấu hình Global.asax của mình. Nó tại trông như thế này:

protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 
     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
     GlobalConfiguration.Configure(WebApiConfig.Register); 
     RouteConfig.RegisterRoutes(RouteTable.Routes); 
     BundleConfig.RegisterBundles(BundleTable.Bundles); 

    } 

Bây giờ khi tôi gọi hàm API của tôi, tôi nhận được ... chờ. Nó không trả về một thông điệp thành công. Nó chỉ bị treo. Tôi không nhận được "Thành công!" cảnh báo.

+2

Đơn đặt hàng bạn đăng ký tuyến đường trong phương thức Global.asax Application_Start() là gì? NẾU bạn đang đăng ký các tuyến MVC trước khi WebAPI roues, thì các tuyến api sẽ thất bại! –

+2

Đã sao chép sự cố bằng cách đăng ký tuyến đường MVC _before_ Tuyến đường WebApi. –

+0

Nếu bạn đặt điểm ngắt trong phương thức Get() của bộ điều khiển Người dùng, nó có bị trúng không? –

Trả lời

2

Mặc dù tôi không chắc đó là cùng một vấn đề mà tôi đã đoán trong nhận xét của tôi, nhưng đó là một lý do có thể xảy ra. Vì vậy, bất cứ ai phải đối mặt với vấn đề tương tự, đây là vấn đề.

Công cụ định tuyến MVC cố gắng khớp các yêu cầu đến với các tuyến đường theo cùng thứ tự mà chúng đã được đăng ký.

  1. Vì vậy, nếu bạn đăng ký lộ trình MVC đầu tiên - {controller}/{action}/{id} id: tùy chọn
  2. Và, sau đó đăng ký các tuyến đường WebAPI - api/{controller}/{ id} id: tùy chọn

yêu cầu sau đó đến sẽ được xuất hiện với lộ trình MVC và nếu nó không phù hợp với một PATTERN tuyến đường, sau đó chỉ nó sẽ được kết hợp với các tuyến đường WebAPI.

Bây giờ, nếu bạn có yêu cầu như , nó sẽ phù hợp với mẫu tuyến đường MVC và sẽ KHÔNG được đối sánh với tuyến đường WebAPI. Kết quả là, MvcHandler sẽ cố gắng tạo ra một lớp điều khiển ApiController MVC và gọi phương thức User() trên đó.Kết quả là, khách hàng sẽ nhận được 404 - không tìm thấy tài nguyên!

Ngoài ra, nếu bạn không sử dụng định tuyến thuộc tính, bạn có thể muốn loại bỏ/bình luận dòng này

//config.MapHttpAttributeRoutes(); 

Và đối với an toàn hơn http-động từ-to-api-phương pháp định tuyến, bạn có thể thêm những điều sau đây cấu hình api của bạn.

routes.MapHttpRoute("RestApiRoute", "Api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" }); //this replaces your current api route 
routes.MapHttpRoute("ApiWithActionRoute", "Api/{controller}/{action}/{id}", new { id = RouteParameter.Optional }); 
routes.MapHttpRoute("DefaultApiGetRoute", "Api/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(new string[] { "GET" }) }); 
routes.MapHttpRoute("DefaultApiPostRoute", "Api/{controller}", new { action = "Post" }, new { httpMethod = new HttpMethodConstraint(new string[] { "POST" }) }); 
routes.MapHttpRoute("DefaultApiPutRoute", "Api/{controller}", new { action = "Put" }, new { httpMethod = new HttpMethodConstraint(new string[] { "PUT" }) }); 
routes.MapHttpRoute("DefaultApiDeleteRoute", "Api/{controller}", new { action = "Delete" }, new { httpMethod = new HttpMethodConstraint(new string[] { "DELETE" }) }); 

hai tuyến đường đầu tiên làm cho nó có thể gọi các điểm kết thúc trong [1] REST của tinh khiết cách & tới [2] gọi họ với tên phương pháp (không phù hợp với tiêu chuẩn REST của mặc dù!)

+0

Cảm ơn bạn - điều này rất hữu ích. Tôi đã di chuyển mã của mình và bây giờ tôi có thể vượt qua được lỗi ban đầu mà tôi đã nhận được, nhưng tôi vẫn chưa nhận được "Thành công!" cảnh báo. Vui lòng xem chỉnh sửa của tôi để biết thêm thông tin. – Max

+0

@ user2291983 Tôi không thấy WebApiConfig.Register() trong phương thức khởi động ứng dụng của bạn, tôi có thiếu gì đó không? Và, bạn có thể chỉ cần nhấn http: // localhost: 50035/api/User (điều chỉnh số cổng nếu điều đó đã thay đổi) từ thanh địa chỉ trình duyệt của bạn và xem điều gì sẽ xảy ra? –

+1

WebApiConfig.Register nằm trong lệnh gọi GlobalConfiguration.Configure(). Tôi thành thật không biết điều đó có tác dụng gì nhưng tất cả các cuốn sách của tôi đều làm theo cách đó. Cuộc gọi URL hoạt động như mong đợi - tôi nhận được một đối tượng JSON có chứa mảng chuỗi. – Max

1

Hãy thử

/api/User/Get 

thay vì chỉ/api/người dùng. Nếu bạn muốn làm quen với nó, hãy xem [RoutePrefix] and [Route] để bạn có thể quản lý nội dung này bằng tay.

+1

Tính năng này hoạt động nhưng nó không giống với những gì tôi nghĩ tôi đã hiểu về các cuộc gọi API. Người dùng là tên bộ điều khiển và tôi đang cố gắng gọi hàm GET không có tham số bằng cách sử dụng yêu cầu Nhận HTTP. – Max

+0

@ user2291983 đánh dấu nó là câu trả lời đúng không? :) Tôi biết, MS không phải là quá nóng trên giải thích công cụ này, đặc biệt là khi nó cho bạn thấy kiến ​​trúc định tuyến mặc định. Đó chỉ là cách nó được, mặc dù. . ./{controllerName}/{actionName}/{parameter} hoặc /? parameter = XXX. Khi bạn bắt đầu tạo API tùy chỉnh (có tên khác với 'GET' và 'POST'), nó sẽ có ý nghĩa hơn. – codeMonkey

Các vấn đề liên quan