2009-12-14 2 views
5

Ich gehe hier verrückt. Ich habe in den folgenden Einträgen gesucht und keine von ihnen sind Korrektur des Fehlverhaltens Ich bin Mit:.NET ASMX - Rückgabe von reinem JSON?

ich auch geschaut haben und bestätigte mein Setup: http://www.asp.net/AJAX/documentation/live/ConfiguringASPNETAJAX.aspx

Hier ist mein Code (ASMX - Code hinten):

namespace RivWorks.Web.Services 
{ 
    /// <summary> 
    /// Summary description for Negotiate 
    /// </summary> 
    [WebService(Namespace = "http://rivworks.com/webservices/")] 
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
    [ToolboxItem(false)] 
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    [ScriptService] 
    public class Negotiate : System.Web.Services.WebService 
    { 
     [WebMethod] 
     [ScriptMethod(ResponseFormat = ResponseFormat.Json)] 
     public RivWorks.Data.Objects.rivProduct GetSetup(string jsonInput) 
     { 
      // Deserialize the input and get all the data we need... 
      // TODO: This is a quick hack just to work with this for now... 
      char[] tokens = { '(', '{', '}', ')', ',', '"' }; 
      string[] inputs = jsonInput.Split(tokens); 
      string inputRef = ""; 
      string inputDate = ""; 
      string inputProductID = ""; 
      for (int i = 0; i < inputs.Length; i++) 
      { 
       if (inputs[i].Equals("ref", StringComparison.CurrentCultureIgnoreCase)) 
        inputRef = inputs[i+2]; 
       if (inputs[i].Equals("dt", StringComparison.CurrentCultureIgnoreCase)) 
        inputDate = inputs[i+2]; 
       if (inputs[i].Equals("productid", StringComparison.CurrentCultureIgnoreCase)) 
        inputProductID = inputs[i+2]; 
      } 

      Guid pid = new Guid(inputProductID); 
      RivWorks.Data.Objects.rivProduct product = RivWorks.Data.rivProducts.GetProductById(pid); 

      return product; 
     } 
    } 

Als ich das von meinem localhost Beispiel führe ich dieses Ergebnis Set bin immer:

<ResultSet> 
    <uiType>modal</uiType> 
    <width>775</width> 
    <height>600</height> 
    <swfSource> 
    http://localhost.rivworks.com/flash/negotiationPlayer.swf 
    </swfSource> 
    <buttonConfig> 
    http://cdn1.rivworks.com/Element/Misc/734972de-40ae-45f3-9610-5331ddd6e8f8/apple-logo-2.jpg 
    </buttonConfig> 
    </ResultSet> 

Was bin ich ???


HINWEIS: Ich bin mit dem 3.5 Framework (oder zumindest dachte ich, ich war als alles, was in meinem web.config für 3.5.0.0 markiert ist)


UPDATE: Ich bin gerade zu den Dienst und das Eingabefeld auf dieser Seite verwenden. Sie können hier versuchen: http://dev.rivworks.com/services/Negotiate.asmx?op=GetSetup. Wir versuchen auch, darauf über eine JS-basierte Web-App zuzugreifen, die auf einer anderen Website läuft (der Hauptzweck dieses speziellen Dienstes). Ich habe den Code dafür hier nicht. (Leider hat die Testform ist vom lokalen Host zur Verfügung.)


UPDATE: Ich habe die folgende Testseite (JsonTest.htm), um zu versuchen, um zu sehen, was hin und her ging. Alles was ich bekomme ist ein 500 Fehler! Ich habe sogar versucht, mich an den Prozess zu binden und in meinen Dienst einzutreten. Der 500-Fehler wird ausgelöst, bevor die ASP-Pipeline überhaupt in meinen Code gelangt.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <title>Untitled Page</title> 
    <script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.js" type="text/javascript"></script> 

    <script language="javascript" type="text/javascript"> 
     function sendReq() { 
      alert("Before AJAX call"); 
      $.ajax(
      { 
       type: "POST" 
       , url: "http://kab.rivworks.com/Services/Negotiate.asmx/GetSetup" 
       , data: "{ \"ref\":\"http://www.rivworks.com/page.htm\", \"dt\":\"Mon Dec 14 2009 10:45:25 GMT-0700 (MST)\", \"productId\":\"5fea7947-251d-4779-85b7-36796edfe7a3\" }" 
       , contentType: "application/json; charset=utf-8" 
       , dataType: "json" 
       , success: GetMessagesBack 
       , error: Failure 
      } 
      ); 
      alert("After AJAX call"); 
     } 
     function GetMessagesBack(data, textStatus) { 
      alert(textStatus + "\n" + data); 
     } 
     function Failure(XMLHttpRequest, textStatus, errorThrown) { 
      alert(textStatus + "\n" + errorThrown + "\n" + XMLHttpRequest); 
     } 
    </script> 
</head> 
<body> 
    <div id="test">Bleh</div> 
    <a href="javascript:sendReq()">Test it</a> 
</body> 
</html> 

Warum ist das so schmerzhaft schwer?!?! :)


