Deserializar JSon a tipo anónimo .Net

En ciertas ocasiones podemos necesitar deserializar un objeto pasado desde un cliente en formato JSon a un tipo .net anónimo. Por ejemplo si utilizas MongoDB con el driver NORM y pretendes filtrar u ordenar de una manera dinámica, es difícil pasar estos objetos a la query para poder generar un filtro dinámico.

Para hacernos una idea esta sería una consulta paginada y con un filtro sencillo con NORM:

1 //NoRM anonymous objects:
2 return GetRepository().GetCollection("Personas")
3 .Find(
4 new { Nombre = Q.IsNotNull() }, //Where
5 new { Fecha = OrderBy.Descending }, //OrderBy
6 10, // Nº elementos de la secuencia "Skip"
7 0 // Primer elemento de la secuencia "Take"
8 );

 

Esta consulta nos devolvería las 10 primeras personas con Nombre que no sea null.

Tanto al utilizar los tipos anónimos como en las consultas LinQ se tiene que especificar la propiedad por la que se quiere filtrar u ordenar y eso nos limita a la hora de intentar hacer estas consultas de forma dinámica.

Parara hacer una prueba crearemos un tipo específico para utilizar en las consultas desde javaScript.

Lo ideal sería:

1 public class QueryRequest
2 {
3 public int Pagina { get; set; }
4 public int Registros { get; set; }
5 public object Orden { get; set; }
6 public object Filtro { get; set; }
7 }

 

Con este tipo nos pasarían como parámetros lel número de página, la cantidad de registros y además un object para filtrar y otro object para ordenar.

Pero esto no funciona porque NORM no lo reconoce como tipo anónimo y si lo intentamos pasar como string tampoco funciona.

Ahora solo nos queda intentar deserializar directamente nosotros el objeto JSON en un tipo anónimo y para eso utilizaremos el tipo dynamic que tenemos disponible desde c# 4.

Para eso solo tenemos que deserializar un texto con datos en formato JSon utilizandoJavaScriptSerializerque te permite utilizar un tipo T.

1 var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
2 var ObjetoAnonimo = jss.Deserialize(strJson);

 

Con estas dos líneas lo tenemos solucionado y el nuevo tipo podría quedar de esta manera para facilitar la entrada de los datos como string y la salida como objeto dinámico.

01 public class QueryRequest
02 {
03 public int Pagina { get; set; }
04 public int Registros { get; set; }
05
06 // input string - output dynamic
07 private string orden;
08 public dynamic Orden { get { return DeserializarJSon(orden); } set { orden = value; } }
09
10 // input string - output dynamic
11 private string filtro;
12 public dynamic Filtro { get { return DeserializarJSon(filtro); } set { filtro = value; } }
13
14 private dynamic DeserializarJSon(string strJson)
15 {
16 var jss = new JavaScriptSerializer();
17 dynamic resultado;
18 try
19 {
20 resultado = jss.Deserialize(strJson);
21 }
22 catch (Exception)
23 {
24 resultado = new { };
25 }
26 return resultado;
27 }
28
29 }

 

Ahora nuestro objeto es capaz de devolver un tipo anónimo al consultar la propiedad Filtro y Orden.

01 public IEnumerable FindFiltradoDinamico( QueryRequest datos )
02 {
03 //NoRM anonymous objects:
04 return GetRepository().GetCollection("Personas")
05 .Find(
06 datos.Filtro as object,
07 datos.Orden as object,
08 datos.Registros,
09 datos.Pagina * datos.Registros
10 );
11
12 }

 

Ahora si tenemos las consultas preparadas para aceptar parámetros dinámicos.

01 public ActionResult Index()
02 {
03 var datos = new QueryRequest()
04 {
05 Pagina = 0,
06 Registros = 10,
07 Filtro = " { Edad : { '$gt': 15 } } ", //mayor de 15 años
08 Orden = "{ Nombre : -1}" // 1 Ascendente - -1 Descendente
09 };
10
11 var f2 = repositoryPersona.FindFiltradoDinamico(datos);
12
13 return View();
14 }

 

 

Cross-Posting: http://mrubino.net

 

 

 

¿ Servicios REST con diferente serialización Json ?

Resulta que estos días he estado jugando un poco con WCF y serialización JSON para participar en el nuevo concurso de MSDN http://www.lahoradelospunos.com

