miércoles, 9 de octubre de 2013

Manejo de Excepciones en .NET


En esta oportunidad veremos cómo hacer uso de las excepciones en un Servicio Web REST, para lo cual, tomaremos como referencia el Servicio Web “Productos” del caso que hemos venido desarrollando en entradas anteriores.

En nuestra carpeta “Dominio” agregar la clase “Validacion.cs” con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;

namespace ProductosService.Dominio
{
    [DataContract]
    public class Validacion
    {
        [DataMember]
        public string Error { get; set; }
    }
}

Luego, dentro de la carpeta “Persistencia”, editemos el archivo “ProductoDAO.cs” y adicionemos el siguiente método:

public Producto ObtenerProductoPorNombre(string No_Producto)
{
    Producto productoEncontrado = null;
    string sql = "SELECT * FROM t_producto WHERE No_Producto = @No_Producto";
    using (SqlConnection con = new SqlConnection(Conexion.Cadena))
    {
        con.Open();
        using (SqlCommand com = new SqlCommand(sql, con))
        {
            com.Parameters.Add(new SqlParameter("@No_Producto", No_Producto));
            using (SqlDataReader resultado = com.ExecuteReader())
            {
                if (resultado.Read())
                {
                    productoEncontrado = new Producto()
                    {
                        Co_Producto = resultado["Co_Producto"].ToString(),
                        No_Producto = (string)resultado["No_Producto"],
                        Ss_Precio = (decimal)resultado["Ss_Precio"],
                        Qt_Stock = (int)resultado["Qt_Stock"]
                    };
                }
            }
        }
    }
    return productoEncontrado;
}

Luego será necesario modificar el archivo “Productos.svc”, con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using ProductosService.Persistencia;
using ProductosService.Dominio;
using System.Net;

namespace ProductosService
{
    public class Productos : IProductos
    {
        private ProductoDAO dao = new ProductoDAO();

        public Producto CrearProducto(Producto productoACrear)
        {
            if (dao.ObtenerProductoPorNombre(productoACrear.No_Producto) == null)
            {
                return dao.Crear(productoACrear);
            }
            else
            {
                throw new WebFaultException<Validacion>(new Validacion { Error = "El producto (" + productoACrear.No_Producto + ") ya existe." }, HttpStatusCode.BadRequest);
            }
        }

        public Producto ObtenerProducto(string Co_Producto)
        {
            return dao.Obtener(Co_Producto);
        }

        public Producto ModificarProducto(Producto productoAModificar)
        {
            if (dao.ObtenerProductoPorNombre(productoAModificar.No_Producto) == null)
            {
                return dao.Modificar(productoAModificar);
            }
            else
            {
                throw new WebFaultException<Validacion>(new Validacion { Error = "El producto (" + productoAModificar.No_Producto + ") ya existe." }, HttpStatusCode.BadRequest);
            }
        }

        public void EliminarProducto(string Co_Producto)
        {
            dao.Eliminar(Co_Producto);
        }

        public List<Producto> ListarProductos()
        {
            return dao.ListarProductos();
        }
    }
}

Agregar a nuestro proyecto “ProductosTEST” la clase “Validacion.cs”.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProductosTEST
{
    class Validacion
    {
        public string Error { get; set; }
    }
}

Ahora pasaremos a modificar nuestro archivo “ProductosTest.cs”, adicionando el siguiente método:

[TestMethod]
public void TestCrearProductoNegativo()
{
    // Prueba de creacion de producto via HTTP POST
    string postdata = "{\"No_Producto\":\"LAPTOP HP PAVILION\",\"Ss_Precio\":\"2599.99\",\"Qt_Stock\":\"150\"}";
    byte[] data = Encoding.UTF8.GetBytes(postdata);
    HttpWebRequest req = (HttpWebRequest)WebRequest
        .Create("http://localhost:32641/Productos.svc/Productos");
    req.Method = "POST";
    req.ContentLength = data.Length;
    req.ContentType = "application/json";
    var reqStream = req.GetRequestStream();
    reqStream.Write(data, 0, data.Length);

    try
    {
        var res = (HttpWebResponse)req.GetResponse();
        StreamReader reader = new StreamReader(res.GetResponseStream());
        string productoJson = reader.ReadToEnd();
        JavaScriptSerializer js = new JavaScriptSerializer();
        Producto productoCreado = js.Deserialize<Producto>(productoJson);
        Assert.AreEqual("LAPTOP HP PAVILION", productoCreado.No_Producto);
        Assert.AreEqual(2599.99m, productoCreado.Ss_Precio);
        Assert.AreEqual(150, productoCreado.Qt_Stock);
    }
    catch (WebException ex)
    {
        HttpWebResponse resError = (HttpWebResponse)ex.Response;
        StreamReader reader = new StreamReader(resError.GetResponseStream());
        string error = reader.ReadToEnd();
        JavaScriptSerializer js = new JavaScriptSerializer();
        Validacion exception = js.Deserialize<Validacion>(error);
        Assert.AreEqual("El producto (LAPTOP HP PAVILION) ya existe.", exception.Error);
    }
}

