2010-07-07 32 views
7

Me doy cuenta de que ya hay toneladas de preguntas similares aquí pero no puedo entender esto.Devolver JSON desde ASMX, y manejarlo correctamente en Javascript

Tengo un servicio web (C#, .net 3.5). El Código esencial que necesita saber de es el siguiente:

[WebService(Namespace = "http://tempuri.org/")] 
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
[System.Web.Script.Services.ScriptService] 
public class WSMember : System.Web.Services.WebService { 

    public WSMember() { 
    } 


    [WebMethod] 
    [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)] 
    public string GetMember(string IdMember) 
    { 
     //Ignore the parameter for now... I will be looking up a database with it... 
     //For now just return a minimal object: 
     Member m = new Member(); 
     m.Surname = "Smith"; 
     m.FirstName = "John"; 
     return new JavaScriptSerializer().Serialize(m); 
    } 

Además, en web.config, hice la siguiente adición (que acabo de ver en algún otro post ... es esto normal/seguro?)

<webServices> 
     <protocols> 
     <add name="HttpGet" /> 
     <add name="HttpPost" /> 
     </protocols> 
    </webServices> 

Luego, en Default.aspx, yo los dos referencias clave ...

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<script type="text/javascript" src="jquery.json-2.2.min.js" ></script> 

jquery.json-2.2.min.js fue descargado desde Google Code

y aquí está el Javascript:

<script type="text/javascript"> 
     $(document).ready(function() { 
      $("#button1").click(function(event) { 
       var myData = { IdMember: "2" }; 
       var encoded = $.toJSON(myData); 

       alert(encoded); 

       $.ajax({ 
        type: "POST", 
        url: "WSMember.asmx/GetMember", 
        data: encoded, 
        contentType: "application/json; charset=utf-8", 
        dataType: "json", 
        success: function(msg) { 
         alert("worked" + msg.d); 
         //$("#sidebar").append(msg); 
        }, 
        error: function(msg) { 
         alert(msg.d); 
         //$("#sidebar").append(msg); 
        } 
       }); 
      }); 
     }); 

    </script> 

Cuando ejecuto, el JSON codificado aparece en el cuadro de mensaje como se esperaba ... es decir, con comillas dobles:

{ "IdMember": "2" }

Sin embargo, siempre falla. Incluso para el Hello World más básico sin datos que se pasan, falla. Me sigo "indefinido" por los datos del mensaje.

Si sólo tiene que utilizar alerta (msg), se muestra [objeto XMLHttpRequest]

¿Alguien sabe dónde se está perdiendo mis datos ??

Y otra pregunta ... ¿hay algo fundamentalmente malo con lo que estoy haciendo?

Muchas gracias.

EDIT:

gracias por la respuesta chicos. He intentado lo siguiente así que ...

UseHttpGet = true ahora se ha cambiado a falso. (De nuevo, lo vi en alguna parte, así que lo intenté ... pero sabía que no podía ser el correcto: - /)

Digamos que el servicio web ahora devuelve una cadena. Construyo la cadena de la siguiente manera (parece un poco loco ... serialización lo hizo exactamente lo mismo ...)

StringBuilder sb = new StringBuilder(); 
    sb.Append("{"); 
    sb.Append("\"Surname\":"); 
    sb.Append("\""); 
    sb.Append(m.Surname); 
    sb.Append("\""); 

    sb.Append(",\"FirstName\":"); 
    sb.Append("\""); 
    sb.Append(m.FirstName); 
    sb.Append("\""); 

    sb.Append("}"); 

    return sb.ToString(); 

Este código devuelve algo como:

{"Surname":"Smith","FirstName":"John"} 

sigo teniendo el exacto mismo error ...

también he intentado algo así como la devolución del objeto "miembro", por lo que el código se convierte en:

[WebMethod] 
[ScriptMethod(ResponseFormat = ResponseFormat.Json)] 
public Member GetMember(string IdMember) 
{ 
    Member m = new Member(); 
    m.Surname = "Smith"; 
    m.FirstName = "John"; 

    return m; 
} 

Esto también arroja el mismo error.

Lamento ser un dolor ... He leído ambos enlaces, y otros. Simplemente no puedo ver por qué esto es diferente.

¿Hay alguna configuración de configuración adicional que deba tener en cuenta posiblemente?

Muchas gracias por las respuestas.

ACTUALIZACIÓN: El problema está solucionado. Los errores clave en el código anterior son:

[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)] 

debería ser

[ScriptMethod(ResponseFormat = ResponseFormat.Json)] 

Además, en el formulario, cuando se utiliza un botón para llamar al Javascript, yo estaba sentado de forma incorrecta el tipo de entrada ...

<input id="button1" type="submit" value="Just a test" /> 

cuando debe decir:

<input id="button1" type="button" value="Just a test" /> 

Muchas gracias a todos los que ayudaron.

Respuesta

3

Me parece que su principal problema es que intenta utilizar manualmente JavaScriptSerializer().Serialize en lugar de devolver un objeto. La respuesta del servicio web será doble JSON codificada.

