2010-01-13 6 views
11

Non sono sicuro di dove sto andando male di quello che mi manca.ASP.NET WebService sta avvolgendo la mia risposta JSON con i tag XML

Sto costruendo un'applicazione Web ASP.NET 2.0 (sul .Net 3.5 framework) e includo un servizio web. Si noti che questo è non un progetto MVC. Vorrei esporre un metodo che restituirà una stringa JSON; formattato per alimentare il plugin jQuery jqGrid.

Questo è il metodo di prova preliminare Ho implementato nel mio servizio: grazie a (Phil Haack's Guide for MVC)

[WebMethod] 
[ScriptMethod(ResponseFormat = ResponseFormat.Json)] 
public string getData() 
{ 
    JavaScriptSerializer ser = new JavaScriptSerializer(); 

    var jsonData = new 
    { 
     total = 1, // we'll implement later 
     page = 1, 
     records = 3, // implement later 
     rows = new[]{ 
      new {id = 1, cell = new[] {"1", "-7", "Is this a good question?", "yay"}}, 
      new {id = 2, cell = new[] {"2", "15", "Is this a blatant ripoff?", "yay"}}, 
      new {id = 3, cell = new[] {"3", "23", "Why is the sky blue?", "yay"}} 
     } 
    }; 

    return ser.Serialize(jsonData); //products.ToString(); 
} 

Quando viene richiamato questo sta ritornando (formattato per chiarezza):

<?xml version="1.0" encoding="utf-8" ?> 
<string mlns="http://tempuri.org/"> 
{ 
    "total":1, 
    "page":1, 
    "records":3, 
    "rows": 
    [ 
     {"id":1,"cell":["1","-7","Is this a good question?","yay"]}, 
     {"id":2,"cell":["2","15","Is this a blatant ripoff?","yay"]}, 
     {"id":3,"cell":["3","23","Why is the sky blue?","yay"]} 
    ] 
} 
</string> 

Come sarebbe Otterrò la risposta sopra senza gli involucri xml?

risposta

8

tre cose che non può essere facendo:

  • Marcatura il metodo statico
  • Esecuzione di una mano POST
  • un vuoto "{}" per i dati in jQuery.

Potrebbe esserci un modo per chiamare il metodo con un GET, ho sempre usato solo POST. Sono stato in grado di ottenere il vostro esempio lavorare con questo:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<script> 
    // In your javascript block 
    $(document).ready(function() 
    { 
     $.ajax({ 
      url: "/Default.aspx/Tester", 
      type: "POST", 
      contentType: "application/json; charset=utf-8", 
      dataType: "json", 
      data: "{}", 
      success: done 
     }); 
    }); 

    function done(data) 
    { 
     // Include http://www.json.org/json2.js if your browser doesn't support JSON natively 
     var data = JSON.parse(data.d); 
     alert(data.total); 
    } 
</script> 

Il codice dietro (non è necessario creare un webservice, si può mettere questo nel vostro default.aspx):

[WebMethod] 
public static string Tester() 
{ 
    JavaScriptSerializer ser = new JavaScriptSerializer(); 

    var jsonData = new 
    { 
     total = 1, // we'll implement later 
     page = 1, 
     records = 3, // implement later 
     rows = new[]{ 
       new {id = 1, cell = new[] {"1", "-7", "Is this a good question?", "yay"}}, 
       new {id = 2, cell = new[] {"2", "15", "Is this a blatant ripoff?", "yay"}}, 
       new {id = 3, cell = new[] {"3", "23", "Why is the sky blue?", "yay"}} 
      } 
     }; 

    return ser.Serialize(jsonData); //products.ToString(); 
} 

il risultato:

{"d":"{\"total\":1,\"page\":1,\"records\":3,\"rows\":[{\"id\":1,\"cell\":[\"1\",\"-7\",\"Is this a good question?\",\"yay\"]},{\"id\":2,\"cell\":[\"2\",\"15\",\"Is this a blatant ripoff?\",\"yay\"]},{\"id\":3,\"cell\":[\"3\",\"23\",\"Why is the sky blue?\",\"yay\"]}]}"} 

Una spiegazione più dettagliata è here

+0

Come hai ottenuto il risultato. Quando implemento il tuo aspetto, sembra che restituisca "[oggetto oggetto]". Questo potrebbe essere ingenuo per JSON, ma non riesco a farlo funzionare. – Mike

+0

Ho usato firebug in Firefox per visualizzare la risposta dal pannello Rete: fare clic sulla scheda risposta per quella richiesta. –

+0

Sapete perché i dati vengono inclusi nella variabile "d"? – Mike

9

Nel codice, non "restituire" il json. Utilizzare invece:

Context.Response.Write(ser.Serialize(jsonData));

allora sarete bene.

Il comando di ritorno regolare aiuta inserendo un formato di servizio più appropriato. Alcuni direbbero che sarebbe una forma migliore per usarlo e scartare il tuo json sul client da questo formato. Dico, sputa semplicemente le cose esattamente come vuoi usarle!

+1

Sembra funzionare se si accede alla pagina .aspx, quindi si segue il collegamento attraverso per richiamare. Sfortunatamente se provo a navigare su "GridDataRequest.asmx/getData" ottengo una schermata gialla della morte "Il formato della richiesta non è riconosciuto per l'URL che termina inaspettatamente in"/getData "." – Mike

+1

+1 per questa comoda gemma di codice. Ho tuttavia scelto un'altra soluzione per adattarsi meglio al nostro modello. – Mike

+0

Sì, meglio usare json.parse, a patto che tu stia usando jquery comunque. Più corretto. –

2

Quando si contrassegna il servizio come ScriptService, gestisce automaticamente la serializzazione JSON. Non dovresti serializzare manualmente la risposta. Vedere this voce di overflow dello stack per ulteriori dettagli.

+0

corretto. A meno che tu non voglia utilizzare un serializzatore diverso come Newtonsoft, è meglio lasciare che asmx funzioni come previsto, e questo include la gestione della serializzazione per te. La chiave per non ottenere XML nella risposta è assicurarsi che IIS sappia che è necessario JSON. Quindi basta restituire l'oggetto C# e la serializzazione su JSON avviene automaticamente: http://stackoverflow.com/a/16335022/397817 –

1

se si req uest JSON e se si include l'attributo , ASP.NET serializzerà automaticamente la risposta a JSON. Il fatto che stiate vedendo XML suggerisce che una di queste 2 condizioni preliminari non sono state soddisfatte. I suggerimenti per la serializzazione su JSON manualmente sono errati, a meno che non si desideri utilizzare un serializzatore diverso come Newtonsoft.

Ecco un semplice esempio di lavoro di un JSON abilitato ASMX servizio Web:

<%@ WebService Language="C#" Class="WebService" %> 
using System; 
using System.Collections.Generic; 
using System.Web.Services; 

[WebService(Namespace = "http://tempuri.org/")] 
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
[System.Web.Script.Services.ScriptService] 
public class WebService : System.Web.Services.WebService { 
    [WebMethod] 
    public MyClass Example() 
    { 
     return new MyClass(); 
    } 

    public class MyClass 
    { 
     public string Message { get { return "Hi"; } } 
     public int Number { get { return 123; } } 
     public List<string> List { get { return new List<string> { "Item1", "Item2", "Item3" }; } } 
    } 
} 

Javascript per richiederla ed elaborare la risposta (vedremo semplicemente pop up un avviso di JS con il messaggio da MyClass.Message):

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
    <title>Test</title> 
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.4.js" type="text/javascript"></script> 
</head> 
<body> 
    <script type="text/javascript"> 
     $.ajax({ 
      type: "POST", 
      url: "WebService.asmx/Example", 
      contentType: "application/json; charset=utf-8", 
      dataType: "json", 
      data: "{ }", 
      error: function (XMLHttpRequest, textStatus, errorThrown) { alert(langError + " " + textStatus); }, 
      success: function (msg) { 
       alert(msg.d.Message); 
      } 
     }); 
    </script> 
</body> 
</html> 

richiesta Http:

POST http://HOST.com/WebService.asmx/Example HTTP/1.1 
Accept: application/json, text/javascript, */*; q=0.01 
Content-Type: application/json; charset=utf-8 
X-Requested-With: XMLHttpRequest 
Referer: http://HOST.com/Test.aspx 
Accept-Language: en-GB,en;q=0.5 
Accept-Encoding: gzip, deflate 
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0) 
Connection: Keep-Alive 
Content-Length: 3 
Host: HOST.com 

{ } 

risposta HTTP:

HTTP/1.1 200 OK 
Cache-Control: private, max-age=0 
Content-Type: application/json; charset=utf-8 
Server: Microsoft-IIS/8.0 
X-AspNet-Version: 4.0.30319 
X-Powered-By: ASP.NET 
Date: Tue, 08 Oct 2013 08:36:12 GMT 
Content-Length: 98 

{"d":{"__type":"WebService+MyClass","Message":"Hi","Number":123,"List":["Item1","Item2","Item3"]}} 

Risultato:

"Hi" viene visualizzato un popup JS.

Vedi anche:

https://stackoverflow.com/a/16335022/397817

https://stackoverflow.com/a/3839649/397817

1

che ho avuto più fortuna con i seguenti accorgimenti:

[WebMethod] 
public static void GetDocuments() 
{ 
    HttpContext.Current.Response.ContentType = "application/json"; 
    HttpContext.Current.Response.Write(JsonConvert.SerializeObject(repository.GetDocuments())); 
    HttpContext.Current.Response.End(); 
} 

E 'importante impostare il tipo correttamente il contenuto, e per scrivi il JSON direttamente alla risposta, quindi per terminare la risposta in modo che non vengano inviati ulteriori dati per danneggiare la tua risposta SE. Un vantaggio di questa architettura è che puoi utilizzare qualsiasi serializzatore che desideri, non sei limitato al serializzatore JSON integrato. In questo caso, ho usato Json.NET.

Mi rendo conto che questo è un abuso dell'architettura (e personalmente non mi piace avere un tipo di reso vuoto per qualcosa che dovrebbe restituire dati) ma questo è l'unico metodo veramente affidabile che ho trovato.

D'altra parte, si dovrebbe passare a WCF o Web API, per ragioni che descrive John Saunders here. In particolare, l'API Web è molto facile da utilizzare e consente la negoziazione del tipo di contenuto tra client e server.