En resumen lo que hay que hacer es un Servicio REST accesible desde peticiones HTTP GET que devuelva la secuencia de movimientos conforme el siguiente esquema.

{ “Alias”: “My_alias”, “Moves”: “A1, A2, B1, A1, ME, A1, A2, B1, B2, B1”, “Enemy”: “Enemy_name” }

Pero el problema viene cuando genero la página para acceder manualmente al servicio desde una página web propia y pretendo hacerlo compatible con las llamadas de cliente MS AJAX.

WCF accesible desde ASP.NET AJAX:

Para hacer accesible el servicio y poderlo consumir desde ASP.NET AJAX solo hay que especificar el parámetro Factory de la directiva @ServiceHost en el archivo .svc como WebScriptServiceHostFactory.

image

Desde ese momento la salida de mi objeto JSon tiene el siguiente formato:

{“d“:{“__type“:”Ataque:#KillBits”,”Alias”:”Marckys “,”Enemy”:”Cliente”,”Moves”:”A2,A2,B1,A2,A2,A2,ME,A1,B1,A2″}}

UPSSS!!! no tiene el mismo formato que me piden en el concurso.

Para hacer que el formato cuadre exactamente con las especificaciones del concurso solo tenemos que hacer una cosa. NO hacer compatible el servicio con MS AJAX, solamente con ASP.NET.

WCF accesible desde ASP.NET:

Hay que utilizar WebServiceHostFactory como Factory y no WebScriptServiceHostFactory

image

Formato correcto !!!

{“Alias”:”Marckys “,”Enemy”:”Cliente descontento “,”Moves”:”A1,A1,ME,A1,A1,A1,A2,A2,A2,A2″}

¿Porqué esta diferencia?

Por cuestiones de seguridad desde ASP.NET 3.5 la serialización JSON que tiene que ser consumida desde el cliente “MS AJAX”, viene envuelta en el atributo d. De esta manera se soluciona una conocida vulnerabilidad “javascript hijacking” que permite la ejecución directa de Script en el constructor de arrays de objetos.

Evitando un ataque de este estilo:

["Marckys", alert("Ataque XSS")]

Cuidado al consumir los datos:

Con estas modificaciones en la serialización, tenéis que tener cuidado al obtener el objeto porque no es lo mismo obtener la información con una respuesta u otra.

No es lo mismo esperar el objeto d:

var alias = resultado.d.Alias;

Que utilizarlo directamente:

var alias = resultado.Alias;

Esto puede dar errores al actualizar aplicaciones a las nuevas versiones.

Espero que os haya podido ayudar esta información.

GridView Custom Edit

Este año ha sido mucho más productivo de lo que me esperaba y el que comienza parece que me va a deparar nuevos retos personales que espero sean lo más positivos posible.

Para empezar con buen pie y no cejar en mis artículos técnicos, hoy haré un nuevo ejemplo práctico para personalizar un control GridView, permitir editar sus elementos con JavaScript y enviar al servidor de manera asíncrona solo las modificaciones realizadas.

Realmente cada vez existen más controles que nos permiten mejorar la experiencia de usuario y potencian usabilidad de los usuarios. Pero con un poco de tiempo es posible dar este toque a los controles con los que trabajamos cotidianamente.

Para comenzar esta práctica crearemos un nuevo proyecto web y cargaremos una grid con la base de datos NorthWind que no puede faltar en cualquier ejemplo que utilice una base de datos SQL.

gridedit

Para poder editar la grid lo que tenemos que hacer primero es marcar las celdas que se podrán editar con una propiedad llamada “editable”,  guardar el nombre del registro para tenerlo a mano a la hora de guardar las modificaciones y agregar el evento onmousedown para que llame a la función javaScript de edición tanto en IE como en Firefox.

  1: protected void GridView1_RowDataBound(object sender, 
  2:    GridViewRowEventArgs e)
  3: {
  4:    if (e.Row.RowType == DataControlRowType.DataRow)
  5:    {
  6:       foreach (TableCell cell in e.Row.Cells)
  7:       {
  8:          cell.Attributes.Add("editable", "true");
  9:          cell.Attributes.Add("columnName", 
 10:            ((System.Web.UI.WebControls.DataControlFieldCell)
 11:               (cell)).ContainingField.HeaderText);
 12:          cell.Attributes.Add("onmousedown", "EditarPrecio(this);");
 13:       }
 14:    }
 15:  }

Una vez preparado el código de servidor que pintará la grid, ya podemos empezar con la funcionalidad en el cliente y para eso utilizaremos diferentes librerías ( JQuery, JSON) y un fichero .js donde se encontrara nuestro código script.

El script de cliente:

*. EditarPrecio( celda ):

Lo primero que haremos es crear un control input para editar el contenido de la celda y como comenté en “Jquery – la potencia sin control no sirve de nada !!” no abusaremos de las funciones Jquery para no perjudicar al rendimiento de nuestro código.

grideditCel

  1: function EditarPrecio(td) {
  2:     
  3:     var tdControl = $(td)[0];
  4:     OcultarTxtEditTodos();
  5: 
  6:     if (tdControl != null && tdControl.innerText != "" 
  7:        && $(td).attr("editable") != null 
  8:        && $(td).attr("editable") == "true") {
  9:         var oldValue = tdControl.innerHTML;
 10:         tdControl.innerHTML = '<input id="txtEditPrecios" '
 11:            + 'onblur="OcultarTxtEdit(this, true);" '
 12:            + 'onkeypress="FiltradoKey(event, this);" '
 13:            + 'class="txtEditPrecios" type="text" value="' 
 14:            + oldValue + '" />';
 15:         $(".txtEditPrecios").focus().select();     
 16:     }
 17: }

4: Ocultamos los posibles inputs que se hayan quedado activados.

10: agregamos el control input a la celda.

11: Al perder el foco evento “onblur” ocultamos el input.

12: Al presionar un tecla evento “onkeypress” detectamos si se presiona la tecla escape para finalizar la edición

15: Otorgamos el foco al input y seleccionamos el contenido para facilitar la edición.

*. OcultarTxtEdit( input, si queremos tabular “bool” ):

 

  1: function OcultarTxtEdit(val, tabular) {
  2:     if (val != null) {
  3:         var txt = $(val);
  4:         var td = txt[0].parentNode;
  5:         if (txt[0].defaultValue != txt[0].value) {
  6:             td.setAttribute("EditVal", txt[0].value);
  7:             td.className = "txtEdit";
  8:         }
  9:         var tdNext = $(td).next();
 10:         td.innerHTML = txt[0].value;
 11: 
 12:         if (tabular)
 13:             if($(tdNext).length)
 14:                EditarPrecio(tdNext);
 15:             else
 16:                 if($(td).parent('tr').next().children().length)
 17:                 EditarPrecio($(td).parent('tr').next().children()[0])
 18:     }
 19: }

5: Comprobamos si el contenido de la celda ha sido modificado.

6: mostramos el nuevo valor.

7: modificamos el estilo para destacar las celdas modificadas.

12: si queremos tabular editamos la siguiente celda

16: si es la última celda de la fila saltaremos a la siguiente fila

grideditCel2

*. OcultarTxtEditTodos():

Oculta todos los inputs de la grid.

  1: function OcultarTxtEditTodos() {
  2:     var txts = $("#txtEditPrecios");
  3:     for (var i = 0; i < txts.length; i++) {
  4:         OcultarTxtEdit($(txts[i]), false); 
  5:     }
  6: }

*. OcultarTxtEditTodos():

Si se presiona la tecla escape salimos de la edición de la celda.

  1: function FiltradoKey(e, txt) {
  2:     var code = (e.keyCode ? e.keyCode : e.which);
  3:     if (code == 27) {
  4:         OcultarTxtEdit(txt, false);
  5:     }
  6: }

YA tenemos nuestra grid con la posibilidad de modificar los registros, con tabulación y cancelación funcionando al 100% !!!!

grideditCel3

grideditCel33

La última parte será habilitar un método de página al que le podremos pasar las celdas modificadas con formato JSon desde el cliente.

*. Tipo:

  1: public class ClienteData
  2: {
  3:     public string id { get; set; }
  4:     public string columna { get; set; }
  5:     public string valor { get; set; }
  6: }

*. ActualizarDatos “Servidor”:

Método del servidor que recupera la información del cliente y convierte el objeto Json en una lista de tipos “ClienteData”:

grideditCelDebug

*. ActualizarDatos “Cliente”:

Función script que recupera todas las celdas que han sido modificadas y crea un objeto json que se envía al servidor.

  1: function ActualizarDatos()
  2: {
  3:     var datos = '';
  4:     var txtEditados = $(".txtEdit");
  5:     for (var i = 0; i < txtEditados.length; i++) {      
  6:         if(i > 0)
  7:             datos += ',';
  8:           
  9:         datos += '{"id":"' 
 10:          + txtEditados[i].parentElement.cells[0].innerText
 11:          +'","columna":"'
 12:          + txtEditados[i].getAttribute("columnName")
 13:          + '","valor":"'+txtEditados[i].innerText
 14:          + '"}';
 15:     }       
 16:     var jDatos = JSON.parse('[' + datos.replace(/;/g, ",")+ ']');   
 17:     PageMethods.ActualizarDatos(jDatos, 
 18:       ActualizarDatosOK, ActualizarDatosKO);
 19: }

4: recupera todas las celdas con el estilo de datos modificado.

9: crea un texto con formato JSon con el identificador del registo, el nombre del campo modificado y el nuevo valor.

16: transforma el texto en un objeto JSon “JSON con ASP.NET II

17: llama al método de página del servidor.

Ya hemos finalizado esta práctica y de una forma muy sencilla hemos mejorado la experiencia de nuestros usuarios. No es tan complicado adaptar los controles ASP.NET para nuestras aplicaciones y a veces es mejor que utilizar complicados controles de terceros.

Aplicaciónimages

Cross-Posting: http://lonetcamp.com

 

Jquery – la potencia sin control no sirve de nada !!

Yo soy de esos programadores web que están disfrutando con las bondades que nos ofrece JQuery desde su aparición. Esta librería nos simplifica enormemente nuestros desarrollos con JavaScript y los hace mucho más productivos.

Pero hasta ahora realmente no había aprovechado todo su potencial y es precisamente en  esta situación cuando me ha defraudado un poco.

Me explico:

He querido tratar todo un interfaz de usuario con JQuery para optimizar la presentación y evitar las idas y venidas de la página para consultar los datos. Para eso recupero la información para rellenar un control, desde mi capa de datos utilizando un método de página y formato Json, de esta manera se evita enviar la información innecesaria de la página.

Estos datos tienen una estructura mas o menos compleja o al menos más compleja que una simple tabla, porque se tiene que representar en diferentes niveles.

  • Fechas[n]
    • Identificadores[n]
      • Propiedades[n]
        • Valor

test11

Para representar estos datos correctamente en la tabla he generado unos bucles que recorren los datos y los presenta dependiendo de algunas condiciones.

No voy a poner todo mi código pero tendría más o menos este aspecto:

  • Varios bucles anidados para recorrer los registros y generar la tabla.
$($("#" + tabla + " tr:first")[0].cells).each(function() { 

        var diaCell = this;
        diaCell.innerText = result[pos].Key.charAt(0);

  • Modificación del DOM para agregar y eliminar datos de la tabla.
var rowHabitaciones = $("#" + tabla + " tr [hab]");
var reg = "<td>"+name +"</td>";
$(RowHab).after(reg);

Todo perfecto y encantado de lo simple que me ha quedado el código de cliente que tiene que tratar tanta información.

Peroooooo!!! si hay un pero.

Al ejecutar el código está tardando mucho más de lo esperado. Llego a tardar tanto en pintar la tabla que hasta el propio explorador me avisaba de este problema.

test

la potencia sin control no sirve de nada !!

Tenemos que tener en cuenta que Jquery es una librería que encapsula el lenguaje JavaScript para simplificar su uso, eso significa que para nosotros recorrer el DOM es ahora mucho más fácil, pero internamente sigue ejecutando complicadas sentencias para que nuestro código funcione por ejemplo en diferentes navegadores sin problemas.

Por ese motivo tenemos que seguir unas cuantas reglas para que nuestro código sea lo más optimo posible.

Antes de la optimización de mi código he testeado la velocidad que tarda el script en representar los datos inicialmente.

Primera prueba sin optimizar: 17,366 segundos !!!!!

test1

Realmente es impensable tener un script que tarde 17 segundos en pintar una tabla en el cliente.

Ahora voy a seguir unas simples reglas para el uso adecuado de Jquery haber si realmente ganamos algo en eficacia.

  1. Iteraciones: Es recomendable utilizar en lo posible las funciones nativas del navegador y evitar utilizar directamente los objetos del DOM en estas. Es más preferible utilizar texto y añadir este al final de la iteración.
  2. Añadir elementos al DOM: Siguiendo el anterior consejo, si tenemos que agregar una gran cantidad de objetos al DOM, es mejor añadir todos los objetos de una vez que irlos añadiendo progresivamente.
  3. NO abusar de los selectores: Es muy fácil abusar de los selectores por su gran potencia. Utilizar variables con los resultados de los selectores para su reutilización.

Muchos más consejos en improve-your-jquery-25-excellent-tips.aspx

Después de limpiar, reorganizar, no abusar de los objetos DOM y utilizar for en decremento de los cómodos each este es el resultado.

Segunda prueba con el código optimizado: 0,361 segundos !!!!!

test2

Realmente si cuidamos un poco la forma de utilizar Jquery sumado con el clásico JavaScript podemos tener un código mucho más optimizado para utilizar con nuestro interfaces de usuario.

Yo al menos en esta práctica me he ahorrado 17 segundos ni más ni menos y mi control está funcionando al 100%.

CrossPosting http://lonetcamp.com

JSON con ASP.NET II

Por petición popular voy a ampliar el artículo que dedique en su día a la clase DataContractJsonSerializer la cual podemos utilizar para serializar o deserializar objetos JSon a objetos .NET.

En este artículo explicaré como pasar una colección de objetos JSON al servidor mediante ASP.Net AJAX de una forma muy sencilla.

Puedes ojear el artículo inicial en : serializar-deserializar-json-en-asp-net

Simplemente ampliaré el ejemplo que ya utilicé en el primer artículo, para que podamos seleccionar varios registros de la grid y posteriormente pasar esta lista de objetos al servidor utilizando un método accesible desde el cliente “PageMethod” con ASP.NET AJAX.

ser2

Este “PageMethod” es muy sencillo, simplemente espera una colección de objetos ProductoData.

Por defecto nuestro método utilizará el formato JSon para recibir los datos, pero he dejado el atributo ResponseFormat para que veáis como se puede especificar si queremos utilizar XML o JSON para nuestro tratamiento de los datos.

En esta imagen podéis comprobar como nuestra colección de objetos llega perfectamente deserializado y convertido a nuestra lista de objetos ProductoData.

ser

Como podéis comprobar en el servidor no nos tenemos que preocupar de convertir los datos que recibimos del cliente, porque es totalmente transparente para nosotros.

La parte donde lo tendremos un poquito más difícil es en el script del cliente, que tiene que formatear los datos en un correcto objeto JSON y enviar los datos al servidor.

function BorrarSeleccionados( ) {

    var ProductoDataList = new Array();
    $("#tableproductos tr td :checked").each(function() {

    ProductoDataList.push('{"ProductID":'
        + $(this).parent().next()[0].innerText + 
        ', "ProductName":"' 
        + $(this).parent().next().next()[0].innerText +
        '", "UnitPrice":' 
        + $(this).parent().next().next().next()[0].innerText +
        ', "UnitsInStock":' 
        + $(this).parent().next().next().next().next()[0].innerText + ' }');

    });

    var productos = JSON.parse(
      '[' + ProductoDataList.toLocaleString().replace(/;/g, ",")+ ']');
PageMethods.BorrarSeleccionados(productos, BorrarSeleccionadosOK, BorrarSeleccionadosKO); }

Esta función JavaScript utiliza JQuery para recorrer la grid en busca de los elementos seleccionados “checked”. Crea un Array de objetos al cual iremos añadiendo los elementos seleccionados dando el formato JSon que necesitamos para generar nuestro objeto ProductoData “ProductID, ProductName, UnitPrice, UnitsInStock”.

Luego utilizaremos la clase JSON para parsear el Array en un Objeto JSON correctamente formado y gracias a esta clase no tenemos que utilizar el famoso eval de JavaScript evitando los problemas de seguridad.

Finalmente pasamos el objeto JSON obtenido al método de servidor que recogerá los datos y ya tenemos el ejemplo 100% funcionando.

ser3

Realmente utilizar el formato de datos JSON con ASP.NET AJAX es realmente fácil, únicamente se nos puede complicar un poco la cosa con la parte de dar formato a los datos en el cliente.

Espero que os sea útil este pequeño ejemplo y a los que me habéis pedido esta explicación ya me comentareis si esto es lo que necesitabais.

Algunas Referencias relacionadas con el artículo:

http://www.json.org/js.html

http://jquery.com/

CrossPosting: http://mrubino.net

 

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.

Nos vemos en el próximo artículo.   

 Cross-Posting www.lonetcamp.com