Detalles del caso

Acabamos de incorporarnos al equipo de desarrollo en un nuevo cliente. En nuestro primer trabajo nos ha tocado crear un cliente que utilice el API del agenda de esta empresa. El WebAPI sobre el que tenemos que trabajar se encuentra alojado en AZURE, y podemos acceder a él a través de este enlace:

 http://agendaexampleapi.azurewebsites.net/

La API de la agenda tiene configurado un C R U D (create, read, update, and delete) que permite las siguientes operaciones:

 

¿Qué es Web API?

ASP.NET Web API es un framework para construir APIs (Application Programming Interfaces), construida sobre el .NET Framework. Es una especie de librería más liviana y simple que WCF (Windows Communication Foundation) orientada completamente al protocolo HTTP, que permite construir servicios web sin estar sujetos a un estilo o arquitectura definido (por ejemplo REST o RPC).

ASP.NET Web API es de código libre, y está disponible al público en general en un repositorio GIT en Codeplex, para ser consultado y también para realizar contribuciones. Esta publicado bajo la Apache License, Version 2.0.
Web API es considerada como el futuro de ASP.NET, pues refuerza el uso de estándares HTTP, y unifica las características esenciales para el desarrollo de servicios web que el MVC Framework y WCF proveen, de una forma más compleja.

 

¿Cuáles son las ventajas de Web API?

.NET Web API presenta las siguientes ventajas para el desarrollo de APIs sobre HTTP:

  • Se acopla a los estándares HTTP, siendo la mejor implementación por parte de Microsoft de las especificaciones del protocolo HTTP (RFC 2616).
  • Modelo de programación HTTP moderno, pues permite el acceso directo a las solicitudes y respuestas HTTP, a través de tipos de objetos especializados.
  • Soporte completo de rutas, lo que permite especificar las acciones a ejecutar, así como parámetros y restricciones, sin necesidad de modulos adicionales de sobreescritura de URL.
  • Soporta negociación de contenido y media types, para que el cliente y el servidor puedan establecer el formato de los datos que la API recibirá y enviará en respuesta. Por defecto, Web API provee soporte para JSON, XML y formularios codificados como URL (URL-encoded form data), pero permite agregar tipos de datos personalizados, a traves de media formatters.
  • Conversión automática de datos a objetos, ya que los datos recibidos en las solicitudes HTTP son transformados a objetos .NET, y viceversa, para ser manipulados en las acciones de la API.
  • Filtros que sirven para añadir una capa extra de funcionalidades a las acciones, y son manejados como atributos, para facilitar su integración en las clases y métodos.
  • Mejora el desarrollo de pruebas unitarias, ya que muchas partes del framework pueden ser personalizadas y simuladas, al basarse en interfaces y clases genéricas que pueden ser extendidas.
  • Inversión de control y resolución de dependencias integrada y extensible, a través del patrón de localización de servicios, implementado mediante el “resolvedor de dependencias” del Framework.
  • Composición de consultas, basada en las convenciones de URL de OData, con solo implementarla interfaz IQueryable<T>.
  • Configuración a través de código, para evitar sobrecargar los archivos de configuración XML.
  • Asíncrono de pies a cabeza, para permitir recibir más solicitudes HTTP, mientras se espera que otras terminen de ser procesadas.
  • Puede ser auto-hospedado (self-hosted), por lo que no está atado al uso del servidor web IIS.

Creación del cliente

