2010-01-13 25 views
11

No estoy seguro de dónde me estoy equivocando de lo que me estoy perdiendo.ASP.NET WebService está envolviendo mi respuesta JSON con etiquetas XML

Estoy construyendo una aplicación web ASP.NET 2.0 (en el framework .Net 3.5) y estoy incluyendo un servicio web. Tenga en cuenta que esto es no un proyecto MVC. Deseo exponer un método que devolverá una cadena JSON; formateado para alimentar el plugin jqGrid jQuery.

Este es el método de ensayo preliminar he aplicado a mi servicio: gracias 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(); 
} 

Cuando se invoca este está volviendo (formateado para mayor claridad):

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

Cómo sería Logré la respuesta anterior sin las envolturas de xml?

Respuesta

8

tres cosas que no se puede estar haciendo:

  • Marcado del método estático
  • Realización de una mano de POST
  • un vacío "{}" para los datos en jQuery.

Puede haber una manera de llamar al método con un GET, solo he usado POST alguna vez. Yo era capaz de obtener su ejemplo de trabajo con esto:

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

El código subyacente (que no es necesario para crear un servicio web, se puede poner esto en su 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(); 
} 

el resultado:

{"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 explicación más detallada es here

+0

¿Cómo obtuvo su resultado? Cuando lo implemento como lo tengo, parece que solo recupero "Objeto Object". Esto podría ser una ingenuidad para JSON, pero parece que no puedo hacer que funcione. – Mike

+0

Utilicé Firebug en Firefox para ver la respuesta desde el panel de Red: haga clic en la pestaña de respuesta para esa solicitud. –

+0

¿Sabes por qué los datos se envuelven en la variable "d"? – Mike

9

En su código, no "devuelva" el json. En lugar de utilizar:

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

, entonces estará bien.

El comando de devolución normal ayuda a poniendo un formato de servicio más adecuado. Algunos dirían que sería mejor forma de usar esto, y desenvolver su JSON en el cliente desde este formato. ¡Yo digo, simplemente escupir exactamente cómo quieres usarlo!

+1

Esto parece funcionar si navega a la página .aspx y luego sigue el enlace para invocar. Desafortunadamente, si trato de navegar a "GridDataRequest.asmx/getData" obtengo una pantalla amarilla de muerte. "El formato de solicitud no se reconoce para URL que inesperadamente termina en '/ getData'." – Mike

+1

+1 para esta útil joya de código. Sin embargo, he elegido otra solución para adaptarla mejor a nuestro modelo. – Mike

+0

Sí, mejor utilizar json.parse, siempre y cuando esté usando jquery de todos modos. Más apropiado. –

2

Cuando marca el servicio como ScriptService, maneja automáticamente la serialización JSON. No debe serializar manualmente la respuesta. Consulte this entrada de desbordamiento de pila para obtener más información.

+0

Correcto. A menos que quiera usar un serializador diferente como Newtonsoft, es mucho mejor dejar que asmx funcione según lo diseñado, y eso incluye administrar la serialización por usted. La clave para no obtener XML en la respuesta es garantizar que IIS sepa que se requiere JSON. A continuación, simplemente devuelva el objeto C# y la serialización a JSON se produce automáticamente: http://stackoverflow.com/a/16335022/397817 –

1

Si usted req uest JSON, y si incluye el atributo [ScriptService], ASP.NET serializará automáticamente la respuesta a JSON. Que estaba viendo XML sugiere que una de estas 2 condiciones previas no se cumplió. Las sugerencias para serializar manualmente a JSON son incorrectas, a menos que desee utilizar un serializador diferente como Newtonsoft.

Aquí es un simple ejemplo de trabajo de un JSON permitido ASMX servicio 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 para solicitarlo y procesar la respuesta (vamos a estallar simplemente una alerta de JS con el mensaje de 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> 

solicitud 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 

{ } 

respuesta 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"]}} 

Resultado:

"Hola" se visualiza en una ventana emergente JS.

Ver también:

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

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

1

he tenido mejor suerte con el siguiente procedimiento:

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

Es importante establecer el tipo de contenido correctamente, y para escriba el JSON directamente en la respuesta, luego termine la respuesta para que no se envíen más datos para corromper su respuesta se. Una ventaja de esta arquitectura es que puede usar el serializador que desee, no está limitado al serializador JSON incorporado. En este caso, utilicé Json.NET.

Me doy cuenta de que esto está abusando de la arquitectura (y personalmente no me gusta tener un tipo de devolución nulo para algo que se supone que devuelve datos) pero este es el único método realmente confiable que he encontrado.

Por otro lado, debe cambiar a WCF o Web API, por razones que John Saunders describe here. La API web, en particular, es muy fácil de usar y permite la negociación del tipo de contenido entre el cliente y el servidor.

Cuestiones relacionadas