UPDATE: Durch einen WCF-Dienst arbeiten. Hier ist mein Setup: Schnittstelle:

namespace RivWorks.Web.Services 
{ 
    [ServiceContract(Name = "Negotiater", Namespace = "http://www.rivworks.com/services")] 
    public interface INegotiaterJSON 
    { 
     //[WebMethod] 
     [OperationContract] 
     [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] 
     [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)] 
     ResultSet GetSetup(string jsonInput); 
    } 
} 

Klasse:

namespace RivWorks.Web.Services 
{ 
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] 
    public class Negotiater : INegotiaterJSON 
    { 
     public ResultSet GetSetup(string jsonInput) 
     { 
      //code removed for brevity - see ASMX code above if you are really interested. 
      return resultSet; 
     } 
    } 


    [DataContract()] 
    public class ResultSet 
    { 
     [DataMember] 
     public string uiType = "modal"; 
     [DataMember] 
     public int width = 775; 
     [DataMember] 
     public int height = 600; 
     [DataMember] 
     public string swfSource = ""; 
     [DataMember] 
     public string buttonConfig = ""; 
    } 
} 

web.Config

<system.serviceModel> 
    <bindings> 
     <basicHttpBinding> 
     <binding name ="soapBinding"> 
      <security mode="None" /> 
     </binding> 
     </basicHttpBinding> 
     <webHttpBinding> 
     <binding name="webBinding"> 
      <security mode="None" /> 
     </binding> 
     </webHttpBinding> 
    </bindings> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior name="poxBehavior"> 
      <webHttp/> 
     </behavior> 
     <behavior name="jsonBehavior"> 
      <enableWebScript /> 
     </behavior> 
     </endpointBehaviors> 
     <serviceBehaviors> 
     <behavior name="defaultBehavior"> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
      <serviceMetadata httpGetEnabled="true" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <services> 
     <service name="RivWorks.Web.Services.Negotiater" behaviorConfiguration="defaultBehavior"> 
     <endpoint address="json" 
        binding="webHttpBinding" 
        bindingConfiguration="webBinding" 
        behaviorConfiguration="jsonBehavior" 
        contract="RivWorks.Web.Services.INegotiaterJSON" /> 
     </service> 
    </services> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"> 
     <baseAddressPrefixFilters> 
     <add prefix="http://dev.rivworks.com" /> 
     </baseAddressPrefixFilters> 
    </serviceHostingEnvironment> 
    </system.serviceModel> 

einfache Testseite

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <title>Untitled Page</title> 
    <script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.js" type="text/javascript"></script> 

    <script language="javascript" type="text/javascript"> 
     function sendReq() { 
      alert("Before AJAX call"); 
      $.ajax(
      { 
       type: "POST" 
       , url: "http://dev.rivworks.com/Services/Negotiater.svc/GetSetup" 
       , data: "{ \"ref\":\"http://www.rivworks.com/page.htm\", \"dt\":\"Mon Dec 14 2009 10:45:25 GMT-0700 (MST)\", \"productId\":\"5fea7947-251d-4779-85b7-36796edfe7a3\" }" 
       , contentType: "application/json; charset=utf-8" 
       , dataType: "json" 
       , success: GetMessagesBack 
       , error: Failure 
      } 
      ); 
      alert("After AJAX call"); 
     } 
     function GetMessagesBack(data, textStatus) { 
      alert(textStatus + "\n" + data); 
     } 
     function Failure(XMLHttpRequest, textStatus, errorThrown) { 
      alert(textStatus + "\n" + errorThrown + "\n" + XMLHttpRequest); 
     } 
    </script> 

</head> 
<body> 
    <div id="test">Bleh</div> 
    <!--<button onclick="javascript:sendReq()">TEST IT</button>--> 
    <a href="javascript:sendReq()">Test it</a> 
</body> 
</html> 

Und jetzt habe ich diese Störung erhalte: IIS angegebenen Authentifizierungsschemata 'IntegratedWindowsAuthentication, Anonymous', aber die Bindung unterstützt nur Spezifikation von genau einem Authentifizierungsschema. Gültige Authentifizierungsschemas sind Digest, Negotiate, NTLM, Basic oder Anonym. Ändern Sie die IIS-Einstellungen, sodass nur ein einziges Authentifizierungsschema verwendet wird.

Wie gehe ich damit um? < state emotion = 'ausgewrungen' physical = 'schlagen'/>

+0

Können Sie den Code posten, den Sie verwenden, um den Dienst aufzurufen? –

+0

Keith, warum versuchen Sie nicht, Ihre WCF-Anwendung nur zum Testen selbst zu hosten? Es wird IIS aus der Gleichung nehmen. Self-Hosting mit einer Konsolenanwendung ist sehr einfach. (Überprüfen Sie WCFHost.cs in meiner Antwort). –

+0

