Introducción a Web Services con .NET III

En las partes uno y dosde nuestros tutoriales vimos como podemos crear un Web Service con .NET, desplegarlo en Flex y posteriormente mediante nuestro Web Service acceder a una base de datos SQL2005. Aunque en el tutorial pasado tenemos una excelente manera de desplegar los datos no es la manera o el camino más adecuado para representar o traer nuestros datos, ya que si son demasiados datos podemos bajar el rendimiento y tiempo de respuesta de nuestra aplicación tanto del lado del cliente como del servidor. En esta última parte de la saga veremos como podemos manejar esta situación además de desplegar resultados y posibles fallas con eventosResultEvent y FaultEvent, además implementaremos un J2EE design pattern llamado DataTransfer Object (Value Object) que me permite un mayor performance en la aplicación en ambos lados, cliente y servidor.

Data Transfer Object (Value Object)


El patron Data Transfer Object tambien conocido como Value Object (VO) es un patrón que me permite optimizar la transferencia de datos atraves de las capas de la aplicación. Este patrón es muy efectivo ya que en lugar de mandar o recibir datos de manera individual, contiene todos los datos en una estructura única (estructura de datos) solicitada ya sea por la petición o la respuesta. Para ver más información acerca de este patrón pueden ir al sitio de Sun o pulsando aqui.. También Xavi escribio un articulo acerca de CAIRNGORM explicando este patrón y lo puedes ver pulsando aqui.

Lo primero que debemos hacer entonces es regresar a nuestro código (.NET) y escribir la siguiente estructura de datos en Service.cs. Tenemos entonces ahora implementando el patron VO, veamos pues el código

[FTF]using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;

