2013-06-27 66 views
28

Tôi đang gửi yêu cầu đăng bài đến một ứng dụng dịch vụ WCF RESTFUL. Tôi có thể gửi thành công yêu cầu POST thông qua Fiddler.jQuery .ajax() Yêu cầu POST ném 405 (Phương thức không được phép) trên RESTful WCF

Tuy nhiên khi tôi làm điều này thông qua các phương pháp jQuery Ajax hàm trả về sau để Console Chrome Developer:

OPTIONS http://www.example.com/testservice/service1.svc/GetData 405 (Method Not Allowed) jquery.min.js:6 

Nhưng sau đó một giây sau khi các bản ghi:

Object {d: "You entered 10"} testpost.html:16 

Điều này nói với tôi là jQuery đang gửi yêu cầu OPTIONS không thành công và sau đó gửi yêu cầu POST trả về dữ liệu dự kiến.

Mã jQuery của tôi:

$.ajax() {   
type: "POST", //GET or POST or PUT or DELETE verb 
    url: "http://www.example.com/testservice/service1.svc/GetData", // Location of the service  
    data: '{"value":"10"}', //Data sent to server 
    contentType:"application/json", 
    dataType: "json", //Expected data format from server  
    processdata: false, 
    success: function (msg) {//On Successfull service call 
     console.log(msg); 
    }, 
    error: function (xhr) { console.log(xhr.responseText); } // When Service call fails    
}); 

Tôi đang sử dụng jQuery phiên bản 2.0.2.

Bất kỳ trợ giúp nào về lý do lỗi này xảy ra sẽ là một trợ giúp tuyệt vời.

Trả lời

54

Mã của bạn thực sự đang cố thực hiện yêu cầu Cross-domain (CORS), không phải là số POST thông thường.

Tức là: Trình duyệt hiện đại sẽ chỉ cho phép các cuộc gọi Ajax đến các dịch vụ trong cùng một miền làm trang HTML.

Ví dụ: Một trang trong http://www.example.com/myPage.html chỉ có thể trực tiếp yêu cầu các dịch vụ có trong http://www.example.com, như http://www.example.com/testservice/etc. Nếu dịch vụ nằm trong miền khác, trình duyệt sẽ không thực hiện cuộc gọi trực tiếp (như bạn mong đợi). Thay vào đó, nó sẽ cố gắng thực hiện một yêu cầu CORS.

Để đặt nó trong thời gian ngắn, để thực hiện một yêu cầu CORS, trình duyệt của bạn:

  • sẽ đầu tiên gửi một yêu cầu OPTION đến URL đích
  • Và sau đó chỉ khi phản ứng máy chủ để OPTION có chứa adequate headers (Access-Control-Allow-Origin is one of them) để cho phép yêu cầu CORS, trình duyệt sẽ thực hiện cuộc gọi (gần như chính xác cách thức nếu trang HTML ở cùng một tên miền).
    • Nếu tiêu đề dự kiến ​​không đến, trình duyệt chỉ đơn giản là từ bỏ (giống như bạn đã làm).

Cách giải quyết? Cách đơn giản nhất là kích hoạt CORS (bật các tiêu đề cần thiết) trên máy chủ.

Nếu bạn không có quyền truy cập phía máy chủ vào nó, bạn có thể phản chiếu dịch vụ web từ một nơi khác và sau đó bật CORS ở đó.

+0

rồi nó làm cho cảm giác bây giờ. Cảm ơn nhiều. –

+0

would't 'jsonp' cũng thực hiện công việc - miễn là nó được máy chủ hỗ trợ? – ProblemsOfSumit

+0

@Sumit Nếu tất cả những gì bạn làm là 'GET', thì ** JSONP ** có thể là một tùy chọn. Tuy nhiên, JSONP là một giải pháp thay vì giải pháp, vì bạn có thể làm những việc rất hạn chế với nó. Bạn không thể làm 'POST' (hoặc 'PUT', vv) thông qua JSONP. – acdcjunior

3

Bạn cũng có thể tạo các tiêu đề bắt buộc trong bộ lọc.

@WebFilter(urlPatterns="/rest/*") 
public class AllowAccessFilter implements Filter { 
    @Override 
    public void doFilter(ServletRequest sRequest, ServletResponse sResponse, FilterChain chain) throws IOException, ServletException { 
     System.out.println("in AllowAccessFilter.doFilter"); 
     HttpServletRequest request = (HttpServletRequest)sRequest; 
     HttpServletResponse response = (HttpServletResponse)sResponse; 
     response.setHeader("Access-Control-Allow-Origin", "*"); 
     response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT"); 
     response.setHeader("Access-Control-Allow-Headers", "Content-Type"); 
     chain.doFilter(request, response); 
    } 
    ... 
} 
+2

Đây không phải là Java? – jonayreyes

4

Bạn phải thêm mã này trong global.aspx:

protected void Application_BeginRequest(object sender, EventArgs e) 
     { 
      HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); 
      if (HttpContext.Current.Request.HttpMethod == "OPTIONS") 
      { 
       HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache"); 
       HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST"); 
       HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); 
       HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000"); 
       HttpContext.Current.Response.End(); 
      } 
     } 
Các vấn đề liên quan