Generando una clase intermedia a través de wsdl.exe para conectarnos a un servicio web .asmx

Como bien sabemos, la forma más sencilla para agregar y posteriormente consumir un servicio web, es a través del menú contextual de Visual Studio:

Screen Shot 03-22-16 at 11.00 AM

Sin embargo, existen otras formas de consumir un servicio web de manera sencilla y transparente. Una de ellas puede ayudarnos además, para analizar, estudiar y aprender del código generado. Esta forma es a través de la herramienta wsdl.exe, que se encuentra en la siguiente ruta:

C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools

Debemos navegar a través de una consola de comandos a la dirección antes especificada, y utilizar algunas de las opciones disponibles. La simbología para utilizar la herramienta, es:

wsdl.exe <opciones> <dirección_url o ruta_de_acceso> …

Si deseamos ver las opciones disponibles, bastará con escribir simplemente wsdl.exe:

Screen Shot 03-22-16 at 11.07 AM

Vamos a utilizar el servicio “Weight Unit Convertor”, disponible en la página http://webservicex.net/, para generar la clase correspondiente. Lo primero que debemos hacer, es navegar al servicio web, donde nos será mostrado el Endpoint:

Screen Shot 03-22-16 at 11.10 AM

Dicho Endpoint, será el que utilizaremos para generar nuestra clase, debiendo colocarlo de la siguiente forma en la consola de comandos:

wsdl http://www.webservicex.net/ConvertWeight.asmx?WSDL

Lo que nos generará una clase en el directorio mismo de la herramienta:

Screen Shot 03-22-16 at 11.15 AM

Podemos agregar la clase generada a un proyecto desde Visual Studio, donde nos mostrará algunos errores si no hemos agregado la biblioteca System.Web.Services, por lo que es necesario que se encuentre dentro del proyecto donde utilizaremos el servicio web.

Screen Shot 03-22-16 at 11.17 AM

Con esto, podremos utilizar la clase generada como cualquier otra:

Screen Shot 03-22-16 at 11.23 AM 001

Además de que funcionará de manera correcta:

Screen Shot 03-22-16 at 11.23 AM

¡Saludos!

Utilizando la Biblioteca SqlHelper (2/n)

Ejecutar consulta y llenar un DataReader:

Para llevar a cabo la ejecución de una consulta y rellenar un DataReader, disponemos de los siguientes métodos:

Screen Shot 03-19-16 at 12.14 PM

En esta demostración, utilizaremos el método:

public static System.Data.SqlClient.SqlDataReader ExecuteReader(string connectionString, System.Data.CommandType commandType, string commandText)

Podemos observar, que se nos pide como primer parámetro una cadena de conexión, como segundo el tipo de comando (si es consulta normal o un stored procedure), y como tercer, la consulta como tal.

En primer lugar, definiremos en una variable la consulta que deseamos ejecutar:

var sqlQuery = "SELECT * FROM Customers";

En segundo lugar, llamaremos al método que nos interesa, pasándole como referencia la cadena de conexión que definimos en el post anterior, seguido por el tipo de enumeración que deseamos aplicar, y la consulta definida previamente. Cabe destacar, que utilizaremos un using para cerrar la conexión y eliminar la instancia una vez que la dejemos de utilizar:

 using (var newDataReader = SqlHelper.ExecuteReader(
                GlobalData.ConnectionString,
                CommandType.Text, sqlQuery))

Por último, haremos un recorrido por el datareader e imprimiremos la información deseada:

while (newDataReader.Read())
                {
                    var customerInfo = string.Format(
                        "Company Name: {0}, ContactName: {1}",
                        newDataReader.GetString(1),
                        newDataReader.GetString(2));
                    Debug.WriteLine(customerInfo);                    
                }

Quedando el código completo del método, de la siguiente manera:

 private void StartDataReaderDemo()
        {
            //Utilizando SqlHelper para llenar un DataReader
            var sqlQuery = "SELECT * FROM Customers";
            using (var newDataReader = SqlHelper.ExecuteReader(
                GlobalData.ConnectionString,
                CommandType.Text, sqlQuery))
            {
                while (newDataReader.Read())
                {
                    var customerInfo = string.Format(
                        "Company Name: {0}, ContactName: {1}",
                        newDataReader.GetString(1),
                        newDataReader.GetString(2));
                    Debug.WriteLine(customerInfo);                    
                }
            }


        }

