2

XDomainRequestに関するすべてのStackOverflow投稿と、AJAXおよびWCFに関するさらに数十の投稿を読んだと思いますが、XDomainRequestAJAX呼び出しを機能させるのにまだ問題があります。WCFサービスにCORS( "Access-Control-Allow-Origin")を実装し、コードはChromeとFirefoxのxmlHttpRequestで正常に機能しますが、クロスドメインで呼び出しを行っているため、IEの場合はXDomainRequestオブジェクト。xdrは、引数のないメソッドに対してGETまたはPOSTすると正常に機能し、クエリ文字列を使用してargsのあるメソッドに対してGET動詞を正常に使用することもできますが、argsのあるメソッドにPOSTしようするBeginRequestメソッドにブレークポイントを設定し、サーバーからの応答が「200 OK」であることがわかりましたが、xdrはエラーをスローします。設定ファイルの設定のすべての組み合わせを試したと思いますが、何かが足りないはずです。私を正しい方向に向ける手助けをしていただければ幸いです。

これが私のコードの適切な部分です:

WCF-Global.asax

protected void Application_BeginRequest(object sender, EventArgs e)
    {
        //for CORS
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
    }

WCF-IService1.cs

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [WebInvoke(Method = "POST")]
    string GetData();

    [OperationContract]
    [WebInvoke(Method = "POST")]
    string GetData2(string param);
}

WCF-Service1.svc

public class Service1 : IService1
{
    public string GetData()
    {
        return "Hello";
    }

    public string GetData2(string param)
    {
        return string.Format("Hello - {0}", param);

    }
}

WCF-Web.config

<?xml version="1.0"?>

<system.web>
    <compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <services>
        <service behaviorConfiguration="WcfService1.Service1Behavior" name="WcfService1.Service1">
            <endpoint address="AjaxEndpoint" behaviorConfiguration="AjaxBehavior" contract="WcfService1.IService1" bindingConfiguration="AjaxBinding"/> 
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="WcfService1.Service1Behavior">
                <!--<serviceMetadata httpGetEnabled="true" />-->
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="AjaxBehavior">
                <enableWebScript/>
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <bindings>
        <webHttpBinding>
            <binding name="AjaxBinding"/>
        </webHttpBinding>
    </bindings>
</system.serviceModel>
<system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>

クライアントAJAX呼び出し

var WcfURL = "http://localhost/WcfService1/Service1.svc/AjaxEndpoint"
if (window.XDomainRequest) {
//IE - use cross-domain request
xdr = new XDomainRequest();
xdr.onprogress = function () { alert("onprogress: " + xdr.responseText) };
xdr.onload = function () { updateText(xdr.responseText) }; 
xdr.onerror = function () { alert("xdr error") };
xdr.timeout = 7500;
xdr.ontimeout = function () { alert("xdr timeout") };

var data = "passedInParam";
//var method = "/GetData";  //this works
var method = "/GetData2";  //this throws an error
xdr.open("POST", WcfURL + method);

xdr.send(data);

}

4

1 に答える 1

4

私は解決策を見つけました。Fiddlerのおかげで、サービスから返ってきた応答をより多く見ることができました。エラーは

着信メッセージのメッセージ形式は「Raw」です。操作に必要なメッセージ形式は「Xml」、「Json」です。これは、WebContentTypeMapperがバインディングで構成されていないことが原因である可能性があります。

この情報を武器に、WebContentTypeMapperの調査を開始しました。この記事は役に立ちました。WebContentTypeMapperメソッドを追加した後、XDomainRequestからのリクエストのcontentTypeが「application / json」タイプであることがわかりました(予想どおり)XDomainRequest.send()メソッドに引数を含めますが、引数が渡されたときに「application / octet-stream」タイプに変更されました。(つまり、xdr.send(data))なぜオクテットに変更されるのかわかりません。 -streamですが、そうすると、サービスメソッドが500エラー(上記のメッセージを含む)をスローするため、xdr要求でエラーが発生します。ただし、WebContentTypeMapperには適切な名前が付けられており、これを使用してcontentTypeを変更するのは簡単です。Jsonと入力するように修正した後、私のxdrは正常に機能しています。

方法は次のとおりです。

public class CustomContentTypeMapper : WebContentTypeMapper
{
    public override WebContentFormat GetMessageFormatForContentType(string contentType)
    {
        if (contentType == "application/octet-stream")
        {
            return WebContentFormat.Json;
        }
        else
        {
            return WebContentFormat.Default;
        }
    }
}

そして、更新された構成ファイルの部分は次のとおりです。

<endpoint address="AjaxEndpoint" behaviorConfiguration="AjaxBehaviour" contract="WcfService1.IService1" binding="customBinding" bindingConfiguration="CustomMapper"/>
...
<bindings>
        <customBinding>
            <binding name="CustomMapper">
                <webMessageEncoding webContentTypeMapperType="WcfService1.CustomContentTypeMapper, WcfService1" />
                <httpTransport manualAddressing="true" />
            </binding>
        </customBinding>
    </bindings>
于 2012-06-22T15:03:43.557 に答える