Finalmente probar nuestro método y verificar también en la base de datos, que el registro duplicado no se registró.


Bueno esto seria todo por hoy, espero que este tema les haya sido útil.

Gracias !!!

Testeando Web Services SOAP y REST


TEST Servicio Web SOAP utilizando WCF Test Client

En esta ocasion probaremos el servicio “Clientes” que desarrollamos en nuestro primer tema (Servicio Web SOAP), para lo cual utilizaremos el WCF Test Client.

Utilizando el explorador de Windows ubiquemos la ruta donde se encuentra instalado el Microsoft Visual Studio y sigamos la ruta que se indica en la siguiente imagen:


Dar doble clic en WcfTestClient, en la ventana que aparece, seleccionar el menú “Archivo” y escoger la opción “Agregar Servicio”, tal como se muestra en la figura adjunta.


Luego colocar la ruta del servicio que queremos probar y dar clic en “Aceptar”.


Nos aparecerá una ventana como se puede apreciar en la figura a continuación, donde se nos presentan los métodos que tiene disponibles el servicio.
Para empezar a probar cada uno de ellos daremos doble clic sobre el método a probar, y en la parte superior derecha aparecerán los datos de entrada (Solicitud), luego dar clic en el botón “Invocar”.


La respuesta a nuestra solicitud se mostrara en la parte inferior derecha.


De igual manera haremos con los demás métodos.


Podemos ver la respuesta en formato XML haciendo clic en la pestaña XML ubicada en la parte inferior.





TEST Servicio Web SOAP utilizando soapUI

Otra forma de probar nuestro servicio SOAP es utilizando SoapUI, el cual podemos descargarlo desde aquí.
La instalación es sencilla, solo seguir los siguientes pasos, tal como se muestra en las siguientes imágenes:










Seleccionar el menú “File” y escoger la opción “New soapUI Project”, tal como se muestra en la figura adjunta.


Luego colocar la ruta del servicio que queremos probar y dar clic en “OK”.


Seleccionar el método a probar y dar doble clic en “Request 1”, luego al lado derecho aparecerá una ventana como se muestra en la imagen.


Colocar los datos que queremos ingresar y dar clic en el icono de “play” color verde ubicado en la parte superior.


Realizando Pruebas Unitarias para probar Servicio Web SOAP

También podemos realizar nuestras propias pruebas unitarias para probar un Servicio Web SOAP.
Siguiendo el ejemplo de “MiTienda”, agregaremos un proyecto “Prueba” (TEST) a la solución que tenemos.



Ahora agregaremos la referencia al servicio. Dar clic derecho en el proyecto “ClienteTEST” y escoger la opción “Agregar referencia de servicio”.


Colocar la dirección del servicio, dar clic en el botón “IR” y seleccionar el contrato.
Luego colocar un nombre y dar clic en “Aceptar”.


Agregar a nuestro proyecto “ClientesTEST” la clase “Cliente.cs”, con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClientesTEST
{
    public class Cliente
    {        
        public int Co_Cliente { get; set; }     
        public string No_Cliente { get; set; }
        public string Nu_Documento { get; set; }        
        public string Tx_Direccion { get; set; }        
        public Distrito Distrito { get; set; }
    }
}

Agregar a nuestro proyecto “ClientesTEST” la clase “Distrito.cs”, con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClientesTEST
{
    public class Distrito
    {
        public int Co_Distrito { get; set; }
        public string No_Distrito { get; set; }
    }
}