Ejecutar consulta a un Stored Procedure y llenar un DataReader:

La forma para llevar a cabo una consulta a un procedimiento almacenado, conlleva básicamente los mismos pasos que anteriormente, con la diferencia, que debemos especificar el nombre del procedimiento almacenado en lugar de la consulta:

var sqlQuery = "Sales by Year";

En segundo lugar, debemos definir un arreglo de tipo SqlParameter, definiendo los parámetros que deseamos pasar:

            var param1 = new SqlParameter {ParameterName = "@Beginning_Date", Value = new DateTime(1995, 1, 1) };
            var param2 = new SqlParameter { ParameterName = "@Ending_Date", Value = new DateTime(1997, 1, 1)};
            SqlParameter[] parameters = new[] {param1, param2};

Lo demás, es prácticamente lo mismo, el código completo del método se encuentra a continuación:

        private void StartDataReaderDemo2()
        {
            //Utilizando SqlHelper para llenar un DataReader a través de un stored procedure
            var sqlQuery = "Sales by Year";
            var param1 = new SqlParameter {ParameterName = "@Beginning_Date", Value = new DateTime(1995, 1, 1)};
            var param2 = new SqlParameter {ParameterName = "@Ending_Date", Value = new DateTime(1997, 1, 1)};
            SqlParameter[] parameters = new[] {param1, param2};
            using (var newDataReader = SqlHelper.ExecuteReader(
                GlobalData.ConnectionString,
                CommandType.StoredProcedure, sqlQuery, parameters))
            {
                while (newDataReader.Read())
                {
                    var customerInfo = string.Format(
                        "Order ID: {0}, Subtotal{1}",
                        newDataReader.GetInt32(1),
                        newDataReader.GetDecimal(2));
                    Debug.WriteLine(customerInfo);
                }
            }
        }

Utilizando la Biblioteca SqlHelper (1/n)

En una publicación pasada, agregamos a nuestra solución una clase que puede llevar a cabo la ejecución de consultas a un servidor SQL Server, vamos a ver en esta entrada cómo utilizar algunos de los métodos incluidos en la clase, tomando como la base de datos Northwind como ejemplo.

Ejecutar consulta y llenar un DataSet:

Si se quiere llenar un DataSet para trabajar posteriormente con él, podemos ejecutar el método denominado “ExecuteDataset”, el cual tiene 8 sobrecargas (Dar click en la imagen para ver en tamaño real):

Screen Shot 03-16-16 at 11.06 AM

La clase nos da una amplia gama de sobrecargas para poder pasar todo tipo de parámetros necesarios para llevar a cabo la ejecución de una consulta y posterior llenado de un Dataset, como ejemplo, vamos a ocupar el segundo método:

SqlHelper.ExecuteDataset(string, System.Data.CommandType, string)

cuya definición es:

public static System.Data.DataSet ExecuteDataset(string connectionString, System.Data.CommandType commandType, string commandText)

Es decir, debemos pasar como primer parámetro una cadena de conexión (Existe otro método para pasar directamente un objeto ConnectinString), para cuestiones de simplicidad, he creado una clase que mantiene la cadena de conexión centralizada:

    public static class GlobalData
    {
        public static string ConnectionString { get; set; }
        static GlobalData()
        {
            ConnectionString = @"Data Source=.\SQLSERVER;Initial Catalog=Northwind;Integrated Security=True";
        }
    }

Debemos crear una variable para almacenar la consulta que deseemos ejecutar, en mi caso será la siguiente:

var sqlQuery = "SELECT * FROM Customers";

Listo, ya podremos utilizar el método con la información previamente definida, colocando el resultado de la ejecución de tipo DataSet en una nueva variable:

            var newDataSet = SqlHelper.ExecuteDataset(
                GlobalData.ConnectionString,
                CommandType.Text, sqlQuery);
            var customers = newDataSet.Tables[0];

