2009-10-22 5 views
7

ich eine WCF-Dienstbibliothek haben durch meine ASPX-Website ausgesetzt alsProblem Aufruf WCF Service Library von jQuery

[System.ServiceModel.OperationContract] 
[System.ServiceModel.Web.WebInvoke(
Method= "POST", 
RequestFormat=System.ServiceModel.Web. WebMessageFormat .Json, 
ResponseFormat=System.ServiceModel.Web.WebMessageFormat .Json)] 
LogonResponse Logon(LogonRequest logonRequest); 


[System.Runtime.Serialization.DataContract] 
[ Serializable()] 
public class LogonRequest 
{ 
[System.Runtime.Serialization.DataMember] 
public string EMailAddress; 
[System.Runtime.Serialization.DataMember] 
public string Password; 
} 

In Meine Testseite folgt kann ich entweder durch MS Ajax nennen: -

<asp:ScriptManager ID ="ScriptManager1" runat="server"> 
<Services> 
<asp:ServiceReference Path="~/testService.svc" /> 
</Services> 
</asp:ScriptManager> 
. 
. 
. 
function clsLogonRequest(eMailAddress, password) { 
this .EMailAddress = eMailAddress; 
this .Password = password; 
} 

function login(eMailAddress, password) { 
var LogonRequest = new clsLogonRequest(eMailAddress, password); 
name.API.IAPI.Logon(LogonRequest, onSuccess, onFailure); 
} 

function onSuccess(result) { 
$("#txtSessionId").val(result.SessionId); 
$("#txtUserName").val(result.Name); 
$("#txtUserId").val(result.UserId); 
} 

das funktioniert gut, oder durch einen jQuery $ Schnipsel Aufruf: -

$(document).ready(function() { 
$("#Button1").click(function() { 
var LogonRequest = new clsLogonRequest('*************' , '***********'); 
$.ajax({ 
type: "POST", 
url: "testService.svc/Logon", 
data: "{'logonRequest':" + JSON.stringify(LogonRequest) + "}" , 
contentType: "application/json; charset=utf-8", 
dataType: "json", 
success: function(msg) { 
alert(msg.d); 
} 
}); 
}); 
}); 

Welche nicht - unter Firebug kann ich sehen, th e 500 Internal Server Error message und die Ausnahme beginnt