Cambiar de nombre al archivo “UnitTest1.cs” por “ClientesTEST.cs”.
Editar y colocar el siguiente código:

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ClientesTEST
{
    [TestClass]
    public class ClientesTest
    {
        [TestMethod]
        public void TestCrearCliente()
        {
            // 1. Instanciar el objeto a probar
            ClientesWS.ClientesClient proxy = new ClientesWS.ClientesClient();
            
            string No_Cliente = "Jorge Risco";            
            string Nu_Documento = "70478704";
            string Tx_Direccion = "Av. Primavera 4578";
            Distrito Distrito = new Distrito()
            {
                Co_Distrito = 1,
                No_Distrito = "Santiago de Surco"
            };
            // 2. Invocar el metodo a probar del objeto
            ClientesWS.Cliente clienteCreado = proxy.CrearCliente(No_Cliente, Nu_Documento, Tx_Direccion, Distrito.Co_Distrito);
            
            // 3. Validacion del resultado esperado
            Assert.AreEqual(clienteCreado.No_Cliente, "Jorge Risco");
            Assert.AreEqual(clienteCreado.Nu_Documento, "70478704");
            Assert.AreEqual(clienteCreado.Tx_Direccion, "Av. Primavera 4578");
            Assert.AreEqual(clienteCreado.Distrito.Co_Distrito, 1);
        }

        [TestMethod]
        public void TestObtenerCliente()
        {
            // 1. Instanciar el objeto a probar
            ClientesWS.ClientesClient proxy = new ClientesWS.ClientesClient();

            // 2. Invocar el metodo a probar del objeto
            ClientesWS.Cliente clienteObtenido = proxy.ObtenerCliente(3);

            // 3. Validacion del resultado esperado
            Assert.AreEqual(clienteObtenido.No_Cliente, "Jorge Risco");
            Assert.AreEqual(clienteObtenido.Nu_Documento, "70478704");
            Assert.AreEqual(clienteObtenido.Tx_Direccion, "Av. Primavera 4578");
            Assert.AreEqual(clienteObtenido.Distrito.Co_Distrito, 1);
        }

        [TestMethod]
        public void TestModificarCliente()
        {
            // 1. Instanciar el objeto a probar
            ClientesWS.ClientesClient proxy = new ClientesWS.ClientesClient();

            int Co_Cliente = 3;
            string No_Cliente = "Jorge Risco Ganoza";
            string Nu_Documento = "70112233";
            string Tx_Direccion = "Av. Caminos del Inca 2544";
            Distrito Distrito = new Distrito()
            {
                Co_Distrito = 1,
                No_Distrito = "Santiago de Surco"
            };
            // 2. Invocar el metodo a probar del objeto
            ClientesWS.Cliente clienteModificado = proxy.ModificarCliente(Co_Cliente, No_Cliente, Nu_Documento, Tx_Direccion, Distrito.Co_Distrito);

            // 3. Validacion del resultado esperado
            Assert.AreEqual(clienteModificado.Co_Cliente, 3);
            Assert.AreEqual(clienteModificado.No_Cliente, "Jorge Risco Ganoza");
            Assert.AreEqual(clienteModificado.Nu_Documento, "70112233");
            Assert.AreEqual(clienteModificado.Tx_Direccion, "Av. Caminos del Inca 2544");
            Assert.AreEqual(clienteModificado.Distrito.Co_Distrito, 1);
        }

        [TestMethod]
        public void TestEliminarCliente()
        {
            // 1. Instanciar el objeto a probar
            ClientesWS.ClientesClient proxy = new ClientesWS.ClientesClient();

            // 2. Invocar el metodo a probar del objeto
            ClientesWS.Cliente clienteAEliminar = proxy.ObtenerCliente(1);
            proxy.EliminarCliente(clienteAEliminar.Co_Cliente);

            // 3. Validacion del resultado esperado
            ClientesWS.Cliente clienteEliminado = proxy.ObtenerCliente(1);
            Assert.IsNull(clienteEliminado);            
        }

        [TestMethod]
        public void TestListarClientes()
        {
            // 1. Instanciar el objeto a probar
            ClientesWS.ClientesClient proxy = new ClientesWS.ClientesClient();

            // 2. Invocar el metodo a probar del objeto            
            ICollection<ClientesWS.Cliente> listaClientes = proxy.ListarClientes();

            // 3. Validacion del resultado esperado
            Assert.AreEqual(listaClientes.Count, 2);
        }
    }
}

Para ejecutar todas las pruebas dar clic derecho sobre el nombre de la clase y escoger la opción “Ejecutar pruebas”.


En la parte inferior nos aparecerá el resultado de las pruebas, donde podremos verificar que las operaciones de nuestro servicio funcionan correctamente.



Realizando Pruebas Unitarias para probar Servicio Web REST

Siguiendo el ejemplo de “MiTienda”, agregaremos un nuevo proyecto “Prueba” (TEST) a la solución que tenemos para probar el servicio “Productos” que desarrollamos anteriormente.


Agregar a nuestro proyecto “ProductosTEST” la clase “Producto.cs”.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProductosTEST
{
    public class Producto
    {
        public string Co_Producto { get; set; }
        public string No_Producto { get; set; }
        public decimal Ss_Precio { get; set; }
        public int Qt_Stock { get; set; }
    }
}

Luego, dentro del proyecto “ProductosTEST”, dar clic derecho en “References” y escoger la opción “Agregar referencia”.
Elegir la opción que se muestra en la siguiente imagen:


Ahora, cambiar de nombre al archivo “UnitTest1.cs” por “ProductosTEST.cs”.
Editar y colocar el siguiente código:

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;
using System.IO;
using System.Web.Script.Serialization;

