2013-06-27 14 views
28

Wysyłam prośbę o dodanie do aplikacji usługi RESTFUL WCF. Jestem w stanie wysłać żądanie przez Fiddler.jQuery .ajax() POST Żądania rzutów 405 (Metoda niedozwolona) na RESTful WCF

Jednak kiedy mogę to zrobić za pomocą metody jQuery Ajax funkcja zwraca następujących do konsoli Chrome Developer:

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

ale potem sekundy po kłody:

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

Co to mówi mi jest to, że jQuery wysyła żądanie, które nie powiedzie się, a następnie wysyła żądanie o wartości POST, które zwraca oczekiwane dane.

mój kod jQuery:

$.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    
}); 

używam jQuery w wersji 2.0.2.

Każda pomoc dotycząca tego, dlaczego wystąpił ten błąd, byłaby bardzo pomocna.

Odpowiedz

54

kod jest rzeczywiście próbując złożyć wniosekCross-domain (CORS), a nie zwykły POST.

To znaczy: Nowoczesne przeglądarki będą zezwalać na połączenia Ajax do usług w domenie tej samej domeny jako strony HTML.

Przykład: Strona w http://www.example.com/myPage.html można tylko bezpośrednio zażądać usług, które są w http://www.example.com, jak http://www.example.com/testservice/etc. Jeśli usługa znajduje się w innej domenie, przeglądarka nie wykona bezpośredniego połączenia (jak można się spodziewać). Zamiast tego spróbuje wysłać żądanie CORS.

Mówiąc krótko, aby wykonać wniosek CORS Twoja przeglądarka:

  • najpierw wysłać OPTION wniosek do docelowego adresu URL
  • A potem tylko jeśli odpowiedź serwera do tego OPTION zawiera adequate headers (Access-Control-Allow-Origin is one of them), aby umożliwić żądanie CORS, przeglądarka wykona połączenie (prawie dokładnie tak, jak gdyby strona HTML była w tej samej domenie).
    • Jeśli oczekiwane nagłówki nie przychodzą, przeglądarka po prostu się poddaje (jak to zrobiła).

Jak go rozwiązać? Najprostszym sposobem jest włączenie CORS (włącz niezbędne nagłówki) na serwerze.

Jeśli nie masz do niego dostęp po stronie serwera, możesz zsynchronizować usługę internetową z innego miejsca, a następnie włączyć funkcję CORS.

+0

Dobrze jest sens teraz. Dziękuję Ci bardzo. –

+0

czy 'jsonp' również nie wykona zadania - o ile jest obsługiwany przez serwer? – ProblemsOfSumit

+0

@Sumit Jeśli wszystko, co robisz, to 'GET', wtedy ** JSONP ** może być opcją. Mimo to JSONP jest bardziej rozwiązaniem niż rozwiązaniem, ponieważ można z nim robić bardzo ograniczone rzeczy. Nie możesz zrobić "POST" (lub "PUT" itp.) Poprzez JSONP. – acdcjunior

3

Można również utworzyć wymagane nagłówki w filtrze.

@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

Czy to nie Java? – jonayreyes

4

Należy dodać ten kod w 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(); 
      } 
     }