web-dev-qa-db-ja.com

jQuery .ajax()POST要求はRESTful WCFで405(メソッドは許可されません)をスローします

RESTFUL WCFサービスアプリケーションに投稿リクエストを送信しています。 Fiddlerを介してPOSTリクエストを正常に送信できます。

ただし、jQuery Ajaxメソッドを使用してこれを行うと、関数はChrome Developer Consoleに次を返します。

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

しかし、その後ログの後に:

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

これが私に伝えることは、jQueryがOPTIONSリクエストを送信し、失敗すると、期待されるデータを返すPOSTリクエストを送信するということです。

私の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             
});

JQueryバージョン2.0.2を使用しています。

このエラーが発生している理由に関するヘルプは、非常に役立ちます。

33
Brandon Davis

あなたのコードは実際に クロスドメイン(CORS) requestを作成しようとしていますが、通常のPOSTではありません。

つまり、最新のブラウザーでは、HTMLページと同じ同じドメインのサービスへのAjax呼び出しのみが許可されます。

例:http://www.example.com/myPage.htmlのページは、http://www.example.comのようなhttp://www.example.com/testservice/etcにあるサービスのみを直接リクエストできます。サービスが他のドメインにある場合、ブラウザーは(予想どおり)直接呼び出しを行いません。代わりに、CORS要求を作成しようとします。

簡単に言うと、CORSリクエストを実行するには、ブラウザは次のようにします。

  • 最初にOPTIONリクエストをターゲットURLに送信します
  • そして、ifサーバー応答にOPTIONが含まれている場合のみ 適切なヘッダー(Access-Control-Allow-Originはそのうちの1つ) を許可するCORSリクエストの場合、ブラウズは呼び出しを実行します(HTMLページが同じドメインにある場合とほぼ同じ方法です)。
    • 期待されたヘッダーが届かない場合、ブラウザは単にあきらめます(あなたにしたように)。

それを解決する方法?最も簡単な方法は、サーバーでCORSを有効にする(必要なヘッダーを有効にする)ことです。

サーバー側からアクセスできない場合は、他の場所からWebサービスをミラーリングし、そこでCORSを有効にすることができます。

61
acdcjunior

このコードを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();
            }
        }
5
ali bencharda

フィルターに必要なヘッダーを作成することもできます。

@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);
    }
    ...
}
3
user4227302