2016-04-13 6 views
0

Ich habe einen WCF-Dienst erstellt, den ich für einen domänenübergreifenden Aufruf verwenden möchte (mit jQuery und JSONP). Ich habe den Dienst geschrieben, und wenn ich es im Visual Studio-Debugger ausführe und es von einer Testseite auf meinem lokalen PC aus anrufe, funktioniert es gut. Wenn ich den Dienst für IIS7 auf unserem Server bereitstellen, funktioniert es nicht. Wenn ich es mit Fiddler betrachte, sehe ich, dass ein Fehler von 400 zurückkommt.Fehler 400 beim Aufrufen der WCF-JSONP-Webdienstmethode

Dies ist mein erster Versuch, einen WCF-Dienst zu erstellen, und auch mein erster Versuch mit JSONP. Daher ist es sehr wahrscheinlich, dass ich etwas Einfaches, aber Wichtiges verpasst habe.

Ich habe 2 Methoden zu diesem Service, eine wirklich einfache (genannt GetData), die nur einen String und gibt es - ich dieses erstellt nur die grundlegende Service-Funktionalität zu testen (dh kann ich einfach die URL setzen in einen Browser und ich bekomme ein JSON zurück) und es funktioniert OK.

Die andere, problematisch, ein (genannt GetMatter) dauert ein paar Parameter, ruft eine andere (SOAP) Web-Service, einige Daten zu erhalten und gibt einen Stream zurück, den Anruf zu meiner Callback-Funktion enthält. Dies wird dann in die aufrufende Seite eingefügt, die das Ergebnis anzeigt.

Der Vertrag sieht wie folgt aus:

[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); 


} 

Die Implementierung sieht wie folgt aus:

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)); 

    } 

} 

Meine einfache Test.html Seite sieht wie folgt aus (für die Zwecke dieser Prüfung, die JS-Datei ist nur auf meinem lokalen Q gespeichert: Laufwerk):

<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 ist wie folgt (beachten Sie, dass Ser vice.Legal ist der Namespace, in dem OracleService definiert ist, und MyServer ist der Name des Servers, auf dem ich den Dienst bereitgestellt habe. Wenn im Debugger ausgeführt wird, wird MyServer auf "localhost: Port-Nummer" und das funktioniert OK dann)

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); 

} 

Schließlich sieht die web.config wie:

<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>

Wie ich oben sagte, wenn ich diesen Dienst im Visual Studio-Debugger ausführen, führt meine HTML-Seite das Javascript in TestService.js aus, das Javascript ruft meinen Dienst an (http://localhost:15021/OracleService.svc/GetMatter/matterId/ServiceCallback) und ich lande mit den erwarteten Daten, die auf dem angezeigt werden Seite.

Wenn ich diesen Dienst URL ändern auf dem Server (http://MyServer/Service.Legal.OracleWebService/OracleService.svc/GetMatter/matterId/ServiceCallback) Punkt, erhalte ich eine leere Seite und Fiddler zeigt den Anforderungsfehler 400.

Ein grundlegender Test der Service-Web geben direkt im Browser

gibt die erwarteten JSON-Daten zurück (obwohl IE natürlich nur fragt, ob ich "1.json" öffnen oder speichern möchte, zeigt es nichts im Browser an), so scheint der Dienst selbst zugänglich zu sein und funktioniert in IIS OK. Es scheint nur etwas mit meiner GetMatter-Funktion oder der Art, wie ich sie anrufe, zu funktionieren, die verhindert, dass sie auf dem Server funktioniert.

Antwort

0

Hmm OK, egal, ich glaube, ich habe das falsche Problem gesucht.

Der 400 (schlechte Anfrage) Fehler hat mich denken lassen, dass das Problem mit dem Anruf zu meinem Webservice war. Aber es scheint, dass das Problem tatsächlich auf der Serverseite passiert, wenn mein Webservice versucht, den anderen Webservice anzurufen. Als ich diesen Aufruf an den anderen Webdienst abholte, gab mein Dienst stattdessen eine 200 (Erfolg) zurück. Ich gehe davon aus, dass das, was ich habe (wie oben beschrieben), in Ordnung ist und das Problem etwas mit dem Aufruf des anderen Webdienstes zu tun hat. Vielleicht ein Firewall-Problem, das verhindert, dass der Anruf von meinem Server zu diesem Server geht, während er es von meinem Entwicklungscomputer auf denselben Server zulässt.