22

wCFサービスにあるrestメソッドにjsonデータを投稿するためにjqueryを取得するのに問題があります。

WCF側では、運用契約は次のとおりです。

[OperationContract]
[WebInvoke(Method = "POST",
           BodyStyle = WebMessageBodyStyle.Bare,
           RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "PostSomething")]
MyResult PostSomething(MyRequest request);

との両方MyResultMyRequest必要なすべての属性と属性がマークされておりDataContractDataMemberサービスはWebHttpエンドポイントを公開しています。

JQuery側では、これが私の関数呼び出しです。

var jsonStr = JSON.stringify(reqObj);

$.ajax({
    type: "POST",
    dataType: "json",
    url: "http://localhost/MyService/PostSomething",
    contentType: "application/json; charset=utf-8",
    data: jsonStr,
    success: function (html) {
        alert(html);
    }
});

このリクエストは私のメソッドに到達することはなく(毎回405メソッドが許可されていません)、Charlesでリクエストを見ると次のようになります。

OPTIONS /MyService/PostSomething HTTP/1.1
Host: localhost
Cache-Control: max-age=0
Access-Control-Request-Method: POST
Origin: null
Access-Control-Request-Headers: Content-Type, Accept
Accept: */*
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.237 Safari/534.10
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

これについて奇妙なことがいくつかあります:

  1. メソッドはPOSTではなくOPTIONSです
  2. text/html; charset=UTF-8jsonの代わりに(別のタブの)コンテンツタイプが表示されます
  3. JSONデータはどこにも見られません

ただし、Charlesでリクエストを変更して、ヘッダーがここのソリューションと同様になるようにすると、すべてが機能します。

POST /MyService/PostSomething HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: localhost
Content-Length: 152

{"Id":"", "Name":"testspot","Description":"test" } 

ここでチュートリアルやその他の質問を見ると、他の人がJQueryにこのようなWCF RESTメソッドに投稿させることができましたが、ここで何が間違っているのか途方に暮れています。

ちなみに、これはWCF 4サービスであり、JQuery1.4.4を使用しています。

ありがとう、

アップデート:

もう少し読んだ後、クロスドメイン仕様を教えてくれたDarrelに感謝し、サービスインターフェイスでサービスに小さな変更を加えることで、もう少し先に進むことができました。

[OperationContract]
[WebInvoke(Method = "*",
           BodyStyle = WebMessageBodyStyle.Bare,
           RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "PostSomething")]
MyResult PostSomething(MyRequest request);

実装では、着信要求がOPTIONSに対するものであるかどうかを確認する必要があります。その場合、意図した作業を行うのではなく、いくつかのヘッダーを返します。

if (WebOperationContext.Current.IncomingRequest.Method == "OPTIONS")
{
    WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
    WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST");
    WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept");

    return null;
}

次に、メソッドが2回呼び出されます。最初は、サーバーがnullを返しますが、クライアントにいくつかのヘッダーを追加します。その後、実際の要求はPOSTをメソッドとして使用して行われ、サーバーは先に進んで要求を通常どおり処理します。

4

5 に答える 5

8

これは、クロスドメイン呼び出しを回避するためのFirefoxのもののようです。http://www.petefreitag.com/item/703.cfmを参照してください

この仕様はここhttp://www.w3.org/TR/cors/にあり、非常に簡単に読んだ後、クロスドメイン呼び出しを行っているため、サービスはOPTIONSメソッドを実装して戻ることが期待されているようです。 POSTメソッドの送信を可能にするいくつかのヘッダー。

于 2011-02-02T14:43:26.327 に答える
3

提案された解決策を含む質問の更新にはいくつかの問題があります-それに関する問題は、入力がPOSTメソッドをサポートしていない場合、OPTIONSリクエストが実際に正しい許可されたヘッダーを返さないことです。実際には、WCFエンドポイントで実際に許可されているメソッドを確認していません。クライアントがOPTIONS要求(実際には何がサポートされているかを尋ねるクライアント)を実行すると、アプリケーション内のすべてのエンドポイントで「POST」が許可されると人為的に言っているだけです。 )。

OPTIONSメソッドの情報に依存してメソッドの有効なリストを返さない場合(一部のCORSリクエストの場合のように)、これはおそらく問題ありませんが、そうである場合は、次のようなことを行う必要があります。この質問の解決策: WCFセルフホストでAjaxJQUERYPOSTリクエストを処理する方法

基本的に、各エンドポイントは以下を実装する必要があります。

Webinvoke(Method="OPTIONS", UriTemplate="")

呼び出し元への応答への適切なヘッダー(そのエンドポイントの適切な「Access-Control-Allow-Method」リストを含む)をロードする適切なメソッドを呼び出します。ホストされたWCFエンドポイントがこれを自動的に行わないのはちょっと残念ですが、これはエンドポイントをより細かく制御できる回避策です。そのソリューションでは、適切な応答ヘッダーがエンドポイントの実装でロードされます。

public void GetOptions()
    {
        // The data loaded in these headers should match whatever it is you support on the endpoint
        // for your application. 
        // For Origin: The "*" should really be a list of valid cross site domains for better security
        // For Methods: The list should be the list of support methods for the endpoint
        // For Allowed Headers: The list should be the supported header for your application

        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
        WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization");
    }

それに加えて、バインディングエンドポイントのweb.config、またはエンドポイントを構成するときのWebHttpBindingのコードのいずれかで「CrossDomainScriptAccessEnabled」フラグを設定する必要があります。それ以外の場合、「Access-Control-Allow-Origin」が「*」(またはURLのリスト)であると言うと、ヘッダー応答に再び嘘をつきます。

于 2014-03-17T16:36:59.623 に答える
1

アップデート:

MyServiceの後に.svcを配置して、URLが次のようになるようにしてください

http://localhost/MyService.svc/PostSomething

私は先日自分でこれに取り組んでいて、リック・シュトラールのブログに次のような投稿を見つけました。

http://www.west-wind.com/weblog/posts/324917.aspx

これは私にとって完璧に機能するので、試してみてください!

お役に立てば幸いです。:)

于 2011-02-02T14:00:28.207 に答える
0

web.configでwebhttpbindingを使用しましたか?

webhttpbindingのみがjsonをサポートします。

于 2011-02-02T13:58:58.377 に答える
0

他の回答は役に立たなかったので、私は私を助けた短い回答を投稿します。

  • シナリオ:wcfサービスへのajax呼び出し。
  • エラーの原因:POSTリクエストを送信する前のajaxからの自動OPTIONSリクエスト。最初のリクエストは私のサービスでは処理できませんでした。
  • 解決策:OPTIONSリクエストを許可し、それに応答します。

するべきこと:

  1. これをweb.configに追加します。

    <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
      </customHeaders>
    </httpProtocol>
    

  2. これをGlobal.asax.csに追加します(ソリューションにこのファイルがない場合は、次の方法で作成します:新しいアイテムの追加=> Visual C#=>グローバルアプリケーションクラス(デフォルト名は "Global.asax")):

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
                        HttpContext.Current.Response.End();
    }
    
于 2016-07-15T08:26:47.440 に答える