Si deseamos consultar el resultado, debemos obtener una de las tablas de la consulta en primer lugar:

var customers = newDataSet.Tables[0];

para posteriormente utilizar Linq para llevar a cabo la consulta (Debemos utilizar un método especial llamado .AsEnumerable para poder realizar consultas con Linq, que se encuentra en el ensamblado System.Data.DataSetExtensions), y como buena práctica, definir un nuevo tipo anónimo para poder utilizar las propiedades desde código:

            var query = from customer in customers.AsEnumerable()
                        select new
                        {
                            CompanyName = customer.Field<string>("CompanyName"),
                            ContactName = customer.Field<string>("ContactName")
                        };

Por último, podemos recorrer el resultado de la consulta Linq e imprimir la información necesaria:

            foreach (var customer in query)
            {
                Debug.WriteLine(customer.CompanyName);
            }

Recuerden que el código se irá complementando en el repositorio de GitHub:

https://github.com/hprez21/Hyrule

 

En la próxima entrada seguiremos viendo más métodos

¿Cómo depurar una aplicación de forma remota con Visual Studio 2015? (aplica para versiones anteriores también)

Aunque existe una guía oficial para llevar a cabo este procedimiento, en esta entrada detallaré los pasos necesarios para llevar a cabo la depuración de una aplicación de forma remota.

Prerrequisitos:

Aunque no es indispensable, es altamente recomendable tener activada y configurada la opción de Conexión a Escritorio Remoto en el equipo donde llevaremos a cabo las pruebas de la aplicación.

Configurando la herramienta:

En primer lugar, debemos instalar la herramienta de depuración remota para Visual Studio 2015. Se pueden elegir las herramientas para las plataformas x64, x86 y ARM.

Una vez instalado en la máquina remota, debemos iniciar el asistente para configurar la herramienta:

Screen Shot 03-04-16 at 08.46 PM

Esto nos desplegará una ventana donde podremos configurar si deseamos que la aplicación se ejecute como un servicio en la máquina de pruebas. En mi caso lo dejaré deseleccionado.

Screen Shot 03-04-16 at 08.47 PM

En la siguiente ventana, se nos pregunta la configuración que deseamos aplicar para el firewall de acuerdo al tipo de red seleccionada. Para cuestiones prácticas dejaré seleccionadas todas las redes.

Screen Shot 03-04-16 at 08.48 PM

 

Después de este paso, podremos dar click en el botón Finalizar. Con esto hemos configurado la herramienta para poder llevar a cabo pruebas de nuestras aplicaciones en una máquina remota.

Preparándonos para la prueba:

Dentro de Visual Studio, debemos irnos a las propiedades del proyecto (no de la solución):

Screen Shot 03-04-16 at 08.55 PM

Dentro de las propiedades del proyecto, debemos irnos al apartado “Debug”, y en la sección de “Start Options”, habilitar “Use remote machine”. En la casilla de la derecha, debemos utilizar de preferencia la dirección IP de la máquina remota.

Screen Shot 03-04-16 at 08.58 PM

Paso siguiente, debemos hacer un rebuild de nuestro proyecto (hay que checar que se encuentre en modo Debug).

En seguida, debemos crear una estructura en la máquina remota que sea idéntica a nuestra carpeta bin de nuestra máquina local. Es decir, si la carpeta Debug de mi proyecto se encuentra en C:\Users\hprez\Documents\Visual Studio 2015\Projects\Blog\ExcelSample\ExcelSample\bin\Debug, debemos crear esta misma estructura en la máquina remota, tal como en el siguiente ejemplo:

Máquina local (con VS)

Screen Shot 03-04-16 at 09.07 PM

Máquina remota (Sin VS)

Screen Shot 03-04-16 at 09.09 PM

Por último, deberemos copiar el contenido de la carpeta Debug de nuestro proyecto, y pegarlo en la carpeta Debug de la máquina remota:

Screen Shot 03-04-16 at 09.11 PM

