Browsing posts in: ASP.NET MVC

Consumiendo APIs desde ASP.NET MVC

Hoy me preguntó alguien que está aprendiendo ASP.NET MVC cuál era la mejor forma de consumir una API usando este framework; y no seré yo quien le responda cuál es la mejor forma, pero al menos era una pregunta que da para post, y no está mal que me critiquéis mi solución.

La API la vamos a consumir desde el servidor, ya que consumirla desde JavaScript parece cumbersome; aunque puede tener sus ventajas si tenemos restricciones por IP, aunque sea jugar sucio, al mismo tiempo podríamos estar exponiendo datos que no nos interesan en una aplicación cliente, o podríamos tener el caso en el que el cliente no tenga JS activado, caso tan raro como cierto.

Al lío: lo primero que vamos a hacer es instalar Unity en el proyecto Web de la solución si usamos MVC 5, o cantar algo si ya usamos ASP.NET vNext, ya que usa inyección de dependencias de por sí, por lo que no tendremos que preocuparnos por el contenedor.

Después de un paso obvio, vamos a definir la interfaz que será la fundación sobre la cual vamos a desarrollar nuestra propia abstracción sobre la API externa, pokeapi.co, en este ejemplo. Lo primero que haremos será definir una abstracción sobre HttpClient.

    public interface IHttpCommunicator
    {
        string BaseAddress { get; set; }

        Task<string> SendGetRequestAsync(string uri);
        Task<string> SendPostRequestAsync<T>(string uri, T data);
    }

Una vez tenemos una abstracción sobre el servicio de comunicación, tendremos que definir una abstracción sobre la API que usaremos, con los métodos que usaremos, donde inyectaremos el servicio HTTP y haremos uso de él:

    public interface IPokeApiClient
    {
        Task<Pokemon> GetPokemon(int id);

        Task<Ability> GetAbility(int id);

        Task<Models.Type> GetType(int id);
    }

Y, finalmente, inyectaremos la abstracción de la API externa en nuestros controladores, u otros servicios donde la vayamos a usar:

        [HttpPost]
        public async Task<ActionResult> Pokemon(int id)
        {
            var pokemon = await _pokeApiClient.GetPokemon(id);
            var vm = new PokemonViewModel
            {
                Pokemon = pokemon
            };
            return View(vm);
        }

Aunque no será la mejor implementación, proporciona una abstracción útil y sencilla sobre APIs de terceros, a pesar de provocar una dependencia temporal sobre definir la BaseAddress desde un punto externo, pero nos permite reutilizar el servicio de HTTP en cualquier parte.

La solución completa se puede encontrar en GitHub.