Pasos: [File] > [New] > [Project…] >> [Installed] > [Visual C#] > [Web] > [ASP.NET Web Application (.Net Framework)] > [Definimos el nombre de la aplicación/solución] > [OK] >> [Template MVC] > [OK]

 

PREPARACION DEL ENTORNO

Para el desarrollo de este proyecto, necesitaremos instalar la ultima version de estos dos modulos NuGet. El primero permite a la aplicación comunicarse con el API. El segundo, facilita la manipulacion del contenido JSON recibido como respuesta del API.

Microsoft.AspNet.WebApi.Client
Newtonsoft.Json

 

 

Pasos: [En el panel de la derecha (Solution Explorer)] > [Click derecha sobre la aplicación (Agenda Example MVC)] > [Manage NuGet Packages…] > [Browse] > [Utiliza el campo de busqueda para encontrar e instalar los NuGets necesarios]

 

EL MODELO

En la carpeta Modelo, tendremos que crear dos clases. La primera se llamara Contact y contendra la definición de las propiedades del objeto Contacto.

 


Pasos: [En el panel de la derecha (Solution Explorer)] > [En la aplicación (Agenda Example MVC)] > [Sobre la carpeta (Models)] > [Click derecha] > [Add] > [Class…]
El contenido de la clase Contact.cs:

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

namespace Agenda_Example_MVC.Models
{
    public class Contact
    {
        public int ContactId { get; set; }
        public string Nombre { get; set; }
        public string Apellidos { get; set; }
        public Nullable Fecha_Nacimiento { get; set; }
        public string Email { get; set; }
        public string Telefono { get; set; }
    }
}
//

La segunda se llamara ContactModel y contendra la definición de funciones asincronas que permitiran a la aplicacion interactuar con el API.

 


El contenido de la clase ContactModel.cs:

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

using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace Agenda_Example_MVC.Models
{
    public class ContactModel
    {
        private String UriApi;
        MediaTypeWithQualityHeaderValue mediaheader;
        public ContactModel()
        {
            //this.UriApi = "http://localhost:50809/"; // Local API
            this.UriApi = "http://agendaexampleapi.azurewebsites.net/"; // Azure API
            this.mediaheader = new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json");
        }

        public async Task<List> GetContacts()
        {
            using (HttpClient client = new HttpClient())
            {
                String petition = "api/Contacts";
                client.BaseAddress = new Uri(this.UriApi);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(mediaheader);
                HttpResponseMessage respuesta = await client.GetAsync(petition);
                if (respuesta.IsSuccessStatusCode)
                {
                    List cList = await respuesta.Content.ReadAsAsync<List>();
                    return cList;
                }
                else { return null; }
            }
        }

        public async Task GetContactByID(int id)
        {
            using (HttpClient client = new HttpClient())
            {
                String petition = "api/Contacts/" + id;
                client.BaseAddress = new Uri(this.UriApi);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(mediaheader);
                HttpResponseMessage respuesta = await client.GetAsync(petition);
                if (respuesta.IsSuccessStatusCode)
                {
                    Contact c = await respuesta.Content.ReadAsAsync();
                    return c;
                }
                else { return null; }
            }
        }

        public async Task AddContact(Contact c)
        {
            using (HttpClient client = new HttpClient())
            {
                String peticion = "api/Contacts";
                client.BaseAddress = new Uri(this.UriApi);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(mediaheader);
                await client.PostAsJsonAsync(peticion, c);
            }
        }

        public async Task EditContact(Contact c)
        {
            using (HttpClient client = new HttpClient())
            {
                String peticion = "api/Contacts";
                client.BaseAddress = new Uri(this.UriApi);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(mediaheader);
                await client.PutAsJsonAsync(peticion, c);
            }
        }

        public async Task DeleteContact(int id)
        {
            using (HttpClient client = new HttpClient())
            {
                String peticion = "api/Contacts/" + id;
                client.BaseAddress = new Uri(this.UriApi);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(mediaheader);
                await client.DeleteAsync(peticion);
            }
        }
    }
}
//

EL CONTROLADOR

El controlador contendra los ActionResult que haran de forma asincrona de puente entre el modelo y las vistas.
Pasos: [En el panel de la derecha (Solution Explorer)] > [En la aplicación (Agenda Example )] > [Sobre la carpeta (Controllers)] > [Click derecha] > [Add] > [Controller…]

 


El contenido del controller ContactsController.cs:

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

using System.Threading.Tasks;
using Agenda_Example_MVC.Models;

namespace Agenda_Example_MVC.Controllers
{
    public class ContactsController : Controller
    {
        ContactModel model;
        public ContactsController()
        {
            this.model = new ContactModel();
        }

        // GET: Contacts
        [AsyncTimeout(1000)]
        public async Task Index()
        {
            List cList = await model.GetContacts();
            return View(cList);
        }

        // GET: Contacts/Details/5
        public async Task Details(int id)
        {
            Contact c = await model.GetContactByID(id);
            return View(c);
        }

        // GET: Contacts/Create
        public async Task Create()
        {
            return View();
        }

        // POST: Contacts/Create
        [HttpPost]
        public async Task Create(Contact c)
        {
            try
            {
                await model.AddContact(c);
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        // GET: Contacts/Edit/5
        public async Task Edit(int id)
        {
            Contact c = await model.GetContactByID(id);
            return View(c);
        }

        // POST: Contacts/Edit/5
        [HttpPost]
        public async Task Edit(Contact c)
        {
            try
            {
                await model.EditContact(c);
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        // GET: Contacts/Delete/5
        public async Task Delete(int id)
        {
            await model.DeleteContact(id);
            return RedirectToAction("Index");
        }
    }
}
//

LA VISTA

En este ultimo paso, necesitaremos crear las vistas para ver la lista de contactos, para crear un contacto nuevo, para editar un contacto, y tambien una vista para ver los detalles de un contacto. Para simplificar el proceso lo haremos utilizando la funccion de escafolding.

 

PRUEBA FINAL DEL CLIENTE API

Con esto nuestro cliente API ya esta listo para ser usado. Vamos ha ejecutar nuestra agenda a ver como ha quedado.

 

Autor: Beniamin Gabriel Tecu

Curso: Microsoft MCSA Web Applications + Microsoft MCSD App Builder + Xamarin

Centro: Tajamar

Año académico: 2017 – 2018

GitHub: https://gitlab.com/BGTecu/Agenda-Example-WebAPI-MVC-Solution/

Linkedin: https://www.linkedin.com/in/bgtecu/

Leave a Comment

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