Una vez que estemos listos, deberemos iniciar la herramienta de depuración remota en la máquina remota, la cual, nos deberá indicar que se encuentra esperando nuevas conexiones:

Screen Shot 03-04-16 at 09.14 PM

Finalmente, iniciaremos nuestro proyecto desde Visual Studio, y todo deberá funcionar a la perfección:

Screen Shot 03-04-16 at 09.16 PM 001

 

Cabe aclarar que si deseamos depurar la aplicación a través de un breakpoint en un punto específico de la aplicación, debemos regenerar el proyecto y copiar de nuevo el contenido de la carpeta bin, esto es debido a que se tiene que regenerar la información de depuración.

Espero que a más de uno le sea de utilidad.

Saludos.

Manipulando archivos de Excel con C# sin morir en el intento (1/n)

Como desarrolladores, muchas veces nos hemos enfrentado a la necesidad de manipular archivos en formato excel.

Una forma, es manipular dichos archivos a través de la biliboteca de interoperabilidad Microsoft.Office.Interop.Excel.dll. Sin embargo, esto requiere que tengamos instalados ensamblados especiales de acuerdo a la compilación que hayamos realizado, lo cual podría provocar el clásico error El proveedor ‘Microsoft.ACE.OLEDB.12.0’ no está registrado en el equipo local. En esta entrada, veremos una forma mucho más sencilla de manipular archivos de Excel de una forma nativa y sin necesidad incluso de tener instalado Excel en la máquina de los clientes.

Overview

Los archivos de Office de las versiones actuales de Office, están basados en OpenXML, cuya definición en Wikipedia es:

Office Open XML (también llamado OOXML u OpenXML) es un formato de archivo abierto y estándar cuyas extensiones más comunes son .docx, .xlsx y .pptx. Se le utiliza para representar y almacenar hojas de cálculo, gráficas, presentaciones y documentos de texto. Un archivo Office Open XML contiene principalmente datos basados en el lenguaje de marcado XML, comprimidos en un contenedor .zip específico.

Es decir, que si contamos con un archivo con extensión .xlsx, basta con cambiarle dicha extensión por una .zip, para poder descomprimirlo y ver en su interior el contenido del archivo tal como en la siguiente imágen:

Screen Shot 03-04-16 at 12.33 PM

Screen Shot 03-04-16 at 12.42 PM

Podemos darnos cuenta entonces, que un archivo de Excel no es más que un conjunto de archivos xml que podemos manipular a nuestro antojo para llevar a cabo distintas operaciones.

Trabajando con archivos de Excel

Para no reinventar la rueda, hoy en día existen diferentes alternativas para abrir documentos con formato open xml. En esta publicación haremos uso de ClosedXML Basta con ir a la página oficial en CodePlex para descargar la dll que necesitemos (framework 3.5 o 4) y descomprimir el archivo .zip descargado para poder utilizar la biblioteca. Por último (Lo remarco en rojo porque es importante) debemos descargar la biblioteca DocumentFormat.OpenXml, ya sea para el framework +4.0 ó 3.5

Creando un archivo de Excel

El uso de la biblioteca (al ser orientado a objetos) resulta extremadamente sencillo. Si deseamos crear una instancia de un libro de Excel, basta con utilizar la clase XLWorkbook, el cual contiene una propiedad haciendo referencia a las hojas del libro, las que a su vez contienen referencias a las celdas.

Nuestro primer ejemplo, consistirá en crear un libro en Excel, el código para hacerlo es el siguiente:

var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sample Sheet");
worksheet.Cell("A1").Value = "Hola mundo desde Excel!";
workbook.SaveAs("HelloWorld.xlsx");

 

Una vez ingresado el código en el manejador de eventos de un botón, tendremos un libro de Excel satisfactoriamente creado:

Screen Shot 03-04-16 at 01.02 PM

Screen Shot 03-04-16 at 01.11 PM

Screen Shot 03-04-16 at 01.11 PM 001

En la siguiente entrada, nos dedicaremos a manipular archivos de Excel existentes.

¡Hasta la próxima!