namespace ProductosTEST
{
    [TestClass]
    public class ProductosTest
    {
        [TestMethod]
        public void TestCrearProducto()
        {
            // Prueba de creacion de producto via HTTP POST
            string postdata = "{\"No_Producto\":\"LAPTOP HP PAVILION\",\"Ss_Precio\":\"2599.99\",\"Qt_Stock\":\"150\"}";
            byte[] data = Encoding.UTF8.GetBytes(postdata);
            HttpWebRequest req = (HttpWebRequest)WebRequest
                .Create("http://localhost:32641/Productos.svc/Productos");
            req.Method = "POST";
            req.ContentLength = data.Length;
            req.ContentType = "application/json";
            var reqStream = req.GetRequestStream();
            reqStream.Write(data, 0, data.Length);
            var res = (HttpWebResponse)req.GetResponse();
            StreamReader reader = new StreamReader(res.GetResponseStream());
            string productoJson = reader.ReadToEnd();
            JavaScriptSerializer js = new JavaScriptSerializer();
            Producto productoCreado = js.Deserialize<Producto>(productoJson);
            Assert.AreEqual("LAPTOP HP PAVILION", productoCreado.No_Producto);
            Assert.AreEqual(2599.99m, productoCreado.Ss_Precio);
            Assert.AreEqual(150, productoCreado.Qt_Stock);
        }

        [TestMethod]
        public void TestObtenerProducto()
        {
            // Prueba de obtencion de producto via HTTP GET
            HttpWebRequest req = (HttpWebRequest)WebRequest
                .Create("http://localhost:32641/Productos.svc/Productos/1");
            req.Method = "GET";
            HttpWebResponse res = (HttpWebResponse)req.GetResponse();
            StreamReader reader = new StreamReader(res.GetResponseStream());
            string productoJson = reader.ReadToEnd();
            JavaScriptSerializer js = new JavaScriptSerializer();
            Producto productoObtenido = js.Deserialize<Producto>(productoJson);
            Assert.AreEqual("TV LCD 32 PULG.", productoObtenido.No_Producto);
            Assert.AreEqual(1199.99m, productoObtenido.Ss_Precio);
            Assert.AreEqual(100, productoObtenido.Qt_Stock);
        }

        [TestMethod]
        public void TestModificarProducto()
        {
            // Prueba de modificacion de producto via HTTP PUT
            string postdata = "{\"Co_Producto\":\"1\",\"No_Producto\":\"TV LCD 40 PULG.\",\"Ss_Precio\":\"2699.99\",\"Qt_Stock\":\"250\"}";
            byte[] data = Encoding.UTF8.GetBytes(postdata);
            HttpWebRequest req = (HttpWebRequest)WebRequest
                .Create("http://localhost:32641/Productos.svc/Productos");
            req.Method = "PUT";
            req.ContentLength = data.Length;
            req.ContentType = "application/json";
            var reqStream = req.GetRequestStream();
            reqStream.Write(data, 0, data.Length);
            var res = (HttpWebResponse)req.GetResponse();
            StreamReader reader = new StreamReader(res.GetResponseStream());
            string productoJson = reader.ReadToEnd();
            JavaScriptSerializer js = new JavaScriptSerializer();
            Producto productoModificado = js.Deserialize<Producto>(productoJson);
            Assert.AreEqual("TV LCD 40 PULG.", productoModificado.No_Producto);
            Assert.AreEqual(2699.99m, productoModificado.Ss_Precio);
            Assert.AreEqual(250, productoModificado.Qt_Stock);
        }

        [TestMethod]
        public void TestEliminarProducto()
        {
            // Prueba de eliminacion de producto via HTTP GET
            HttpWebRequest req = (HttpWebRequest)WebRequest
                .Create("http://localhost:32641/Productos.svc/Productos/2");
            req.Method = "DELETE";
            HttpWebResponse res = (HttpWebResponse)req.GetResponse();

            // Prueba de obtencion de producto via HTTP GET
            HttpWebRequest req2 = (HttpWebRequest)WebRequest
                .Create("http://localhost:32641/Productos.svc/Productos/2");
            req2.Method = "GET";
            HttpWebResponse res2 = (HttpWebResponse)req2.GetResponse();
            StreamReader reader2 = new StreamReader(res2.GetResponseStream());
            string productoJson2 = reader2.ReadToEnd();
            JavaScriptSerializer js2 = new JavaScriptSerializer();
            Producto productoEliminado = js2.Deserialize<Producto>(productoJson2);
            Assert.IsNull(productoEliminado);
        }

        [TestMethod]
        public void TestListarProductos()
        {
            // Prueba de obtencion de producto via HTTP LIST
            HttpWebRequest req = (HttpWebRequest)WebRequest
                .Create("http://localhost:32641/Productos.svc/Productos");
            req.Method = "GET";
            HttpWebResponse res = (HttpWebResponse)req.GetResponse();
            StreamReader reader = new StreamReader(res.GetResponseStream());
            string productosJson = reader.ReadToEnd();
            JavaScriptSerializer js = new JavaScriptSerializer();
            List<Producto> productosObtenidos = js.Deserialize<List<Producto>>(productosJson);
            Assert.AreEqual(2, productosObtenidos.Count);
        }
    }
}
Finalmente ejecutar todas las pruebas para verificar que todas las operaciones de nuestro servicio “Productos” funcionen correctamente.