[WebService(Namespace = "http://localhost/webserviceclass/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
//Data Transfer Object de Producto

public class Service : System.Web.Services.WebService
{
//DTO para la tabla Productos
public struct Product
{
public int ProductId;
public int CategoryId;
public string ModelNumber;
public string ModelName;
public string ModelImage;
public decimal UnitCost;
public string Description;

}

public Service () {

//Eliminar la marca de comentario de la línea siguiente si utiliza los componentes diseñados
//InitializeComponent();
}

[WebMethod (Description="Método de prueba que me regresa una cadena")]
public string HelloWorld() {
return “Hola a todos”;
}

[WebMethod(Description = "Método para probar la conexión con la base de datos")]
public bool TestConnection()
{
//CADENA DE CONEXION
string strConn = ConfigurationManager.ConnectionStrings["StoreAccess"].ConnectionString;

//OBJETO DE CONEXION SQL, SI LA BASE DE DATOS ES ACCESS
//EL OBJETO SERIA OleDbConnection
SqlConnection sqlConn=new SqlConnection();

//ASIGNO LA CADENA DE CONEXIÓN
sqlConn.ConnectionString=strConn;

try{

//ABRO LA CONEXION

sqlConn.Open();

//SI TODO ES CORRECTO REGRESAME VERDADERO
return true;
}

//DE LO CONTRARIO REGRESAME FALSO
catch(Exception ex){
return false;
}

//FINALMENTE CIERRA LA CONEXION
finally{
sqlConn.Close();
}

}
[WebMethod(Description = "Método que me devuelve un Arreglo de Productos")]
public Product[] obtenProductos()
{
//DECLARO MI CADENA DE CONEXION ALMACENADA
//EN EL ARCHIVO WEB.CONFIG
string strConn = ConfigurationManager.ConnectionStrings["StoreSQL"].ConnectionString;

//DECLARO MI OBJETO DE CONEXION
SqlConnection sqlConn = new SqlConnection();

//ASIGNO LA CADENA DE CONEXION
sqlConn.ConnectionString = strConn;

//SQL A LA TABLA PRODUCTS
string strSQL = “SELECT * FROM PRODUCTS”;

//DECLARO UN SQL COMMAND
SqlCommand sqlCom = new SqlCommand();

//ASIGNO EL COMANDO
sqlCom.CommandText = strSQL;
sqlCom.Connection = sqlConn;

//BLOQUE TRY
try
{
sqlConn.Open();
//DECLARO UN DATAREADER
SqlDataReader dr = sqlCom.ExecuteReader();

//ARRAY LIST
ArrayList al = new ArrayList();

while (dr.Read())
{
//CREO UN NUEVO OBJETO PRODUCTO POR CADA
//REGISTO QUE SE ENCUENTRE EN EL DATA READER
Product producto = new Product();

producto.ProductId = dr.GetInt32(0);
producto.CategoryId = dr.GetInt32(1);
producto.ModelNumber = dr.GetString(2);
producto.ModelName = dr.GetString(3);
producto.ModelImage = dr.GetString(4);
producto.UnitCost = dr.GetDecimal(5);
producto.Description = dr.GetString(6);

//AGREGO CADA UNO DE LOS OBJETOS CREADOS AL ARRAYLIST
al.Add(producto);
}

//DEFINIMOS UN ARRAY DE PRODUCTOS Y LOS LLENAMOS
Product[] productoFlex = new Product[al.Count];

for (int i = 0; i < al.Count; i++)
{
//CASTING PARA QUE SEA DE TIPO PRODUCTOS
productoFlex[i] = (Product)al[i];
}

return productoFlex;
}
catch (Exception ex)
{
return null;
}

}

}[/FTF]

Posteriormente vamos a cambiar ahora el método que teniamos anteriormente, es decir el metódo getDataTable (tutorial pasado) por un método llamado obtenProductos para regresar un arreglo de objetos e inerpretarlo directamente en Flex como un ArrayCollection, en este caso de productos, entonces en las lineas n y n dentro del bloque try declaro un Reader que me
leera los datos de mi consulta. Enseguida declaro un ArrayList, no se olviden importar la clase System.Collections para tal efecto , y este ArrayList es el que me almacenara los datos que vaya leyendo el DataReader uno por uno. Con el método Read, del DataReader ire leyendo todos y cada uno de los registros que tengo disponibles, recuerden que para consultas de solo lectura usemos DataReader y no Dataset ya que el DataReader es mucho más rápido que el DataSet.

Ahora en las lineas n y n creo un nuevo objeto por cada uno de los datos o registros que encuentre mi datareader y asigno las propiedades que ya defini en mi estructura de datos. Estas propiedades seran igual al valor obtenido por el DataReader y si se dan cuenta van de manera secuencial es decir de 0 a 6 y lo más importante de todo que que el dr tiene tipos de datos para obtener, lo cual esto es caso sensible ya que si se que en mi tabla de la base de datos tengo un tipo de dato Int y quiero obtener un dr.GetString (n) me mandara un error el compilador. Para esto también es importante definir el tipo de datos correcto en mi estructura de datos si no me puede ocasionar problemas posteriores. Ahora una vez que ya tengo cada uno de los registros en un objeto , voy agregando esos objetos a mi ArrayList, es importante recalcar que hasta este punto no estamos regresando nuestros VOs o Value Objects.

Ahora nuestra intención es regresar los VOs entonces en la línea n declaro un tipo de Dato Product (estructura de datos que ya definimos) y que sera un array y le asigno un nombre de variable que sera igual al mismo pero con una dimensión preestablecida y que es igual a la dimensión de el ArrayList que ya llene con mis registros. Es entonces el momento de regresar mi estructura de datos dentro de un ciclo for y diciendole que cada elemento i de productFlex sera igual a un tipo de dato Product (elemento i del arreglo). Si notamos tenemos un parentesis, esto esta haciendo una conversion de datos del ArrayList a Product, de esta manera ya podemos regresar nuestras estructuras de datos y Flex las interpretara como un ArrayList!.

Finalmente en la línea n regreso mi estructura de Datos y Listo.

Manejo de Resultados (ResultEvent) y Errores (FaultEvent)

En todas las aplicaciónes al dia de hoy es necesario además de desplegar los resultados de manera eficiente, tambien manejar las posibles fallas que se nos pueden presentar a lo largo de la aplicación. Algunas de las fallas pueden ser que el servidor no este disponible, que el nombre del método que tengo del lado de mi WebService no corresponde al que estoy asignando en flex y esto es muy común osea que mucho cuidado, o algun otro tipo de error. Entonces siempre que trabajemos con WebServices u Objetos Remotos por que esto tambien aplica a objetos Remotos es manejar eventos de Tipo ResultEvent y FaulEvent uno para los resultados y otro para posibles fallas. Como recomendación entonces siempre manejaremos ResultEvent y FaultEvent, ya sea para WebServices o Para Objetos Remotos.

En Flex entonces modificaremos el código de la siguiente manera:

[FTF]


//IMPORTO LAS CLASEs NECESARIAS PARA MANEJAR EL DATASET Y EL EVENTO
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;

[Bindable]
private var arrProductos:ArrayCollection

//FUNCION QUE ME LLENA UN DATAGRID
private function llenaDataGrid(event:ResultEvent):void{

arrProductos=event.result as ArrayCollection;

}
//FUNCION QUE ME MANEJA LOS POSIBLES ERRORES
private function faultGrid(event:FaultEvent):void{

Alert.show(event.fault.faultCode+event.fault.faultDetail+event.fault.faultString);

}

]]>



