Serializar – Deserializar JSON en ASP.NET

Cuando trabajamos con AJAX no tardaremos en darnos cuenta lo complicado que se nos puede hacer enviar y recuperar datos entre el cliente y el servidor.

El viaje entre el servidor y el cliente no es tanto el problema, porque un método web utiliza la serialización JSon por defecto y si queremos utilizar XML como tipo de datos devuelto tendremos que especificar el formato con el atributo [ScriptMethod(ResponseFormat = ResponseFormat.Xml)].

Hoy voy a hacer una pequeña página web que recupere la información de la base de datos y la muestre en una tabla directamente desde el cliente con JQuery. Los datos los recuperaré de la famosa base de datos NorthWind que la podéis descargar desde http://technet.microsoft.com/es-es/library/ms143221.aspx

Para garantizar que los datos se serializan correctamente vamos a crear una clase llamada ProductoData que será el objeto que pasaremos entre el servidor y el cliente, para garantizar su correcta serialización utilizaremos los atributos de System.Runtime.Serialization para definir el contrato y sus Datamember. Esto nos servirá para los métodos web y para WCF con AJAX.

using System.Runtime.Serialization;

[DataContract]
public class ProductoData
{
    [DataMember]
    public int ProductID { get; set; }
    [DataMember]
    public string ProductName { get; set; }
    [DataMember]
    public decimal UnitPrice { get; set; }
    [DataMember]
    public int UnitsInStock { get; set; }

    public ProductoData(){}
    public ProductoData( int id, string name, decimal price, int stock)
    {
        this.ProductID = id;
        this.ProductName = name;
        this.UnitPrice = price;
        this.UnitsInStock = stock;
    }
}

Luego para tratar los datos crearé una clase Productos que nos hará el servicio de capa lógica de Negocios para cargar y añadir campos en la base de datos. Como es un simple ejemplo no iremos más allá de recuperar los datos y añadir uno nuevo para mostrar el envío y recuperación de datos serializados, no entraremos en conexiones, capas y validaciones de datos.

public List<ProductoData> GetProductos(string idCategoria )
{
   List<ProductoData> productos = new List<ProductoData>();
   SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString);
   SqlCommand command = new SqlCommand(@"SELECT ProductID, ProductName, "
   UnitPrice, UnitsInStock FROM  Products where CategoryID = @CategoryID", con);"
   command.Parameters.Add(new SqlParameter("@CategoryID", idCategoria));
   SqlDataReader reader = null;
   try
   {
       con.Open();
       reader = command.ExecuteReader();
       while (reader.Read())
       {
          productos.Add(new ProductoData(int.Parse(reader["ProductID"].ToString()),
              reader["ProductName"].ToString(),
              decimal.Parse(reader["UnitPrice"].ToString()),
              int.Parse(reader["UnitsInStock"].ToString())));
       }
   }
   catch (Exception ex)
   {
       string error = ex.Message;
   }
   finally
   {
     con.Close();
     reader.Close();
   }

   return productos;
}

Para recuperar los productos de la base de datos y mostrarla en el cliente sin hacer una recarga completa de la página utilizaremos un PageMethod, eso quiere decir que será un método público y estático que se accederá desde el cliente como si fuera una método de un webService. A este método le tenemos que decir que es accesible desde el cliente con el atributo [WebMethod].

[WebMethod]
 public static List<ProductoData> GetProductos(string idCategoria)
 {
     List<ProductoData> productos;
     Productos srvProductos = new Productos();
     productos = srvProductos.GetProductos(idCategoria);
     return productos;
 }

Este método simplemente carga una lista de productos filtrado por su categoría que nos viene en forma de parámetro y retorna una colección de objetos productos para que podamos los datos en cliente en formato JSon.

Primero de todo necesitamos tener un ScriptManager para poder dotar de toda la funcionalidad AJAX a nuestra página ASP.NET y habilitaremos los PageMethods en el scriptManager para poder acceder a los métodos de servidor. Registraremos un fichero JS en el ScriptManager que será el encargado de llamar a los Metodos de página y cargar los datos en la tabla.

Luego en la página contaremos con un dropDownList con las categorías de los productos, una tabla donde mostraremos los productos y dos botones para la edición de los datos. En el evento onchange de la lista utilizaremos una función javascript para cargar los datos «onchange=Cargarproductos(this)«.

function  CargarProductos(list)
{
   PageMethods.GetProductos(list.options[list.selectedIndex].value,
    OnLlamadaProductos);
}

Esta función es la que llama al método de página que tenemos preparado en el servidor para cargar los datos. El primer parámetro es el identificador de la familia para filtrar los datos y el segundo es la función que utilizaremos pra tratar los datos devueltos.