Eso es todo por ahora, espero les haya servido el tema de hoy.

Gracias !!!

Creación de Servicio Web REST CRUD


Siguiendo nuestro ejemplo de “MiTienda”, crearemos ahora un servicio REST para productos. Para lo cual, en nuestra base de datos agregaremos la tabla “Productos”, con la siguiente estructura:


Ahora, en nuestra solución .NET agregaremos un nuevo proyecto.


Cambiaremos de nombre al servicio “Service1” por “Productos”. De igual manera cambiaremos “IService1” por “IProductos”. Tambien agregaremos al proyecto las carpetas “Dominio” y “Persistencia”.

Luego crearemos la clase “Producto.cs” dentro de la carpeta “Dominio” con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;

namespace ProductosService.Dominio
{
    [DataContract]
    public class Producto
    {
        [DataMember]
        public string Co_Producto { get; set; }
        [DataMember]
        public string No_Producto { get; set; }
        [DataMember]
        public decimal Ss_Precio { get; set; }
        [DataMember]
        public int Qt_Stock { get; set; }
    }
}

Luego crearemos la clase “Conexion.cs” dentro de la carpeta “Persistencia”, con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ProductosService.Persistencia
{
    public class Conexion
    {
        public static string Cadena
        {
            get
            {
                return "Data Source=(local);Initial Catalog=BD_Tienda;Integrated Security=SSPI;";
            }
        }
    }
}

Luego dentro de la misma carpeta adicionaremos la clase “ProductoDAO”, con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ProductosService.Dominio;
using System.Data.SqlClient;

namespace ProductosService.Persistencia
{
    public class ProductoDAO
    {
        public Producto Crear(Producto productoACrear)
        {
            Producto productoCreado = null;
            productoACrear.Co_Producto = ObtenerMaximoId().ToString();
            string sql = "INSERT INTO t_producto VALUES (@Co_Producto, @No_Producto, @Ss_Precio, @Qt_Stock)";
            using (SqlConnection con = new SqlConnection(Conexion.Cadena))
            {
                con.Open();
                using (SqlCommand com = new SqlCommand(sql, con))
                {
                    com.Parameters.Add(new SqlParameter("@Co_Producto", productoACrear.Co_Producto));
                    com.Parameters.Add(new SqlParameter("@No_Producto", productoACrear.No_Producto));
                    com.Parameters.Add(new SqlParameter("@Ss_Precio", productoACrear.Ss_Precio));
                    com.Parameters.Add(new SqlParameter("@Qt_Stock", productoACrear.Qt_Stock));
                    com.ExecuteNonQuery();
                }
            }
            productoCreado = Obtener(productoACrear.Co_Producto);
            return productoCreado;
        }

        public int ObtenerMaximoId()
        {
            int id = 0;
            string sql = "SELECT max(Co_Producto) FROM t_producto";
            using (SqlConnection con = new SqlConnection(Conexion.Cadena))
            {
                con.Open();
                using (SqlCommand com = new SqlCommand(sql, con))
                {
                    try
                    {
                        id = (int)com.ExecuteScalar();
                    }
                    catch (Exception e) { }
                }
            }
            return id + 1;
        }

        public Producto Obtener(string Co_Producto)
        {
            Producto productoEncontrado = null;
            string sql = "SELECT * FROM t_producto WHERE Co_Producto = @Co_Producto";
            using (SqlConnection con = new SqlConnection(Conexion.Cadena))
            {
                con.Open();
                using (SqlCommand com = new SqlCommand(sql, con))
                {
                    com.Parameters.Add(new SqlParameter("@Co_Producto", Co_Producto));
                    using (SqlDataReader resultado = com.ExecuteReader())
                    {
                        if (resultado.Read())
                        {
                            productoEncontrado = new Producto()
                            {
                                Co_Producto = resultado["Co_Producto"].ToString(),
                                No_Producto = (string)resultado["No_Producto"],
                                Ss_Precio = (decimal)resultado["Ss_Precio"],
                                Qt_Stock = (int)resultado["Qt_Stock"]
                            };
                        }
                    }
                }
            }
            return productoEncontrado;
        }

        public Producto Modificar(Producto productoAModificar)
        {
            Producto productoModificado = null;
            string sql = "UPDATE t_producto SET No_Producto = @No_Producto, Ss_Precio = @Ss_Precio, Qt_Stock = @Qt_Stock WHERE Co_Producto = @Co_Producto";
            using (SqlConnection con = new SqlConnection(Conexion.Cadena))
            {
                con.Open();
                using (SqlCommand com = new SqlCommand(sql, con))
                {
                    com.Parameters.Add(new SqlParameter("@No_Producto", productoAModificar.No_Producto));
                    com.Parameters.Add(new SqlParameter("@Ss_Precio", productoAModificar.Ss_Precio));
                    com.Parameters.Add(new SqlParameter("@Qt_Stock", productoAModificar.Qt_Stock));                    
                    com.Parameters.Add(new SqlParameter("@Co_Producto", productoAModificar.Co_Producto));
                    com.ExecuteNonQuery();
                }
            }
            productoModificado = Obtener(productoAModificar.Co_Producto);
            return productoModificado;
        }