width="201" click="mifWebService.HelloWorld()" />

click="mifWebService.obtenProductos()"/>

[/FTF]

En mi etiqueta operation que se encuentra en la línea n tengo un atributo llamado name que es igual al nombre del método que tengo de manera remota, es decir en .NET , esto hay que tener mucho cuidado para no tener posibles errores. Los siguientes dos atributos son result que es igual a una función y que esa funcion se encargara de llenar un ArrayCollection con los resultados para el DataGrid ya que declaramos este ArrayCollection con el Metatag [Bindable]. Posteriormente tengo otro atributo llamado fault que es igual a una función que en caso de cualquier falla, me dira en una ventana de Alerta, la posible falla en la que estoy incurriendo.

Puedo tener más etiquetas operation es decir más operaciones para efectuar , además es muy conveniente y comodo manejar por cada etiqueta operation sus resultados es decir escribir las funciones pertinentes para manejar los resultados y podemos tener de alguna manera solo un faulEvent es decir uno genérico o podriamos implementar uno por cada operacion.

Esta es la manera más apropiada de trabajar con WebServices y .NET, ya que me va a ofrecer un rendimiento mucho mejor del lado del cliente y servidor. No obstante implica más código pero es la mejor manera de hacerlo. A los WebServices podemos mandarles también parámetros para una mayor interacción con el servicio Remoto y que estos esperen el parámetro o parametros para efectuar las operaciones solicitadas con este parametro. En la próximo tutorial veremos como puedo accesar directamente a un objeto Remoto es decir a una dll hecha en .NET atraves de WEBORB

Israel Gaytán es un Adobe Certified Professional y desarrollador enfocado en la creación de RIAs. Desarrolla bajo la plataforma.NET y ha trabajado con Flash, Flash remoting (AMFPHP, .NET) y Flash Media Server.

Sitio Web:http://riata.wordpress.com

