我已经创建了一个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看起来像:
<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;
正如我上面所说,当我在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函数似乎有问题,或者我调用它的方式阻止它在服务器上运行。
答案 0 :(得分:0)
嗯,好吧没关系,我想我正在看错了问题。
400(错误请求)错误让我觉得问题出在我的网络服务调用上。但是当我的Web服务试图调用其他Web服务时,似乎问题实际上发生在服务器端。当我取消对其他Web服务的调用时,我的服务返回了200(成功)。我将假设我所拥有的(如上所述)是正常的,并且该问题与调用其他Web服务有关。也许防火墙问题阻止了从我的服务器到该服务器的呼叫,同时允许它从我的开发机器转到同一台服务器。