        public void Eliminar(string Co_Producto)
        {
            string sql = "DELETE FROM t_producto WHERE Co_Producto = @Co_Producto";
            using (SqlConnection con = new SqlConnection(Conexion.Cadena))
            {
                con.Open();
                using (SqlCommand com = new SqlCommand(sql, con))
                {
                    com.Parameters.Add(new SqlParameter("@Co_Producto", Co_Producto));
                    com.ExecuteNonQuery();
                }
            }
        }

        public List<Producto> ListarProductos()
        {
            List<Producto> productos = new List<Producto>();
            string sql = "SELECT * FROM t_producto";
            using (SqlConnection con = new SqlConnection(Conexion.Cadena))
            {
                con.Open();
                using (SqlCommand com = new SqlCommand(sql, con))
                {
                    using (SqlDataReader resultado = com.ExecuteReader())
                    {
                        while (resultado.Read())
                        {
                            productos.Add(new Producto()
                            {
                                Co_Producto = resultado["Co_Producto"].ToString(),
                                No_Producto = (string)resultado["No_Producto"],
                                Ss_Precio = (decimal)resultado["Ss_Precio"],
                                Qt_Stock = (int)resultado["Qt_Stock"]
                            });
                        }
                    }
                }
            }
            return productos;
        }
    }
}

Ahora editaremos el archivo “Productos.svc” con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using ProductosService.Persistencia;
using ProductosService.Dominio;

namespace ProductosService
{
    public class Productos : IProductos
    {
        private ProductoDAO dao = new ProductoDAO();

        public Producto CrearProducto(Producto productoACrear)
        {
            return dao.Crear(productoACrear);
        }

        public Producto ObtenerProducto(string Co_Producto)
        {
            return dao.Obtener(Co_Producto);
        }

        public Producto ModificarProducto(Producto productoAModificar)
        {
            return dao.Modificar(productoAModificar);
        }

        public void EliminarProducto(string Co_Producto)
        {
            dao.Eliminar(Co_Producto);
        }

        public List<Producto> ListarProductos()
        {
            return dao.ListarProductos();
        }
    }
}

Luego editaremos el archivo “IProductos.cs” con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using ProductosService.Dominio;

namespace ProductosService
{
    [ServiceContract]
    public interface IProductos
    {
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "Productos", ResponseFormat = WebMessageFormat.Json)]
        Producto CrearProducto(Producto productoACrear);

        [OperationContract]
        [WebInvoke(Method = "GET", UriTemplate = "Productos/{Co_Producto}", ResponseFormat = WebMessageFormat.Json)]
        Producto ObtenerProducto(string Co_Producto);

        [OperationContract]
        [WebInvoke(Method = "PUT", UriTemplate = "Productos", ResponseFormat = WebMessageFormat.Json)]
        Producto ModificarProducto(Producto productoAModificar);

        [OperationContract]
        [WebInvoke(Method = "DELETE", UriTemplate = "Productos/{Co_Producto}", ResponseFormat = WebMessageFormat.Json)]
        void EliminarProducto(string Co_Producto);

        [OperationContract]
        [WebInvoke(Method = "GET", UriTemplate = "Productos", ResponseFormat = WebMessageFormat.Json)]
        List<Producto> ListarProductos();
    }
}

Ahora, dar clic derecho sobre el archivo “Productos.svc” y escoger la opción “Ver Marcado”, y adicionar la última línea que se muestra en la siguiente imagen:


Insertar algunos registros en nuestra tabla productos para poder probar el listado de productos.


Ahora sobre el mismo archivo “Productos.svc” dar clic derecho y escoger la opción “Ver en el Explorador”.


En la pantalla que nos aparecerá, agregar al final de la url lo siguiente: /Productos/1


Luego probar con: /Productos


Podemos verificar la respuesta generada en formato JSON.

Espero que este tema les haya sido de utilidad, en el próximo tema veremos como realizar pruebas unitarias para un servicio REST, siguiendo este mismo ejemplo.

Gracias !!!

lunes, 7 de octubre de 2013

Creación de Servicio Web SOAP


En esta ocasión, veremos cómo crear un servicio SOAP en .NET utilizando Hibernate para conectarnos a una base de datos SQL Server.

Lo primero que haremos será crear un nuevo proyecto, luego buscar la opción Visual C#, seleccionar WCF y luego escoger la opción “Aplicación de servicios WCF” y colocar un nombre tal como se muestra en la siguiente imagen:


Cambiar de nombre al servicio “Service1.svc” que se crea por defecto. Para este ejemplo colocaremos el nombre “Clientes.svc”. De igual manera cambiaremos “IService1.cs” por “IClientes.cs”.