{"ExceptionDetail":{"HelpLink":null,"InnerException":null,"Message":"The token '\"' was expected but found '''.","StackTrace":" at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)\u000d\u000a at System.Xml.XmlExceptionHelper .ThrowTokenExpected(XmlDictionaryReader reader, String expected, Char found)\u000d\u000a at System.Runtime... 

Warum scheint es, dass die jQuery Aufruf XML ist vorbei, wenn ich es ausdrücklich sage nicht (und wie kann ich es so zu stoppen, die aus allen Quellen ruft werden so natürlich wie möglich gehandhabt)?

Vielen Dank im Voraus.

EDIT:

Danke für die Vorschläge, habe ich sah, was du gesagt und denke, dass meine Erklärung des Problems nicht klar genug war.

Das Problem ist nicht, dass JSON nicht gesendet wird, es gesendet wird und im richtigen Format ist, kann ich das von Firebug sehen. Das Problem besteht darin, dass die WCF-Servicebibliothek XML erwartet und beim Empfang von JSON umfällt.

Nur um sicher zu sein, habe ich nicht die vorgeschlagene Lösung übersehen, hier ist der web.Config-Extrakt - Ich habe versucht, aus dem Verhalten zu entfernen und entfernen Sie die BehaviorConfiguration Attribut aus dem Services/Service/Endpunkt-Tag und das macht nur das Ganze scheitert, ohne die Seite zu verlassen.

<system.serviceModel> 
<behaviors> 
<serviceBehaviors> 
<behavior name ="MyServiceTypeBehaviors "> 
<serviceDebug includeExceptionDetailInFaults="true" /> 
<serviceMetadata httpGetEnabled="true" /> 
</behavior> 
</serviceBehaviors> 
<endpointBehaviors> 
<behavior name ="AspNetAjaxBehavior"> 
<enableWebScript/> 
</behavior> 
</endpointBehaviors> 
</behaviors> 
<serviceHostingEnvironment aspNetCompatibilityEnabled= "true " /> 
<services> 
<service name ="test.API.API" behaviorConfiguration = " MyServiceTypeBehaviors"> 
<endpoint behaviorConfiguration="AspNetAjaxBehavior" binding = " webHttpBinding" contract="test.API.IAPI" /> 
<endpoint contract ="IMetadataExchange" binding= " mexHttpBinding" address="mex" /> 
</service> 
</services> 
</system.serviceModel> 

Dank im Voraus

Antwort

13

Ich vermute, Sie WebScriptEnablingBehavior (enableWebScript Element in .config) angewendet haben? Dies bewirkt, dass alle Anforderungen in ein JSON-Objekt mit einem einzelnen Feld namens "d" eingeschlossen werden, das dann ein Objekt mit Ihren benannten Parametern enthält. So müssten Sie die jQuery-Daten ändern sein:

data: "{d:{logonRequest:" + JSON.stringify(LogonRequest) + "}}" 

Entweder das, oder entfernen Sie das enableWebScript Verhalten, aber, wenn Sie das tun, können Sie das webHttp Verhalten stattdessen beantragen. Leider ist die Standardkodierung dann XML und das Verhalten bietet keine Schalter, um die Kodierung für einen ganzen Dienst zu steuern (schlechtes Design durch MSFT). Also, entweder müssen Sie sich mit einer einzelnen Codierung für jede Methode verheiraten, indem Sie die Request/ResponseFormat-Eigenschaften festlegen, oder, wie ich das in der Vergangenheit gehandhabt habe, dass ich ein "EnhancedWebHttpElement" erstellt habe, das dasselbe WebHttpBehavior anwendet, aber gibt Config Level Kontrolle über seine verschiedenen Eigenschaften. Der Vorteil der Verwendung dieser Konfiguration besteht darin, dass Sie denselben WCF-Dienst nun über verschiedene Endpunkte bereitstellen können, indem Sie die ASP.NET AJAX-Codierung für einen einfachen JSON-Code auf der anderen und möglicherweise sogar POX für einen anderen verwenden.

Hier ist der Code:

public sealed class EnhancedWebHttpElement : BehaviorExtensionElement 
{ 
    #region Type specific properties 

    [ConfigurationProperty("defaultBodyStyle", DefaultValue=WebMessageBodyStyle.Bare)] 
    public WebMessageBodyStyle DefaultBodyStyle 
    { 
     get 
     { 
      return (WebMessageBodyStyle)this["defaultBodyStyle"]; 
     } 

     set 
     { 
      this["defaultBodyStyle"] = value; 
     } 
    } 

    [ConfigurationProperty("defaultOutgoingRequestFormat", DefaultValue=WebMessageFormat.Xml)] 
    public WebMessageFormat DefaultOutgoingRequestFormat 
    { 
     get 
     { 
      return (WebMessageFormat)this["defaultOutgoingRequestFormat"]; 
     } 

     set 
     { 
      this["defaultOutgoingRequestFormat"] = value; 
     } 
    } 

    [ConfigurationProperty("defaultOutgoingResponseFormat", DefaultValue=WebMessageFormat.Xml)] 
    public WebMessageFormat DefaultOutgoingResponseFormat 
    { 
     get 
     { 
      return (WebMessageFormat)this["defaultOutgoingResponseFormat"]; 
     } 

     set 
     { 
      this["defaultOutgoingResponseFormat"] = value; 
     } 
    }  

    #endregion 

    #region Base class overrides 

    protected override object CreateBehavior() 
    { 
     WebHttpBehavior result = new WebHttpBehavior(); 

     result.DefaultBodyStyle = this.DefaultBodyStyle; 
     result.DefaultOutgoingRequestFormat = this.DefaultOutgoingRequestFormat; 
     result.DefaultOutgoingResponseFormat = this.DefaultOutgoingResponseFormat; 

     return result; 
    } 

    public override Type BehaviorType 
    { 
     get 
     { 
      return typeof(WebHttpBehavior); 
     } 
    } 

    #endregion 
} 

Und dann müssen Sie es registrieren:

<system.serviceModel> 
    <extensions> 
     <behaviorExtensions> 
      <add name="enhancedWebHttp" type="MyNamespace.EnhancedWebHttpElement, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/> 
      </behaviorExtensions> 
    </extensions> 

Und Sie dann verwenden, etwa so:

<behavior name="MyBehavior"> 
    <enhancedWebHttp defaultOutgoingRequestFormat="JSON" defaultOutgoingResponseFormat="JSON" /> 
</behavior> 

UPD ATE:

Diese obige Antwort gilt ausschließlich für .NET 3.x. Wenn Sie .NET 4.x verwenden, können Sie jetzt the DefaultOutgoingResponseFormat property verwenden, das unter WebHttpElement verfügbar ist, um dies zu kontrollieren. Noch besser, Sie können einen einzelnen Endpunkt freilegen und the new AutomaticFormatSelectionEnabled property setzen, der mit dem korrekten Format antwortet, das auf dem Format der ursprünglichen Anfrage basiert.

+0

danke für den Vorschlag, habe ich meinen ursprünglichen Posten geklärt, um zu klären. – bean

+1

Die Ausnahme sieht immer so aus, als würde sie XML analysieren, da dies das von WCF verwendete Modell ist, auch wenn die Daten nicht wirklich XML sind. Im Falle von JSON wird der DataContractJsonSerialzer verwendet, aber selbst dieser erbt von XmlObjectSerializer und so kann der Stack es so aussehen lassen, als würde es mit XML arbeiten. Wenn Sie den kompletten Stack-Trace veröffentlichen könnten, der auch nützlich wäre. Alles andere an Ihrer Konfiguration sieht gut aus, aber mit enableWebScript dort müssen Sie dieses Wrapper-Objekt übergeben, wie ich schon sagte. Wenn Sie das enableWebScript entfernen, müssen Sie die Nachrichtencodierung tatsächlich selbst auf JSON setzen. –

+0

Ich habe buchstäblich die Menge an Arbeit gesehen, die nötig war, um die "WCF Ajax Enabled" Dienste zu "Ajax Enabled" zu machen. –