2009-12-14 14 views
5

Sto impazzendo qui. Ho guardato le seguenti voci e nessuno di loro è correggere il comportamento aberrante che sto vedendo:.NET ASMX - Restituzione di Pure JSON?

Ho anche guardato e confermato il mio setup: http://www.asp.net/AJAX/documentation/live/ConfiguringASPNETAJAX.aspx

Ecco il mio codice (codice ASMX dietro):

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

Quando eseguo questo dal mio esempio localhost sto ottenendo questo risultato insieme:

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

Che cosa mi manca ???


NOTA: Sto usando il framework 3.5 (o almeno Pensavo di come tutto nel mio web.config è contrassegnato per 3.5.0.0)


UPDATE: Sto navigando a il servizio e utilizzando la casella di input su quella pagina. Puoi provare qui: http://dev.rivworks.com/services/Negotiate.asmx?op=GetSetup. Stiamo anche provando ad accedervi da un'app Web basata su JS in esecuzione su un altro sito (lo scopo principale di questo particolare servizio). Non ho il codice per questo qui. (Scusate, il modulo di test è disponibile solo da localhost.)


UPDATE: ho aggiunto la seguente pagina di prova (JsonTest.htm) per cercare di vedere che cosa stava succedendo e indietro. Tutto quello che ottengo è un errore di 500! Ho persino provato ad associarmi al processo e ad entrare nel mio servizio. L'errore 500 viene generato prima che la pipeline ASP venga inserita nel mio codice.

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

Perché è così dolorosamente difficile?!?! :)


AGGIORNAMENTO: Utilizzo di un servizio WCF. Qui è la mia messa a punto: Interfaccia:

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

Classe:

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> 

semplice pagina di prova

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

E ora sto ottenendo questo errore: IIS 'IntegratedWindowsAuthentication, Anonymous' schemi di autenticazione specificati, ma il legame supporta solo le specifiche di esattamente un schema di autenticazione Gli schemi di autenticazione validi sono Digest, Negotiate, NTLM, Basic o Anonymous. Modificare le impostazioni di IIS in modo che venga utilizzato un unico schema di autenticazione.

Come gestirlo? < state emotion = 'wrung out' physical = 'beat up'/>

+0

È possibile inserire il codice che si sta utilizzando per richiamare il servizio? –

+0

Keith, per quanto riguarda il tuo ultimo aggiornamento, perché non provi ad auto-ospitare la tua applicazione WCF solo per i test? Eliminerà IIS dall'equazione. L'auto hosting con un'applicazione Console è molto semplice. (controlla WCFHost.cs nella mia risposta). –

+0

Hai risolto il problema con IIS eliminando la sicurezza integrata (che non stavamo comunque utilizzando). Ora ricevi un errore di 500 su SVC. --- La conversione da un host ospitato a un sito Web ospitato non è un grosso problema? Abbiamo intenzione di farlo funzionare la scorsa settimana. "Dovrebbero solo prendere 10 minuti". Forse dovrei "dentro" il problema ora. –

risposta

8

Perché non si esegue la migrazione del servizio Web ASMX in WCF?

L'API WCF in .NET Framework 3.5 supporta i servizi Web JSON in modo nativo.

Inoltre, Microsoft ha dichiarato ASMX come "tecnologia legacy" e suggerisce "I servizi Web e i client del servizio Web XML devono ora essere creati utilizzando Windows Communication Foundation (WCF)". (Source).

Si consiglia di controllare questi link per iniziare:

Inoltre, potresti anche voler leggere il seguente esempio che ho "estratto" da un mio progetto WCF auto-ospitato. I servizi WCF self-hosted non richiedono IIS, ma possono essere offerti da qualsiasi applicazione .NET gestita. Questo esempio è ospitato in modo molto semplice C# applicazione console:

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

using System; 
using System.Collections.Generic; 
using System.ServiceModel; 
using System.ServiceModel.Web; 
using System.ServiceModel.Description; 
using System.Threading; 
using System.Text; 

namespace MyFirstWCF 
{ 
    class Program 
    { 
     private static WebServiceHost M_HostWeb = null; 

     static void Main(string[] args) 
     { 
      M_HostWeb = new WebServiceHost(typeof(MyFirstWCF.Service)); 

      M_HostWeb.Open(); 

      Console.WriteLine("HOST OPEN"); 
      Console.ReadKey(); 

      M_HostWeb.Close(); 
     } 
    } 
} 

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> 

L'esempio sopra è molto semplice. Se si crea una richiesta con Fiddler a http://127.0.0.1:8000/api/CustomerName/1000, verrà semplicemente restituito "Customer Name: 1000".

Assicurarsi di impostare content-type: application/json nell'intestazione della richiesta. Per restituire strutture di dati più complesse, sarà necessario utilizzare i Contratti di dati. Questi sono costruiti come segue:

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

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

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

È necessario aggiungere riferimenti .NET di System.RuntimeSerialization, System.ServiceModel e System.ServiceModel.Web per questo progetto di esempio per la compilazione.

+0

Hmmm. Sembra che qualcosa sia FUBAR sulla mia macchina. Non ho un'opzione per creare un servizio WFC AJAX. C'è qualcosa che dovrei installare su VS2008? –

+0

È possibile semplicemente creare un normale servizio WCF; puoi decorare la tua interfaccia con gli attributi per indicare che ResponseFormat sarà JSON. –

+0

Non ho un'opzione per creare * qualsiasi * servizio WCF. http://screencast.com/t/OGQwMDlk –

3

Qual è il "tipo di contenuto" impostato sulla richiesta per il metodo?

Da quello che ho fatto con ASP.NET, se è impostato su text/xml, si otterrà di nuovo XML; ma se è impostato su application/json, riavrai JSON.

+0

application/json in JS. Nota: il JS non è sulle nostre pagine! Il WS deve rispondere a una richiesta JS straniera. –

+0

Penso che il punto sia che restituirà la risposta nel tipo richiesto, che sembra essere "text/xml" nell'esempio. Anche se non è una richiesta da qualcosa che hai scritto, puoi facilmente scrivere un tuo piccolo script JS per testarlo con 'application/json' –

+0

Il tipo di contenuto è molto importante. Grazie! –

Problemi correlati