Agregar al proyecto las carpetas “Dominio” y “Persistencia”. Adicionar a la solución la carpeta “Librerias” la cual contendrá los archivos “Iesi.Collections.dll” y “NHibernate.dll”. Usar el explorador de Windows para ir a la carpeta donde se encuentra nuestro proyecto y crear una carpeta llamada "Librerias" que contenga los archivos que incluiremos en la librería, luego arrastrarlos hacia la carpeta “Librerias” que se encuentra en nuestra solución. Deberíamos tener una estructura como se muestra en la siguiente imagen:


Luego dentro de nuestro proyecto dar clic derecho sobre la opción “References” y escoger la opción “Agregar Referencia”. Escoger la pestaña “Examinar” y seleccionar los archivos que colocamos en la carpeta “Librerias”.


Ahora crearemos nuestra base de datos, la cual llamaremos BD_Tienda. Debería quedar de la siguiente manera:


Ahora crearemos la clase “Conexión.cs” dentro de la carpeta “Persistencia”. Con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ClientesService.Persistencia
{
    public class Conexion
    {
        public static string Cadena()
        {
            return "Data Source=(local);Initial Catalog=BD_Tienda;Integrated Security=SSPI;";
        }
    }
}

Luego la clase “NHibernateHelper.cs” con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NHibernate;
using NHibernate.Cfg;

namespace ClientesService.Persistencia
{
    public class NHibernateHelper
    {
        private static ISessionFactory _Fabrica;

        private static ISessionFactory Fabrica
        {
            get
            {
                if (_Fabrica == null)
                {
                    var _Conf = new Configuration();
                    _Conf.SetProperty("connection.provider", "NHibernate.Connection.DriverConnectionProvider");
                    _Conf.SetProperty("connection.driver_class", "NHibernate.Driver.SqlClientDriver");
                    _Conf.SetProperty("connection.connection_string", Conexion.Cadena());
                    _Conf.SetProperty("adonet.batch_size", "10");
                    _Conf.SetProperty("show_sql", "true");
                    _Conf.SetProperty("dialect", "NHibernate.Dialect.MsSql2000Dialect");
                    _Conf.SetProperty("command_timeout", "60");
                    _Conf.SetProperty("query.substitutions", "true 1, false 0, yes 'Y', no 'N'");
                    _Conf.AddAssembly(typeof(NHibernateHelper).Assembly);
                    _Fabrica = _Conf.BuildSessionFactory();
                }
                return _Fabrica;
            }
        }

        public static ISession ObtenerSession()
        {
            return Fabrica.OpenSession();
        }

        public static void CerrarFabrica()
        {
            _Fabrica = null;
        }
    }
}

Luego crear la clase “BaseDAO” con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NHibernate;

namespace ClientesService.Persistencia
{
    public class BaseDAO<Entidad, Id>
    {
        public Entidad Crear(Entidad entidad)
        {
            using (ISession session = NHibernateHelper.ObtenerSession())
            {
                session.Save(entidad);
                session.Flush();
            }
            return entidad;
        }

        public Entidad Obtener(Id id)
        {
            using (ISession session = NHibernateHelper.ObtenerSession())
            {
                return session.Get<Entidad>(id);
            }
        }

        public Entidad Modificar(Entidad entidad)
        {
            using (ISession session = NHibernateHelper.ObtenerSession())
            {
                session.Update(entidad);
                session.Flush();
            }
            return entidad;
        }

        public void Eliminar(Entidad entidad)
        {
            using (ISession session = NHibernateHelper.ObtenerSession())
            {
                session.Delete(entidad);
                session.Flush();
            }
        }

        public ICollection<Entidad> ListarTodos()
        {
            using (ISession session = NHibernateHelper.ObtenerSession())
            {
                ICriteria busqueda = session.CreateCriteria(typeof(Entidad));
                return busqueda.List<Entidad>();
            }
        }
    }
}

Ahora crearemos la clase “Distrito.cs” dentro de la carpeta “Dominio”, tal como sigue:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;

namespace ClientesService.Dominio
{
    [DataContract]
    public class Distrito
    {
        [DataMember]
        public int Co_Distrito { get; set; }
        [DataMember]
        public string No_Distrito { get; set; }
    }
}

Luego la clase “Cliente.cs” de la siguiente manera:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;

namespace ClientesService.Dominio
{
    [DataContract]
    public class Cliente
    {
        [DataMember]
        public int Co_Cliente { get; set; }
        [DataMember]
        public string No_Cliente { get; set; }
        [DataMember]
        public string Nu_Documento { get; set; }
        [DataMember]
        public string Tx_Direccion { get; set; }
        [DataMember]
        public Distrito Distrito { get; set; }
    }
}

Ahora crearemos dentro de la carpeta “Persistencia” la clase “ClienteDAO”, tal como se muestra a continuación:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ClientesService.Dominio;