function OnLlamadaProductos(resultado)
{
    var etiqueta = $get("lblMensaje");  

    $('#tableproductos tr').next().remove();
    for( var x = 0; x < resultado.length; x++)
    {
        $('#tableproductos tr:last').after('<tr><td>'+
        resultado[x].ProductID+'</td>'+
        '<td>'+resultado[x].ProductName+'</td>'+
        '<td>'+resultado[x].UnitPrice +'</td>' +
        '<td>'+resultado[x].UnitsInStock+'</td></tr>');

    }

    $('#tableproductos tr:odd').css('background-color','#CCCCCC');
}

Esta función utiliza JQuery para recorrer el resultado y añadir las rows a la tabla y dar el formato a las alternateRows.

Como podréis comprobar en esta imagen los datos vienen perfectamente serializados en Json para poder trabajar desde nuestro código JavaScript como una colección de objetos perfectamente definidos.

Hasta ahora no hemos tenido que hacer nada especial para enviar los datos serializados desde el servidor hasta el cliente. Pero cuando queremos hacer le paso contrario y enviar los datos serializados desde el cliente al servidor se nos complica un poco más la cosa.

Para mostrar un ejemplo sencillo de este proceso, vamos a dar la opción de añadir nuevos registros a nuestra base de datos desde el cliente, para eso utilizaremos otra función javascript llamada AddProducto.

function AddProducto()
{
    var nom = $('#txtNom')[0].value;
    var precio = $('#txtPrecio')[0].value;
    var stock = $('#txtStock')[0].value;
    var producto = "{"ProductName":""+nom+"
        "","UnitPrice":"+precio+"
        ","UnitsInStock":"+stock+"}";

    PageMethods.AddProducto( producto,
        OnAddProductoOK, OnAddProductoKO);
}

Para no entrar en profundidad en como poder trabajar con JSon desde JavaScript y el tema de la inyección de script vamos a enviar al servidor un formato correcto JSon pero trabajaremos con los datos como texto plano. Esta función simplemente recupera los datos de los textbox de edición los formatea y los envía al servidor mediante otro page Method donde le pasamos los datos y la función que seguirá si todo ha ido correcto y la función si ocurre un error.

El código realmente interesante está en el método del servidor que recibiremos los datos del cliente.

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static int AddProducto(string producto)
{
   System.IO.MemoryStream stream = new System.IO.MemoryStream(
    System.Text.ASCIIEncoding.UTF8.GetBytes(producto));
   DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ProductoData));
   stream.Position = 0;
   ProductoData dsProducto = (ProductoData)ser.ReadObject(stream);

   Productos srvProductos = new Productos();
   int id = srvProductos.AddProducto(dsProducto);
   return id;
}

Para recuperar los datos del cliente en formato JSon y convertirlo en un tipo personalizado utilizaremos la clase DataContractJsonSerializer, esta clase será la encargada de coger el texto que hemos enviado desde el cliente y convertirlo en nuestro Tipo ProductoData.

DataContractJsonSerializer nos servirá tanto para serializar como para deserializar datos Json a objetos.

using System.Runtime.Serialization.Json

Como podréis comprobar con esta clase podemos recuperar fácilmente los datos del cliente como json y convertirlos en objetos para trabajar con estos datos más fácilmente desde nuestro código.

Bueno, como ejemplo me parece que ya está todo explicado .

 

 

ASP.NET CODEBARS

En el foro de MSDN han consultado como poder  generar códigos de barra en una aplicación ASP.NET, yo hace bastante tiempo hice un ejemplo para una aplicación windows utilizando unas fuentes True Type para este menester y ahora haré lo mismo pero para una aplicación web.

El artículo original para Windows lo podéis encontrar en la web del guille en http://www.elguille.info/colabora/NET2006/Marckys_BarCode.htm .

Lo primero que voy a hacer es un proyecto web con una simple página donde podré introducir los datos para generar el código de barras y una combo para seleccionar las fuentes que me darán los diferentes formatos de código de barras.

La idea de esta utilidad es mostrar los datos en un formato de código de barras y la opción que he considerado más oportuna es generar una imagen con este texto y mostrarlo en la web como un simple control de servidor image de toda la vida.

Para poder realizar esto si tenernos que complicar muchísimo la vida. Lo mejor es crear un http handler que nos genere esta imagen y la muestre en el control.

Que es un HttpHandler ??

Pues un manejador de las solicitudes http que implementa la interface IHttpHandler y nos puede servir tanto para interceptar las llamadas de un fichero con una extensión en particular como para llamarlo directamente, como va a ser nuestro caso. Sigue leyendo