调用WCF JSONP Web服务方法时出错400

时间:2016-04-13 02:10:09

标签: javascript jquery wcf jsonp

我已经创建了一个WCF服务,我尝试用于跨域调用(使用jQuery和JSONP)。我已经编写了该服务,当我在Visual Studio调试器中运行它并从我本地PC上的测试页面调用它时,它工作正常。当我将服务部署到我们服务器上的IIS7时,它不起作用。与Fiddler一起看,我看到有400错误回来。

这是我第一次尝试创建WCF服务,也是我第一次尝试JSONP,所以很有可能我错过了一些简单而又重要的东西。

我在这个服务上有2个方法,一个非常简单的方法(称为 GetData ),只需要一个字符串并返回它 - 我创建这个只是为了测试基本的服务功能(即我可以只需将URL放入浏览器中,然后我就会收到一些json)并且工作正常。

另一个有问题的(称为 GetMatter )接受一些参数,调用另一个(SOAP)Web服务来获取一些数据并返回包含对我的回调函数的调用的Stream。然后将其插入到显示结果的调用页面中。

合同如下:

    [ServiceContract]
public interface IOracleService
{

    [OperationContract]
    [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "getData/{value}")]
    string GetData(string value);

    [OperationContract]
    [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "getMatter/{matterId}/{callback}")]
    Stream GetMatter(string matterId, string callback);


}

实现如下:

    public class OracleService : IOracleService
{
    public string GetData(string value)
    {
        return string.Format("You entered: {0}", value);
    }


    public Stream GetMatter(string matterId, string callback)
    {

        //call web service
        var serviceResult = <call to web service goes here>;

        //serialize data to json
        JavaScriptSerializer js = new JavaScriptSerializer();
        string jsonResult = js.Serialize(serviceResult.data);
        jsonResult = jsonResult.Substring(1, jsonResult.Length - 2);

        string result = callback + "(" + jsonResult + ");";

        return new MemoryStream(Encoding.UTF8.GetBytes(result));

    }

}

我的简单Test.html页面如下所示(出于此测试的目的,js文件只存储在我的本地Q:驱动器上):

    <html>

<head>
  <script src="./jquery-2.2.2.min.js" type="text/javascript"></script>
</head>

<body>

  <div id="output"></div>
  <div id="output2"></div>

  <script language="javascript">
    var url = "Q:\TestService.js";

    var script = document.createElement("script");
    script.setAttribute("src", url);
    script.setAttribute("type", "text/javascript");
    document.body.appendChild(script);
  </script>


</body>

</html>

TestService.js如下(请注意,Service.Legal是定义OracleService的名称空间,MyServer是我已将服务部署到的服务器的名称。在调试器中运行时,MyServer更改为&#34; localhost:portnumber&#34;然后就可以了。)

    var url = "http://MyServer/Service.Legal.OracleWebService/OracleService.svc/GetData/1";

url += "?" + new Date().getTime().toString(); //append time to prevent caching


var script = document.createElement("script");
script.setAttribute("src", url);
script.setAttribute("type", "text/javascript");
document.body.appendChild(script);


function ServiceCallback(data) {
  console.log("got data: ");
  console.dir(data);

  var result = data;
  var date = new Date(parseInt(result.INVOICE_DATE.substr(6)));

  var output = "<ul>";
  output += "<li>INVOICE DATE: " + date + "</li>";
  output += "<li>TOTAL EXCL GST: " + result.TOTAL_EXCL_GST + "</li>";
  output += "<li>FEE ESTIMATE: " + result.FEE_ESTIMATE + "</li>";
  output += "</ul>";

  $("#output").html(output);

}

最后,web.config看起来像:

&#13;
&#13;
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <authentication mode="Windows" />
  </system.web>
  <system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="webHttpBinding" crossDomainScriptAccessEnabled="true">
          <security mode="Transport">
            <transport clientCredentialType="None" />
          </security>
        </binding>
      </webHttpBinding>
    </bindings>
    <client />
    <services>
      <service name="Service.Legal.OracleWebService.OracleService">
        <endpoint address="" binding="webHttpBinding" contract="Service.Legal.OracleWebService.IOracleService" behaviorConfiguration="webBehaviour" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://MyServer/Service.Legal.OracleWebService/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="webBehaviour">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
      </customHeaders>
    </httpProtocol>
    <modules runAllManagedModulesForAllRequests="true" />
    <directoryBrowse enabled="true" />
    <httpErrors errorMode="Detailed" />
    <validation validateIntegratedModeConfiguration="false" />
  </system.webServer>

</configuration>
&#13;
&#13;
&#13;

正如我上面所说,当我在Visual Studio调试器中运行此服务时,我的html页面在TestService.js中运行javascript,javascript调用我的服务(http://localhost:15021/OracleService.svc/GetMatter/matterId/ServiceCallback),我最终得到了预期的数据显示在页面上。

当我将该服务URL更改为指向服务器(http://MyServer/Service.Legal.OracleWebService/OracleService.svc/GetMatter/matterId/ServiceCallback)时,我得到一个空白页面,Fiddler显示请求给出错误400.

直接在浏览器中对Web服务进行基本测试

http://MyServer/Service.Legal.OracleWebService/OracleService.svc/getData/1

确实返回了预期的json数据(虽然显然IE只是询问我是否要打开或保存&#34; 1.json&#34;它在浏览器中没有显示任何内容),所以服务本身似乎在IIS中可以访问并正常工作。我的GetMatter函数似乎有问题,或者我调用它的方式阻止它在服务器上运行。

1 个答案:

答案 0 :(得分:0)

嗯,好吧没关系,我想我正在看错了问题。

400(错误请求)错误让我觉得问题出在我的网络服务调用上。但是当我的Web服务试图调用其他Web服务时,似乎问题实际上发生在服务器端。当我取消对其他Web服务的调用时,我的服务返回了200(成功)。我将假设我所拥有的(如上所述)是正常的,并且该问题与调用其他Web服务有关。也许防火墙问题阻止了从我的服务器到该服务器的呼叫,同时允许它从我的开发机器转到同一台服务器。