Das IIS-Problem wurde behoben, indem die integrierte Sicherheit (die wir sowieso nicht verwendeten) gelöscht wurde. Jetzt bekomme ich einen 500 Fehler auf dem SVC. --- Konvertieren von einem selbst gehosteten zu einem Web gehostet ist keine große Sache? Wir haben das letzte Woche in Betrieb genommen. "Sollte nur 10 Minuten dauern". Vielleicht bin ich jetzt zu "in" dem Problem. –

Antwort

8

Warum migrieren Sie Ihren ASMX-Webservice nicht zu WCF?

Die WCF-API in .NET Framework 3.5 unterstützt JSON-Webdienste nativ.

Darüber hinaus erklärte Microsoft ASMX als "Legacy-Technologie" und schlägt vor, "Web-Services und XML-Web-Service-Clients sollten nun mit Windows Communication Foundation (WCF) erstellt werden". (Source).

Möglicherweise möchten Sie diese Links überprüfen, um zu beginnen:

Darüber hinaus möchten Sie vielleicht auch das folgende Beispiel lesen, das ich aus einem selbst gehosteten WCF-Projekt von mir "extrahiert" habe. Self-hosted WCF-Dienste benötigen keinen IIS, können aber von jeder verwalteten .NET-Anwendung bereitgestellt werden.

IContract.cs

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Runtime.Serialization; 
using System.ServiceModel; 
using System.ServiceModel.Web; 

namespace MyFirstWCF 
{ 
    [ServiceContract] 
    public interface IContract 
    { 
     [OperationContract] 
     [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "/CustomerName/{CustomerID}")] 
     string GET_CustomerName(string CustomerID); 
    } 
} 

Service.cs

using System; 
using System.Collections.Generic; 
using System.Runtime.Serialization; 
using System.ServiceModel; 
using System.ServiceModel.Activation; 
using System.ServiceModel.Syndication; 
using System.ServiceModel.Web; 

namespace MyFirstWCF 
{ 
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] 
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.NotAllowed)] 
    public class Service : IContract 
    { 
     public string GET_CustomerName(string CustomerID) 
     { 
      return "Customer Name: " + CustomerID; 
     } 
    } 
} 

WCFHost.cs (Console: In diesem Beispiel wird in einem sehr einfachen C# -Konsolenanwendung gehostet Anwendung)

app.config

<?xml version="1.0" encoding="utf-8" ?> 

<configuration> 
    <system.serviceModel> 
    <services> 
     <service name="MyFirstWCF.Service"> 

     <endpoint address="http://127.0.0.1:8000/api" 
        binding="webHttpBinding" 
        contract="MyFirstWCF.IContract" /> 

     </service> 
    </services> 

    </system.serviceModel> 
</configuration> 

Das obige Beispiel ist sehr einfach. Wenn Sie eine Anfrage mit Fiddler an http://127.0.0.1:8000/api/CustomerName/1000 erstellen, wird einfach "Customer Name: 1000" zurückgegeben.

Stellen Sie sicher, dass die content-type: application/json im Anforderungsheader festgelegt ist. Um komplexere Datenstrukturen zurückzugeben, müssen Sie Datenkontrakte verwenden. Diese sind wie folgt aufgebaut:

[DataContract] 
public class POSITION 
{ 
    [DataMember] 
    public int  AssetID { get; set; } 

    [DataMember] 
    public decimal Latitude { get; set; } 

    [DataMember] 
    public decimal Longitude { get; set; } 
} 

Sie müssen .NET Verweise auf System.RuntimeSerialization, System.ServiceModel und System.ServiceModel.Web für dieses Beispiel Projekt hinzufügen zu kompilieren.

+0

Hmmm. Scheint, dass etwas auf meinem Rechner FUBAR ist. Ich habe keine Möglichkeit, einen AJAX WFC Service zu erstellen. Gibt es etwas, das ich auf VS2008 installieren sollte? –

+0

Sie können einfach einen normalen WCF-Dienst erstellen. Sie können Ihre Schnittstelle mit Attributen dekorieren, um anzuzeigen, dass das ResponseFormat JSON ist. –

+0

Ich habe keine Option zum Erstellen * irgendein * WCF-Dienst. http://screencast.com/t/OGQwMDlk –

3

Was ist der "Content-Type", der bei der Anforderung der Methode festgelegt wurde?

Von dem, was ich mit ASP.NET getan habe, wenn es auf text/xml festgelegt ist, erhalten Sie XML zurück; aber wenn es auf application/json eingestellt ist, erhalten Sie JSON zurück.

+0

Anwendung/JSON in JS. Hinweis: Das JS befindet sich nicht auf unseren Seiten! Der WS muss auf eine ausländische JS-Anfrage antworten. –

+0

Ich denke, der Punkt ist, dass es die Antwort im angeforderten Typ zurückgibt, die in Ihrem Beispiel 'text/xml' zu sein scheint. Auch wenn es keine Anfrage von etwas ist, das Sie geschrieben haben, könnten Sie einfach ein kleines JS-Skript schreiben, um es mit 'application/json' zu testen. –

+0

Der Inhaltstyp ist sehr wichtig. Vielen Dank! –