Este es un proyecto desarrollado para plataformas móviles y en este blog muestro de cómo consumir una api(Application Programming Interface) y poder utilizar la información. Implementando Repository Pattern y Model View ViewModel como buenas prácticas y tener un código limpio.
Aplicacion:
Proyecto desarrollado con .Net C# MAUI 8.0
Especificamos el PageContent con el que inicializaría la aplicación al ejecutarse:
using AppDragonBallZ.View;
namespace AppDragonBallZ
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new Characters());
}
}
}
View(Vista): Creamos un nuevo archivo ContentPage con el nombre 'Characters' que será la vista para mostrar los personajes.
Métodos de Interfaz: ICharactersRepository. En esta interfáz creamos 3 métodos y de los cuáles solo utilizaremos 2. Una interfaz define un contrato o conjunto de reglas que las clases que lo implementen deben cumplirlos.
using AppDragonBallZ.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppDragonBallZ.RepositoryPattern.IRepositoryPattern
{
public interface ICharactersRepository
{
Task Characters(string uriApi);
Task GetCharacterById(long characterId);
Task GetCharacterByName(string name);
}
}
Repository Pattern: CharactersRepository, implementa los métodos de la Interfaz: ICharactersRepository. Este contiene únicamente la lógica para consumir la api y poder deserealizarlo y retornar los datos para luego ser utilizado de acuerdo a la información que necesitaríamos visualizar en vista de la aplicación.
using AppDragonBallZ.Model;
using AppDragonBallZ.Model.DBZmodel;
using AppDragonBallZ.RepositoryPattern.IRepositoryPattern;
using AppDragonBallZ.Generico;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppDragonBallZ.RepositoryPattern
{
public class CharactersRepository : ICharactersRepository
{
public async Task Characters(string uriApi)
{
Respuesta respuesta = new();
try
{
string urlApi = uriApi;
var httpClient = new HttpClient();
Pagination pagination = new();
var response = await httpClient.GetAsync(urlApi);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject(content);
pagination = result;
}
respuesta.Data = pagination;
respuesta.Resultado = true;
respuesta.Mensaje = "Consulta exitosa";
}
catch (Exception ex)
{
respuesta.Resultado = false;
respuesta.Mensaje = "Error en método: Characters - > " + ex.Message.ToString();
}
return respuesta;
}
Apr 28, 2025 - 07:31
0
Este es un proyecto desarrollado para plataformas móviles y en este blog muestro de cómo consumir una api(Application Programming Interface) y poder utilizar la información. Implementando Repository Pattern y Model View ViewModel como buenas prácticas y tener un código limpio.
Aplicacion:
Proyecto desarrollado con .Net C# MAUI 8.0
Especificamos el PageContent con el que inicializaría la aplicación al ejecutarse:
Métodos de Interfaz: ICharactersRepository. En esta interfáz creamos 3 métodos y de los cuáles solo utilizaremos 2. Una interfaz define un contrato o conjunto de reglas que las clases que lo implementen deben cumplirlos.
Repository Pattern: CharactersRepository, implementa los métodos de la Interfaz: ICharactersRepository. Este contiene únicamente la lógica para consumir la api y poder deserealizarlo y retornar los datos para luego ser utilizado de acuerdo a la información que necesitaríamos visualizar en vista de la aplicación.
usingAppDragonBallZ.Model;usingAppDragonBallZ.Model.DBZmodel;usingAppDragonBallZ.RepositoryPattern.IRepositoryPattern;usingAppDragonBallZ.Generico;usingNewtonsoft.Json;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceAppDragonBallZ.RepositoryPattern{publicclassCharactersRepository:ICharactersRepository{publicasyncTask<Respuesta>Characters(stringuriApi){Respuestarespuesta=new();try{stringurlApi=uriApi;varhttpClient=newHttpClient();Paginationpagination=new();varresponse=awaithttpClient.GetAsync(urlApi);if(response.IsSuccessStatusCode){varcontent=awaitresponse.Content.ReadAsStringAsync();varresult=JsonConvert.DeserializeObject<Pagination>(content);pagination=result;}respuesta.Data=pagination;respuesta.Resultado=true;respuesta.Mensaje="Consulta exitosa";}catch(Exceptionex){respuesta.Resultado=false;respuesta.Mensaje="Error en método: Characters - > "+ex.Message.ToString();}returnrespuesta;}publicasyncTask<Respuesta>GetCharacterById(longcharacterId){Respuestarespuesta=new();try{stringurlApi=$"{Utilidades.UrlApiDBZ}/{characterId}";varhttpClient=newHttpClient();Charactercharacter=new();varresponse=awaithttpClient.GetAsync(urlApi);if(response.IsSuccessStatusCode){varcontent=awaitresponse.Content.ReadAsStringAsync();varresult=JsonConvert.DeserializeObject<Character>(content);character=result;}respuesta.Data=character;respuesta.Resultado=true;respuesta.Mensaje="Consulta exitosa";}catch(Exceptionex){respuesta.Resultado=false;respuesta.Mensaje="Error en método: GetCharacterById - > "+ex.Message.ToString();}returnrespuesta;}publicTask<Respuesta>GetCharacterByName(stringname){thrownewNotImplementedException();}}}
ViewModel(Modelo de Vista): CharactersViewModel.
Es una clase que encapsula la lógica de la interfaz de usuario, separándola de la vista (la interfaz de usuario XAML) y del modelo (los datos y la lógica de negocio). Esto facilita el desarrollo de aplicaciones más organizadas, testables y mantenibles.
usingAppDragonBallZ.RepositoryPattern;usingAppDragonBallZ.Generico;usingAppDragonBallZ.Model;usingAppDragonBallZ.Model.DBZmodel;usingAppDragonBallZ.RepositoryPattern.IRepositoryPattern;usingAppDragonBallZ.View;usingSystem.Windows.Input;namespaceAppDragonBallZ.ViewModel{publicclassCharactersViewModel:BaseViewModel{#regionVARIABLESprivatereadonlyICharactersRepositorycharactersRepository=newCharactersRepository();Pagination_pagination=new();publicboolIsRefreshing{get;set;}int_page=1;int_limit=10;bool_btnAnterior;bool_btnSiguiente;#endregion#regionOBJETOSpublicPaginationPagination{get{return_pagination;}set{SetValue(ref_pagination,value);}}publicboolBtnAnterior{get{return_btnAnterior;}set{SetValue(ref_btnAnterior,value);}}publicboolBtnSiguiente{get{return_btnSiguiente;}set{SetValue(ref_btnSiguiente,value);}}publicintPage{get{return_page;}set{SetValue(ref_page,value);}}publicintLimit{get{return_limit;}set{SetValue(ref_limit,value);}}#endregion#regionCONSTRUCTORpublicCharactersViewModel(INavigationnavigation){Navigation=navigation;BtnSiguiente=true;ObtenerPersonajes();}#endregion#regionPROCESOSpublicasyncvoidObtenerPersonajes(){try{Respuestarespuesta=awaitcharactersRepository.Characters($"{Utilidades.UrlApiDBZ}?page={Page}&limit={Limit}");if(respuesta.Resultado!=true){awaitDisplayAlert("Error",respuesta.Mensaje,"Ok");}Pagination=(Pagination)respuesta.Data;}catch(Exceptionex){awaitDisplayAlert("Error en método: ObtenerPersonajes -> ",ex.Message.ToString(),"Ok");}}publicasyncvoidSiguientePagina(Paginationpagination){try{Respuestarespuesta=awaitcharactersRepository.Characters(pagination.Links.Next.ToString());if(respuesta.Resultado!=true){awaitDisplayAlert("Error",respuesta.Mensaje,"Ok");}Pagination=(Pagination)respuesta.Data;ValidarEstadoBoton("Siguiente");}catch(Exceptionex){awaitDisplayAlert("Error en método: SiguientePagina -> ",ex.Message.ToString(),"Ok");}}publicasyncvoidAnteriorPagina(Paginationpagination){try{Respuestarespuesta=awaitcharactersRepository.Characters(pagination.Links.Previous.ToString());if(respuesta.Resultado!=true){awaitDisplayAlert("Error",respuesta.Mensaje,"Ok");}Pagination=(Pagination)respuesta.Data;ValidarEstadoBoton("Anterior");}catch(Exceptionex){awaitDisplayAlert("Error en método: AnteriorPagina -> ",ex.Message.ToString(),"Ok");}}publicasyncvoidValidarEstadoBoton(stringboton){try{if(boton.Equals("Siguiente")){BtnSiguiente=Pagination.Links.Next==null?false:true;BtnAnterior=Pagination.Links.Previous==null?false:true;}elseif(boton.Equals("Anterior")){BtnAnterior=Pagination.Links.Previous==null?false:true;BtnSiguiente=Pagination.Links.Next==null?false:true;}}catch(Exceptionex){awaitDisplayAlert("Error en método: ValidarEstadoBoton -> ",ex.Message.ToString(),"Ok");}}publicasyncvoidSeleccionarPersonaje(longcharacterId){try{awaitNavigation.PushAsync(newCharacterDetail(characterId));}catch(Exceptionex){awaitDisplayAlert("Error en método: SeleccionarPersonaje -> ",ex.Message.ToString(),"Ok");}}#endregion#regionCOMANDOSpublicICommandSiguientePaginaCommand=>newCommand<Pagination>(SiguientePagina);publicICommandAnteriorPaginaCommand=>newCommand<Pagination>(AnteriorPagina);publicICommandSeleccionarPersonajeCommand=>newCommand<long>(SeleccionarPersonaje);#endregion}}
Model(Modelo): En estas clases están todas las propiedades de acuerdo a la información de la API obtenida; estos nos servirá para setear los datos despues de ser deserealizados.
BindingContext:, creamos una instancia hacia CharactersViewModel permitiendo así que los elementos de la Interfaz de usuario se vinculen a sus propiedades, métodos, comandos etc.