¡Tienes razón! Hay muchas preguntas cercanas. Mire aquí Can I return JSON from an .asmx Web Service if the ContentType is not JSON? y Can't get jQuery Ajax to parse JSON webservice result y encontrará (espero) la respuesta.

ACTUALIZADO: Lo sentimos, pero tiene un pequeño error en alguna parte de lo que no publicó. Para cerrar el problema, creé un pequeño proyecto con una versión anterior de Visual Studio (VS2008) que prácticamente tiene exactamente su código y que funciona. Lo coloqué en http://www.ok-soft-gmbh.com/jQuery/WSMember.zip. Puede descargarlo, compilar y verificar que funcione. Entonces puedes comparar tu código con mi y encontrar tu error.

Saludos

+0

Oleg, En un tema ligeramente diferente, está cambiando estos servicios a WCF REST muy recomendable ?? ¡Pareces estar a favor aquí ...! http://stackoverflow.com/questions/3189653/cant-get-jquery-ajax-to-parse-json-webservice-result/3190823#3190823 – collumbo

+1

La gente me rechazó por decirlo, pero no recomiendo usar WCF para simples devoluciones de llamada AJAX. WCF es mucho más poderoso, pero realmente no aporta mucho si no usas ese poder. De hecho, el JavaScriptSerializer de ASMX es en realidad más flexible que el DataContractJsonSerializer de WCF en lo que respecta a las fechas y las enumeraciones. La complejidad añadida de WCF es difícil de justificar en este escenario (sin embargo, están trabajando en ello). –

+0

Oleg, su ejemplo me llamó la atención sobre una sola línea de código que lo arregló. Muchas gracias. El código estaba realmente bien. para el botón que tiene type = "button". Tenía type = "submit". Acababa de tomar una forma antigua y la he editado ... sin notar el tipo del botón. Además, actualicé mi referencia de jquery a 1.4.2 (todavía me refería a 1.3.2) solo por el simple hecho de eliminar. También uso su sugerencia "stringify", aunque $ .toJSON (myData) también funciona. Dave - muchas gracias por sus comentarios también. Muy útil. – collumbo

1

Si usted está haciendo un post a sus datos, ¿por qué definiendo UseHttpGet = true? ¿No debería ser falso para que coincida con el tipo de respuesta de su solicitud? Además, poner un punto de interrupción en la llamada ws para ver exactamente lo que devuelve el serializador ayudaría también ... No creo que deba devolver un objeto JSON si el valor devuelto es una cadena.

HTH.

+0

¡Correcto! Es un error más en el programa. – Oleg

1

Sí, definitivamente no serialice manualmente el objeto. Si devuelve un tipo Member, el marco gestionará la serialización JSON por usted.

Cuando está viendo la alerta [objeto XMLHttpRequest], parece que entra en el controlador de errores en su llamada $ .ajax(), donde la respuesta pasa en su objeto XHR como primer parámetro. Probablemente estés obteniendo un error de 500 en el servidor.

Aquí está an example of decoding the ASP.NET AJAX error response in jQuery. La mayoría simplemente, cambiar su controlador de errores a esto:

error: function(xhr, status, error) { 
    var err = eval("(" + xhr.responseText + ")"); 

    alert(err.Message); 
} 

que le dará una idea de lo que es el error específico.

-1

tengo mal Inglés, pero esto es una solución

----- ------ WSMember.asmx

[WebService(Namespace = "http://tempuri.org/")] 
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
[System.Web.Script.Services.ScriptService] 
public class WSMember : System.Web.Services.WebService { 

    public WSMember() { 
    } 

    [WebMethod] 
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)] 
    public string GetMember(int IdMember) 
    { 
     Member m = new Member();//Get Member from DB, exam Linq to Sql 
     m.Surname = "Smith"; 
     m.FirstName = "John"; 
     return string.Format("{{ \"Surname\":\"{0}\",\"FirstName\":\"{1}\" }}",m.Surname,m.FirstName); 
    } 
} 

---- ---- Default.aspx

<a href="#" id="button1">Just a test</a> 
<script type="text/javascript"> 
    $("#button1").click(function (event) { 
     event.preventDefault(); 
     $.ajax({ 
      type: "POST", 
      url: "WSMember.asmx/GetMember", 
      data: "{IdMember: 2 }", 
      contentType: "application/json; charset=utf-8", 
      dataType: "json", 
      success: function (msg) { 
       if (msg.hasOwnProperty('d')) { 
        msg = msg.d; 
       } 
       var json = JSON.parse(msg); 
       console.log(json.Surname); 
       console.log(json.FirstName); 
      }, 
      error: function (xhr, status, error) { 
       //console.log(xhr); 
       //console.log(status); 
       //console.log(error); 
      } 
     }); 
    }); 
</script> 
0

Si va a devolver cualquier objeto complejo (objetos relacionales con las claves externas), tiene 2 opciones:

  1. con un objeto DTO
  2. Escribe tu propia convertidor de serialización específica
Cuestiones relacionadas