sábado, 24 de marzo de 2012

JSON



Cuando queremos implementar un modelo de comunicación asíncrono entre una página web y el servidor tenemos al menos dos opciones: JSON y XML a través de requests con distintos verbos dependiendo del objetivo de la llamada o ejecución.    Aún cuando sea algo muy sabido creo que es necesario mecionar que generalmente los verbos se utilizan de la siguiente forma:

GET: Leer
POST: Agregar / Actualizar
DELETE: Eliminar
PUT: Agregar / Actualizar

En este ejercicio estaremos ocupando los dos verbos más comunes que son el GET y el POST.    Para preparar el entorno agregaremos los siguientes elementos:

1. Crear carpeta js.
2. Agregar jquery.js a la carpeta js.
3. Crear carpeta Handlers.
4. Agregar Products.ashx y AddProduct.ashx a la carpeta Handlers.
5. Crear carpeta DataObjects.
6. Agregar clase Product a la carpeta DataObjects.
7. Agregar archivo Products.html al proyecto (opté por un HTML para dejar en claro que todo se hará a través de requests asíncronos y no a través de posts de una WebForm)

Si vemos el explorador de soluciones (Ctrl + Alt + L) veremos un arreglo de archivos como este:


Vamos a agregarle dos propiedades públicas de lectura y escritura a nuestra clase Product:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Ahora vamos a crear el código necesario para que Products.ashx devuelva la lista de productos en JSON.    Para empezar vamos a agregar dos espacios de nombres, el que contiene a JavaScriptSerializer y a nuestra clase Product:

using System.Web.Script.Serialization;
using SendReceiveJSON.DataObjects;

Los handlers reciben las peticiones a través del procedimiento ProcessRequest.   Notemos que por defecto ya viene un código que dice el tipo MIME que se va a devolver y el contenido de la respuesta.    El tipo MIME de JSON es "application/json" por lo que deberemos fijar este valor en la propiedad ContentType de la propiedad Response.

context.Response.ContentType = "application/json";

Ahora vamos a llenar una lista de objetos Product y la vamos a convertir en JSON utilizando el objeto JavaScriptSerializer:

List<Product> result = new List<Product>();
for (int i = 0; i < 10; i++)
{
    result.Add(new Product() { Id = i + 1, Name = "Product " + (i + 1).ToString() });
}
JavaScriptSerializer js = new JavaScriptSerializer();
context.Response.Output.Write(js.Serialize(result));

Si ejecutamos directamente el handler Products.ashx desde el navegador deberemos ver un resultado como este:


Para terminar este primer ejercicio vamos a crear el código necesario en nuestra página Products.htm para que llame al handler y muestre el listado de productos.    Para esto necesitamos un botón y un contenedor donde insertaremos una tabla con los productos.

<input type="button" value="Get products" onclick="return getProducts()" />
<hr />
<div id="divProducts"></div>

En nuestra función getProducts haremos la llamada a Products.ashx (recuerden agregar el script jquery en el head):

<script language="javascript" type="text/javascript">
    function getProducts() {
        $.ajax({
            'type': 'GET',
            'url': '/Handlers/Products.ashx',
            'success': getProducts_success,
            'error': getProducts_error
        });
        return false;
    }
    function getProducts_success(d) {
    }
    function getProducts_error(d) {
    }
</script>

Con la función $.ajax (de jquery) podemos realizar peticiones asíncronas (con el verbo type) al recurso web identificado determinado a través de la propiedad url.    Cuando la ejecución es exitosa se mandará a llamar a la función getProducts_success y cuando haya un error se ejecutará la función getProducts_error.

Vamos a modificar las funciones getProducts_success y getProducts_error para darle significado al ejercicio:

function getProducts_success(d) {
    var products = '<table cellspacing="0" cellpadding="5">';
    products += '<tr><th>Id</th><th>Name</th></tr>';
    for (var i = 0; i < d.length; i++) {
        products += '<tr>';
        products += '<td>' + d[i].Id + '</td>';
        products += '<td>' + d[i].Name + '</td>';
        products += '</tr>';
    }
    products += '</table>';
    products = $(products);
    $('#divProducts').append(products);
}
function getProducts_error(d) {
    alert('There was an error during execution process');
}

Notemos que estamos ocupando las propiedades públicas de nuestro objeto Product (Id y Name), esto se debe a que jquery realiza la decodificación de JSON y genera el arreglo de objetos necesarios para mostrar la información.    Es por eso que se llama JSON (JavaScript Object Notation)

En la siguiente entrada veremos cómo enviar un objeto Product al servidor a través de un POST en notación JSON.

4 comentarios:

  1. Buen día, en la función "getProducts_success" cual es el objetivo de esta línea "products = $(products);"?

    ResponderBorrar
  2. Hola, lo que hago es convertir el código html que viene cargando la variable "products" hacia un objeto jquery.

    Una vez convertido podemos utilizar las funciones propias de jquery que apliquen al objeto, por ejemplo:

    products.css('font-family', 'Arial')

    ResponderBorrar
  3. Ok, gracias por aclarar mi duda, he probado lo que comentas y veo que al hacer esa conversión tienes acceso a otras propiedades tal como lo colocas en tu ejemplo.

    ResponderBorrar
    Respuestas
    1. De nada jovenazo, qué bueno que te ha resultado útil.

      Borrar