namespace ClientesService.Persistencia
{
    public class ClienteDAO : BaseDAO<Cliente, int>
    {
    }
}

Y ahora “DistritoDAO”:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ClientesService.Dominio;

namespace ClientesService.Persistencia
{
    public class DistritoDAO : BaseDAO<Distrito, int>
    {
    }
}

Ahora editar el archivo “Clientes.svc” y colocar el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using ClientesService.Persistencia;
using ClientesService.Dominio;

namespace ClientesService
{
    public class Clientes : IClientes
    {
        private ClienteDAO clienteDAO = null;
        private ClienteDAO ClienteDAO
        {
            get
            {
                if (clienteDAO == null)
                    clienteDAO = new ClienteDAO();
                return clienteDAO;
            }
        }

        private DistritoDAO distritoDAO = null;
        private DistritoDAO DistritoDAO
        {
            get
            {
                if (distritoDAO == null)
                    distritoDAO = new DistritoDAO();
                return distritoDAO;
            }
        }

        public Cliente CrearCliente(string NoCliente, string NuDocumento, string TxDireccion, int CoDistrito)
        {
            Distrito distritoExistente = DistritoDAO.Obtener(CoDistrito);
            Cliente clienteACrear = new Cliente()
            {
                No_Cliente = NoCliente,
                Nu_Documento = NuDocumento,
                Tx_Direccion = TxDireccion,
                Distrito = distritoExistente 
            };
            return ClienteDAO.Crear(clienteACrear);
        }

        public Cliente ObtenerCliente(int CoCliente)
        {
            return ClienteDAO.Obtener(CoCliente);
        }

        public Cliente ModificarCliente(int CoCliente, string NoCliente, string NuDocumento, string TxDireccion, int CoDistrito)
        {
            Distrito distritoExistente = DistritoDAO.Obtener(CoDistrito);
            Cliente clienteAModificar = new Cliente()
            {
                Co_Cliente = CoCliente,
                No_Cliente = NoCliente,
                Nu_Documento = NuDocumento,
                Tx_Direccion = TxDireccion,
                Distrito = distritoExistente
            };
            return ClienteDAO.Modificar(clienteAModificar);
        }

        public void EliminarCliente(int CoCliente)
        {
            Cliente clienteExistente = ClienteDAO.Obtener(CoCliente);
            ClienteDAO.Eliminar(clienteExistente);
        }

        public List<Cliente> ListarClientes()
        {
            return ClienteDAO.ListarTodos().ToList();
        }
    }
}

Luego editar el archivo “IClientes.cs” con el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using ClientesService.Dominio;

namespace ClientesService
{
    [ServiceContract]
    public interface IClientes
    {
        [OperationContract]
        Cliente CrearCliente(string NoCliente, string NuDocumento, string TxDireccion, int CoDistrito);

        [OperationContract]
        Cliente ObtenerCliente(int CoCliente);

        [OperationContract]
        Cliente ModificarCliente(int CoCliente, string NoCliente, string NuDocumento, string TxDireccion, int CoDistrito);

        [OperationContract]
        void EliminarCliente(int CoCliente);

        [OperationContract]
        List<Cliente> ListarClientes();
    }
}

Por ultimo crearemos los archivos XML en la carpeta “Dominio”.
A continuación el archivo “Cliente.hbm.xml”:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="ClientesService"
                   namespace="ClientesService.Dominio"
                   default-lazy="false">
    <class name="Cliente" table="t_cliente">
        <id name="Co_Cliente" column="Co_Cliente">
            <generator class="increment" />
        </id>
        <property name="No_Cliente" column="No_Cliente" />
        <property name="Nu_Documento" column="Nu_Documento" />
        <property name="Tx_Direccion" column="Tx_Direccion" />
        <many-to-one name="Distrito" column=" Co_Distrito" />
    </class>
</hibernate-mapping>

Ahora el archivo “Distrito.hbm.xml”

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="ClientesService"
                   namespace="ClientesService.Dominio"
                   default-lazy="false">
    <class name="Distrito" table="t_distrito">
        <id name="Co_Distrito" column="Co_Distrito">
            <generator class="increment" />
        </id>
        <property name="No_Distrito" column="No_Distrito" />
    </class>
</hibernate-mapping>

Es importante escoger la opción de Contenido: “Recurso Incrustado” en las propiedades de ambos archivos, como se muestra en la siguiente figura


Ahora demos clic derecho sobre nuestro servicio “Clientes.svc” y escojamos la opción “Ver en el explorador”.


Nos deberia salir una pantalla similar a la que se muestra en la siguiente imagen:


El puerto puede variar, dependiendo de la configuración de las propiedades del proyecto que tengamos, a continuación se muestra como cambiar el puerto por defecto.




Eso es todo por ahora, espero que les haya servido el tema de hoy, mas adelante veremos como probar un Servicio Web SOAP siguiendo este mismo ejemplo.

Gracias !!!