25 Comentarios

  1. Rodolfo

    buen documento, sin embargo no estoy deacuerdo
    que un solo punto

    la no utilizacion de DataSet … creo que eso es muy subjetivo y depende mucho del tipo problema a resolver ….

    1ero son aplicaciones RIA lo que implica casi de manera inmediata un ancho de banda suficiente para ejecutarlas
    (por ejemplo una intranet)

    2do Existen un sin fin de ventajas relacionadas a los dataset (.net/ flex) que se pueden convertir en un dolor de cabeza al utilizar un manejo de arreglos derivados de un datareader

    detodas formas me gusto el articulo, es solo una opinion

  2. jorge oscar

    saludos me parecen muy bien los ejemplos creo que son faciles de entender y de verdad que me han ayudado mucho, pero estaria genial que publicaras uno para manipulacion de datos ya que tienes muy bien explicados tis archivos esperemos que salga el IV felicitaciones israel

  3. Israel Gaytan

    Estamos trabajando para ello Jorge Oscar y la idea es con WebOrb, lo mejor de todo es que los conceptos de ADO.NET los vas a poder aplicar de la misma manera con Web Services

  4. kike Pradas

    Gracias Israel, estamos aprendiendo muchisimo con tus tutoriales y tenemos gran interes en que edites el número IV.

    Animo.

  5. kike Pradas

    Querido Israel:

    Debido a mi poca paciencia, nos hemos puesto a investigar el tema del WebORD y Flex. Todo a sido muy emocionante y una vez que habiamos conseguido instalar todo correctamente me sale un mensaje mediante el cual necesito una licencia profesional (3000$) para que funcione el data manager.

    Mi desilusión fue mayuscula. Aun así veré si puedo realizar conexión a la MSQL sin necesidad de ese desembolso.

    Un abrazo.

  6. Angel Méndez

    Muchas felicidades por los artículos, me han ayudado mucho porque de programar todo en .NET he podido pasar fácilmente a un tipo de cliente como es el flex.
    Ahora mismo estoy un poco bloqueado porque no consigo llamar un servicio web pasándole como parámetro un datatable.
    ¿me podrías indicar un ejemplo?

    Muchas Gracias

    Angel

  7. Israel Gaytan

    Queridos Kike y Angel:

    Bueno si , esta un poco caro el servidor de webORB pero si vale la pena para una aplicación enterprise adquirirlo. Ahora se que sqlServer 2005 tiene un motor para xml nativo, yo no he hecho las pruebas pero en teorioa podrias consultar directamente ese “xml” de sqlserver2005. En cuanto a Angel, que es exactamente lo que quieres realizar, es decir con que intención???

    Saludos!!!

  8. Angel Méndez

    Querido Israel.

    Lo que pretendo es descargarme en un cliente flex un datatable. Las filas las proceso en el cliente, las actualizo y le añado nuevas.
    Hasta aquí bien, pero ahora quiero, para grabar los datos en el servidor no hacer una llamada por cada fila a un web service, sino crear un webservice que reciba como parametro un datatable y procesar fila a fila dentro del webservice.

    gracias

    Angel

  9. Angel Méndez

    Querido Israel

    Lo he resuelto, no sé si será la óptima pero me funciona.

    En la parte servidora he creado un web service que recibe como parámetro un XMLNode o un String y automaticamente lo convierto en un dataset.

    En el cliente lo que he hecho el una función que haciendo uso de las clases de XMLDocument y XMLNode transformo un ArrayCollection en una cadena XML con estructura de documento XML. Esto es lo que le paso como parámetro al web Service.

    Un saludo
    Angel

  10. Gerardo Cabestani

    Muchísimas gracias por estos tres artículos.
    Además de felicitarte, necesito aclarar una duda, que me tiene un poco desesperado. Hice el web service en asp y el front con Flex para llamar una base de datos, el cual funciona perfectamente si se comunica con el servicio web de manera local, pero al momento de publicarlo ya no aparece la información en el datagrid de flex. Lo más extraño es que no presenta ningún error y si registro un dato nuevo en la base de datos desde el front hecho con flex, si lo registra, sólo que no presenta nada en el data Grid. Ayuda por favor. Gracias de antemano.

  11. Israel Gaytan

    Puede ser por varias causas, e incluso a mi me paso u na vez..verifca qu eel namespace ya no este con tempuri. Y si esta en un dominio asignale el dominio, si el caso es lo contrario vuelve a poner tempuri, a mi en más de una ocasion me ha pasado. Espero te sirva

    Saludos

  12. Jefferson

    Hola, interesante el articulo, pero quisiera saber si tengo algun problema de comunicacion que por ejemplo este usando una wan, tengo que salirme de la aplicacion completa que utiliza web services asi ya vuelva a tener comunicacion? y si esto me sucede que debo hacer?
    Gracias.

  13. jose

    Tengo una pregunta puedo tener esto en mi webservice

    la pregunta es varios operation??

    agradesco su ayuda.

  14. carlos

    hola oye tengo un problema con esto y ya me quebre la cabeza buscando soluciones a ver is tu me puedes ayudar, hize todo esto que explicas tengo un web service en .net se conecta a una base de datos en mysql y al correrlo en el internet explorer todo va bien pero al momento de hacer el flex no me llena el datagrid de ninguna de las dos formas con el dataset ni con el arreglo, lo corro y no me marca ningun error ni nada, si me muestra el hola mundo, y tambien hize un boton que me muestre el resultado de la prueba de conexion con la base de datos y me muestra true, asi que no entinedo que pasa, uso visual studio 2008, flex builder 3 y mysql server 5

  15. jose

    tu error va a que no estas bindeando tu arreglo .

    asegurate que en tu web service mandes un arreglo… para q no haya problemas en flex

    saludos y suerte

  16. carlos

    listo muchas gracias, el conector .net de mysql tiene un bug con los tipos unsigned int ya vi como solucionarlo, no es problema del tutorial esta perfecto

  17. Raul

    Como buena la info me ha parecido excelente, aunque me interesaria saber como poder pasar al webservice un parametro, digamos tengo un campo text en mi flex, como paso eso a mi web service, ojala alguien pueda responderme se lo agradecere
    :mrgreen:

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Acerca de Made In Flex

Made In Flex es una comunidad de desarrolladores de Apache Flex creada en 2006.

Apache Flex, anteriormente conocido como Adobe Flex, es un SDK (kit de desarrollo de software) para crear aplicaciones enriquecidas - multiplataforma basadas en Adobe Flash donado por Adobe a la fundación Apache in 2011 y promocionado a proyecto de primer nivel en Diciembre de 2012.

Actualmente estamos cambiando muchos aspectos del sitio web para ofrecer un sitio útil para toda la comunidad que tenga en cuenta las necesidades actuales.

Últimas Fotos

Instalador de Apache Flex

Entrar o Registrase