SlideShare una empresa de Scribd logo
1 de 53
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Publicando un WebApi ASP
.NET Core con Entity
Framework Core en IIS y
aplicación cliente de Xamarin
Publicación del web api en IIS visible en la red local
Paso 1. Primero que nada debemos asegurarnos de que tenemos
instalado IIS y no la versión exprés (el caso más común). Para ello,
abre Panel de Control y selecciona Programas.
Paso 2. Selecciona la opción Activar o desactivar las características de
Windows.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 3. Marca las siguientes opciones dentro de Internet Information
Services (también las sub-opciones que aparecen palomeadas):
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 4. Da clic en Aceptar y espera a que el proceso finalice
correctamente.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
En la sesión anterior hablamos del Runtime & Hosting Bundle (paso
32, usamos la versión 2.0.9 que puedes descargar desde este enlace).
Cuando lo descargamos se menciona un punto muy importante: Si IIS
está instalado en el equipo, el Bundle también agregará el Módulo
ASP .NET Core para IIS. Dado que recién agregamos IIS, nuestra
instalación del Bundle está incompleta.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 5. Ejecuta el instalador del Runtime & Hosting
Bundle nuevamente y selecciona la opción Reparar.
Paso 6. Una vez finalizada la reparación, lo más probable es que
tengas que reiniciar el equipo.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 7. Una vez de vuelta, busca y ejecuta el Administrador de
Internet Information Services (IIS).
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 8. Ahora da clic derecho en Sitios y selecciona Agregar sitio web.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 9. Coloca la siguiente información:
 Nombre del sitio: Store
 Ruta de acceso física: La ubicación donde publicaste el WebApi de
la sesión anterior.
 Puerto: Uno diferente al 5000, por ejemplo el 5001.
 Nombre de host: Comodín, es decir, *.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 10. Ahora selecciona Grupos de aplicaciones, elige el
grupo Store (se creó al momento de generar el sitio web) y da clic
en Configuración básica.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 11. En Versión de .NET CLR selecciona Sin código administrado y
da clic en Aceptar.
Paso 12. Vuelve a seleccionar el grupo de aplicación Store y ahora
elige Configuración avanzada.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 13. En la categoría Modelo de proceso, da clic en el botón que
aparece en la propiedad Identidad.
Paso 14. Selecciona la cuenta integrada LocalSystem de la lista y acepta
este cambio.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 15. Abre Postman y utilizando la dirección IP de tu equipo realiza
una petición a alguno de los controladores disponibles en tu web
service. La petición debería ser exitosa. Por ejemplo, consultemos
la lista de clientes realizando una petición de tipo GET a la
URL http://mi-direccion-ip:puerto/api/customers; como puedes ver en
la imagen, en este caso estoy usando:
 La dirección IP asignada en el adaptador de red inalámbrico
(debido a que el dispositivo con el que probaré la aplicación cliente
-un teléfono- está conectado a la misma red inalámbrica.
 El puerto 5001 asignado en el paso 9.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Es importante recordar que en nuestro equipo puede haber varias
direcciones IP según el número de adaptadores que tengamos; por
ejemplo, en mi caso la conexión Ethernet y la red inalámbrica están en
diferentes redes. Como mencioné, estoy usando la de la red WiFi porque
el teléfono con el que probaré la aplicación también se conecta de manera
inalámbrica (y por tanto podrá ver al servidor).
Paso 16. Dependiendo la seguridad que tengamos, es altamente
probable que debamos agregar una regla de seguridad en nuestro
firewall para permitir la comunicación con otros dispositivos. Entonces
en primer lugar hay que ejecutar el firewall, por ejemplo el de Windows
(si tienes antivirus, usa el firewall de tu antivirus).
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 17. Selecciona Configuración avanzada.
Paso 18. Selecciona Nueva regla en la sección de Reglas de entrada.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 19. Elige el tipo de regla Puerto.
Paso 20. Especifica el puerto 5001 (o el que hayas asignado en el paso
9)
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 21. Dado que queremos aceptar las peticiones por este puerto,
selecciona la opción Permitir la conexión.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 22. Permite los 3 casos (dominio, privado y público)
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 23. Asigna un nombre a esta regla y finaliza el proceso para crear
la regla de entrada.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 24. Ahora realiza una petición de tipo GET desde otro
dispositivo en la misma red hacia el servidor; a continuación puedes
ver que utilicé un teléfono para obtener la lista de clientes con la
URL http://direccion-ip-servidor:5001/api/customers y funcionó
correctamente.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Así concluimos con la publicación del servicio web. Ahora es turno de
desarrollar una pequeña aplicación móvil que utilice el servicio para
mostrar datos y modificar la información de algunas tablas. En esta
sección crearemos algo muy básico, la aplicación de los Empleados que
podrá manipular la tabla de Clientes.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Cabe mencionar que en una sesión futura desarrollaremos otra
aplicación (la de los Clientes), por tanto lo ideal es compartir los
elementos comunes, como los modelos y los servicios. Por eso, antes
de crear la aplicación móvil agregaremos dos proyectos (capas) a la
solución
Proyectos móviles
Paso 1. Abre Visual Studio 2017 y selecciona Soluciones de Visual
Studio dentro de la categoría Otros tipos de proyectos. Elige Solución en
blanco y asigna el nombre MobileStore.
Paso 2. Da clic derecho en la solución vacía y elige la opción Agregar –
> Nuevo proyecto…
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 3. Selecciona Biblioteca de clases (.NET Standard) dentro
de Visual C# –> .NET Standard y asígnale el
nombre MyStore.Services al proyecto.
Paso 4. Repite el paso 2 para agregar otro proyecto del mismo tipo que
el anterior. Este segundo proyecto se llama MyStore.Models.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 5. Elimina Class1.cs en ambos proyectos.
Paso 6. Da clic derecho sobre el proyecto MyStore.Models y
selecciona Agregar –> Elemento existente…
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 7. Selecciona todas las clases DTO del
proyecto StoreWebApi (excepto AutoMapperConfiguration, que no es
un DTO)
Paso 8. Modifica el espacio de nombres de cada clase agregada. En
vez de StoreWebApi.DTOs es MyStore.Models. Además, tanto en los
modelos EmployeeDTO como CustomerDTO agrega una propiedad de
solo lectura FullName que retorne el apellido y el nombre de la
persona. Por ejemplo, a continuación se muestra el código de la
clase EmployeeDTO.cs:
using System;
using System.Collections.Generic;
namespace MyStore.Models
{
public class EmployeeDTO
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
public string UserName { get; set; }
public string Password { get; set; }
public string FullName => $"{LastName} {FirstName}";
}
}
view rawEmployeeDTO.cs hosted with ❤ by GitHub
Recuerda, este paso hay que hacerlo por cada una de las 6 clases
DTO del proyecto.
Paso 9. Ahora da clic derecho sobre Dependencias dentro del
proyecto MyStore.Services.
Paso 10. Selecciona el proyecto MyStore.Models de la
sección Proyectos. Esto permitirá utilizar las clases de la capa de
Modelos en la capa de Servicios.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 11. Vuelve a dar clic derecho sobre Dependencias del
proyecto MyStore.Services pero ahora selecciona Administrar paquetes
Nuget.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 12. Busca el paquete Newtonsoft.Json en la sección Examinar e
instálalo en el proyecto.
Paso 13. A continuación agrega una nueva clase al
proyecto MyStore.Services. Su nombre es Constants y solo tiene una
propiedad de momento, que es la URL que será utilizada como base
para acceder al web api.
namespace MyStore.Services
{
public class Constants
{
public const string StoreWebApiURL = "http://direccion-ip-servidor:5001/api/";
}
}
view rawConstants.cs hosted with ❤ by GitHub
Paso 14. Otra clase que se creará en el
proyecto MyStore.Services es MD5Security.cs, la cual convierte una
cadena de texto en su equivalente MD5. Será utilizada para insertar el
password en la base de datos. Su código es:
using System.Text;
using System.Linq;
using System.Security.Cryptography;
namespace MyStore.Services
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
{
public static class MD5Security
{
public static string ToMD5Hash(this string str)
{
if (string.IsNullOrEmpty(str))
return null;
return Encoding.ASCII.GetBytes(str).ToMD5Hash();
}
public static string ToMD5Hash(this byte[] bytes)
{
if (bytes == null || bytes.Length == 0)
return null;
using (var md5 = MD5.Create())
{
return string.Join("", md5.ComputeHash(bytes).Select(x => x.ToString("X2")));
}
}
}
}
view rawMD5Security.cs hosted with ❤ by GitHub
Paso 15. La última clase de este proyecto es la que se comunica con el
web api y es una clase con métodos genéricos
llamada StoreWebApiClient.cs. Por supuesto, es la clase más
importante de la capa de servicios y además implementa el
patrón Singleton con una instancia de clase (que a su vez hereda
de HttpClient). Esto se hace porque al realizar una conexión a un
servidor es mejor preservarla para su futura reutilización. Si durante el
ciclo de vida de una aplicación abrimos y cerramos conexiones, en
algún momento se agotará el número de conexiones disponibles con
el servidor, por lo cual se recomienda una sola instancia.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Además en esta clase se definen métodos CRUD genéricos para
llamar a los controladores del web api. Estos métodos genéricos nos
sirven para todos los modelos, por lo que no es necesario definir
métodos específicos (es decir, uno para el cliente, otro para el
empleado, etc.) puesto que ambos se consultan de la misma forma
(GET). Sí habrá algunos métodos particulares como el de Login. que
se incluye. El código es el siguiente:
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using MyStore.Models;
using Newtonsoft.Json;
namespace MyStore.Services
{
public class StoreWebApiClient : HttpClient
{
private static readonly StoreWebApiClient instance = new StoreWebApiClient();
static StoreWebApiClient() { }
private StoreWebApiClient() : base()
{
Timeout = TimeSpan.FromMilliseconds(15000);
MaxResponseContentBufferSize = 256000;
BaseAddress = new Uri(Constants.StoreWebApiURL);
DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")
}
public static StoreWebApiClient Instance
{
get
{
return instance;
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
}
}
public async Task<List<T>> GetItems<T>(string service)
{
var response = await GetAsync(service);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<List<T>>(content);
}
//throw new Exception(response.ReasonPhrase);
return default(List<T>);
}
public async Task<List<T>> GetItems<T>(string service, string method)
{
var response = await GetAsync($"{service}/{method}");
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<List<T>>(content);
}
//throw new Exception(response.ReasonPhrase);
return default(List<T>);
}
public async Task<T> GetItem<T>(string service, int id)
{
var response = await GetAsync($"{service}/{id}");
if (response.IsSuccessStatusCode)
{
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(content);
}
//throw new Exception(response.ReasonPhrase);
return default(T);
}
public async Task<T> GetItem<T>(string service, string method)
{
var response = await GetAsync($"{service}/{method}");
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(content);
}
//throw new Exception(response.ReasonPhrase);
return default(T);
}
public async Task<T> PostItem<T>(string service, T item)
{
var body = JsonConvert.SerializeObject(item);
var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await PostAsync(service, content);
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(json);
}
//throw new Exception(response.ReasonPhrase);
return default(T);
}
public async Task<bool> PutItem<T>(string service, T item, int id)
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
{
var body = JsonConvert.SerializeObject(item);
var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await PutAsync($"{service}/{id}", content);
if (response.IsSuccessStatusCode)
return true;
//throw new Exception(response.ReasonPhrase);
return false;
}
public async Task<bool> DeleteItem<T>(string service, int id)
{
var response = await DeleteAsync($"{service}/{id}");
if (response.IsSuccessStatusCode)
return true;
//throw new Exception(response.ReasonPhrase);
return false;
}
public async Task<EmployeeDTO> Login(string username, string password)
{
var credentials = new { username = username, password = MD5Security.ToMD5Hash(password)
var body = JsonConvert.SerializeObject(credentials);
var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await PostAsync("Employees/Login", content);
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<EmployeeDTO>(json);
}
//throw new Exception(response.ReasonPhrase);
return default(EmployeeDTO);
}
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
}
}
view rawStoreWebApiClient.cs hosted with ❤ by GitHub
Paso 16. Nuevamente da clic derecho a la solución para agregar un
proyecto. Sin embargo, en esta ocasión el proyecto será de la
categoría Cross-Platform (dentro de Visual C#) –> Mobile App
(Xamarin.Forms). El nombre del proyecto es MyStore.EmployeesApp.
Paso 17. Selecciona el template de Aplicación vacía y la estrategia de
código compartido .NET Standard.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 18. Da clic derecho sobre el proyecto MyStore.EmployeesApp y
selecciona Agregar –> Referencia.
Paso 19. Selecciona los
proyectos MyStore.Models y MyStore.Services de la solución
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 20. Nuevamente da clic derecho sobre MyStore.EmployeesApp y
agrega una nueva carpeta llamada Pages. Ahora sobre esta carpeta da
botón derecho y selecciona Agregar –> Nuevo elemento. Agregarás
un Content Page (dentro de la categoría Xamarin.Forms)
llamado LoginPage.
Paso 21. Esta página tendrá un pequeño formulario para que el usuario
ingrese sus credenciales y, solo si son correctas, se le brinde el
acceso. El código de la interfaz (XAML) es el siguiente:
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyStore.EmployeesApp.Pages.LoginPage">
<ContentPage.Content>
<StackLayout BackgroundColor="White">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Label Text="UserName: " Grid.Row="0" Grid.Column="0"
HorizontalOptions="Start" TextColor="Black"/>
<Entry Placeholder="User Name" x:Name="UserNameEntry"
Grid.Row="0" Grid.Column="1" WidthRequest="300"
HorizontalOptions="Start" TextColor="Black"
BackgroundColor="LightGreen"/>
<Label Text="Password: " Grid.Row="1" Grid.Column="0"
HorizontalOptions="Start" TextColor="Black"/>
<Entry x:Name="PasswordEntry"
Grid.Row="1" Grid.Column="1"
IsPassword="True" WidthRequest="300"
HorizontalOptions="Start" TextColor="Black"
BackgroundColor="LightGreen"/>
<Button x:Name="SignInButton" Text="Sign In"
Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"
BackgroundColor="LightBlue" TextColor="Black"
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Clicked="SignInButton_Clicked"/>
</Grid>
</StackLayout>
</ContentPage.Content>
</ContentPage>
view rawLoginPage.xaml.cs hosted with ❤ by GitHub
Y el code-behind es:
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using MyStore.Services;
using MyStore.Models;
namespace MyStore.EmployeesApp.Pages
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class LoginPage : ContentPage
{
public LoginPage ()
{
InitializeComponent ();
}
public async void SignInButton_Clicked(object sender, EventArgs e)
{
var username = UserNameEntry.Text;
var password = PasswordEntry.Text;
var employee = await StoreWebApiClient.Instance.Login(username, password);
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
if (employee != default(EmployeeDTO))
{
App.CurrentEmployee = employee;
await DisplayAlert("Welcome!", $"Welcome {employee.FullName}", "OK");
await Navigation.PushAsync(new CustomerListPage());
}
else
{
await DisplayAlert("Error!", "Wrong credentials!", "OK");
}
}
}
}
view rawLoginPage.cs hosted with ❤ by GitHub
Paso 22. Ahora agrega un nuevo Content Page (sobre la carpeta Pages)
llamado CustomerListPage que mostrará la lista de clientes registrados
(y un botón para agregar un nuevo cliente). Además, si se selecciona
un cliente se navegará a otra página para conocer su detalle. El
código XAML es el siguiente:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyStore.EmployeesApp.Pages.CustomerListPage">
<ContentPage.Content>
<StackLayout BackgroundColor="White">
<Label Text="Customer List" TextColor="Black" FontSize="Large" Margin="15"/>
<ActivityIndicator x:Name="indicator" Color="Green" VerticalOptions="Center" HorizontalOp
<ListView x:Name="CustomersListView" ItemSelected="CustomersListView_ItemSelected" HasUne
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding FullName}" FontSize="Medium"
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
LineBreakMode="WordWrap" TextColor="Black" Margin="10"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="AddButton" Text="Add" Order="Primary" Priority="0" Clicked="AddButton_Cl
</ContentPage.ToolbarItems>
</ContentPage>
view rawCustomerListPage.xaml.cs hosted with ❤ by GitHub
Y el code-behind es.
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using MyStore.Models;
using MyStore.Services;
namespace MyStore.EmployeesApp.Pages
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CustomerListPage : ContentPage
{
public CustomerListPage ()
{
InitializeComponent ();
}
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
protected async override void OnAppearing()
{
base.OnAppearing();
Loading(true);
CustomersListView.ItemsSource = await StoreWebApiClient.Instance.GetItems<CustomerDTO>("C
Loading(false);
}
void Loading(bool show)
{
indicator.IsEnabled = show;
indicator.IsRunning = show;
}
private async void CustomersListView_ItemSelected(object sender, SelectedItemChangedEventArgs
{
try
{
var item = (CustomerDTO)e.SelectedItem;
await Navigation.PushAsync(new CustomerPage(item));
CustomersListView.SelectedItem = null;
}
catch (Exception ex)
{
}
}
public async void AddButton_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new CustomerPage(new CustomerDTO()));
}
}
}
view rawCustomerListPage.cs hosted with ❤ by GitHub
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 23. Nuevamente agregamos un Content Page dentro de la
carpeta Pages llamado CustomerPage que mostrará el detalle del
cliente seleccionado en la pantalla previa para editar sus datos o
permitirá agregar un nuevo cliente (si se seleccionó esta opción en la
página anterior). Se tienen 3 botones: Register (para guardar
cambios), ViewOrders (para mostrar las órdenes del cliente -aunque
de momento solo se navegará a la página-) y Delete (para eliminar el
cliente, previa confirmación). El código XAML es el siguiente:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyStore.EmployeesApp.Pages.CustomerPage">
<ContentPage.Content>
<StackLayout BackgroundColor="White">
<Label Text="Customer Details" TextColor="Black" FontSize="Large" Margin="15"/>
<StackLayout Padding="15">
<Label Text="First Name: " TextColor="Blue" FontSize="Large"/>
<Entry x:Name="FirstNameTextBox" Text="{Binding FirstName}" TextColor="White"
Placeholder="First Name" PlaceholderColor="LightGray"
BackgroundColor="Black" FontSize="Medium"/>
</StackLayout>
<StackLayout Padding="15">
<Label Text="Last Name: " TextColor="Blue" FontSize="Large"/>
<Entry x:Name="LastNameTextBox" Text="{Binding LastName}" TextColor="White"
Placeholder="Last Name" PlaceholderColor="LightGray"
BackgroundColor="Black" FontSize="Medium"/>
</StackLayout>
<StackLayout Padding="15">
<Label Text="UserName: " TextColor="Blue" FontSize="Large"/>
<Entry x:Name="UserNameTextBox" Text="{Binding UserName}" TextColor="White"
Placeholder="User Name" PlaceholderColor="LightGray"
BackgroundColor="Black" FontSize="Medium"/>
</StackLayout>
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
<ActivityIndicator x:Name="indicator" Color="Green" VerticalOptions="Center" HorizontalOp
</StackLayout>
</ContentPage.Content>
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="RegisterButton" Text="Register | " Order="Primary" Priority="0" Clicked=
<ToolbarItem x:Name="ViewCustomerOrdersButton" Text="Orders | " Order="Primary" Priority="1"
<ToolbarItem x:Name="DeleteButton" Text="Delete | " Order="Primary" Priority="2" Clicked="Del
</ContentPage.ToolbarItems>
</ContentPage>
view rawCustomerPage.xaml.cs hosted with ❤ by GitHub
Y el code-behind es.
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using MyStore.Models;
using MyStore.Services;
namespace MyStore.EmployeesApp.Pages
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CustomerPage : ContentPage
{
public CustomerPage (CustomerDTO item)
{
InitializeComponent ();
this.BindingContext = item;
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
if (item.Id == 0)
{
this.ToolbarItems.RemoveAt(2);
this.ToolbarItems.RemoveAt(1);
}
}
void Loading(bool show)
{
indicator.IsEnabled = show;
indicator.IsRunning = show;
}
async void RegisterButton_Clicked(object sender, EventArgs e)
{
Loading(true);
var item = (CustomerDTO)this.BindingContext;
if (item.Id > 0)
await StoreWebApiClient.Instance.PutItem<CustomerDTO>("Customers", item, item.Id);
else
{
item.Password = MD5Security.ToMD5Hash("abc");
await StoreWebApiClient.Instance.PostItem<CustomerDTO>("Customers", item);
}
Loading(false);
await DisplayAlert("Success", "Item registered!", "OK");
await Navigation.PopAsync();
}
async void ViewCustomerOrdersButton_Clicked(object sender, EventArgs e)
{
var item = (CustomerDTO)this.BindingContext;
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
await Navigation.PushAsync(new CustomerOrderListPage(item));
}
async void DeleteButton_Clicked(object sender, EventArgs e)
{
if (await DisplayAlert("Warning!", "Do you really want to delete this item?", "Yes", "No"))
{
Loading(true);
var item = (CustomerDTO)this.BindingContext;
var op = await StoreWebApiClient.Instance.DeleteItem<CustomerDTO>("Customers", item.Id);
Loading(false);
if (op)
{
await DisplayAlert("Success!", "Item deleted!", "OK");
await Navigation.PopAsync();
}
else
{
await DisplayAlert("Error!", "Item was not deleted!", "OK");
}
}
}
}
}
view rawCustomerPage.cs hosted with ❤ by GitHub
Paso 24. Ya casi para terminar, agrega un nuevo Content Page (sobre
la carpeta Pages) llamado CustomerOrderListPage que de momento
tendrá el código XAML por default. Solo se hará un pequeño cambio
en el constructor en el código de C# respectivo, el cual se muestra a
continuación:
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using MyStore.Models;
namespace MyStore.EmployeesApp.Pages
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CustomerOrderListPage : ContentPage
{
public CustomerOrderListPage (CustomerDTO item)
{
InitializeComponent ();
}
}
}
view rawCustomerOrderListPage.cs hosted with ❤ by GitHub
Paso 25. Modifica el archivo App.xaml.cs de la siguiente manera:
using System;
using Xamarin.Forms;
using MyStore.Models;
namespace MyStore.EmployeesApp
{
public partial class App : Application
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
{
public static EmployeeDTO CurrentEmployee;
public App ()
{
InitializeComponent();
MainPage = new NavigationPage(new Pages.LoginPage());
}
}
}
view rawApp.xaml.cs hosted with ❤ by GitHub
Paso 26. Finalmente, da clic derecho sobre el proyecto que deseas
probar, por ejemplo en este caso, el de Android y selecciona la
opción Establecer como proyecto de inicio.
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Paso 27. Compila y ejecuta la aplicación. Realiza varias pruebas para
verificar el correcto funcionamiento de la misma.
Inicio de sesión:
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Lista de Clientes:
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Agregar un cliente:
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Editar datos del cliente:
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información
Eliminar un cliente:
Mg. Luis FernandoAguas
Universidad Israel
Cienciasde la Ingeniería
Carrera de Sistemasde Información

Más contenido relacionado

Similar a Web API ASP. NET XAMARIN - Luis Fernando Aguas

Anexo 15 actividad 4 instalacion de maquina virtual y sistemas operativos en red
Anexo 15 actividad 4 instalacion de maquina virtual y sistemas operativos en redAnexo 15 actividad 4 instalacion de maquina virtual y sistemas operativos en red
Anexo 15 actividad 4 instalacion de maquina virtual y sistemas operativos en redEdgar Mtz
 
Configurando Ambiente de Desarrollo WEB en Eclipse Neón para Desarrolladores
Configurando Ambiente de Desarrollo WEB en Eclipse Neón para DesarrolladoresConfigurando Ambiente de Desarrollo WEB en Eclipse Neón para Desarrolladores
Configurando Ambiente de Desarrollo WEB en Eclipse Neón para DesarrolladoresIvan Luis Jimenez
 
Construcción de un siti web
Construcción de un siti webConstrucción de un siti web
Construcción de un siti webmascorroale
 
"Los Imprescindibles de .NetCore"
"Los Imprescindibles de .NetCore""Los Imprescindibles de .NetCore"
"Los Imprescindibles de .NetCore"www.encamina.com
 
Manual jira , Instalación, Creación de Proyecto, Incidencias, Usuarios
Manual jira , Instalación, Creación de Proyecto, Incidencias, UsuariosManual jira , Instalación, Creación de Proyecto, Incidencias, Usuarios
Manual jira , Instalación, Creación de Proyecto, Incidencias, UsuariosLeo Ruelas Rojas
 
Appcircus Academy: Integración de Social Media en Android
Appcircus Academy: Integración de Social Media en AndroidAppcircus Academy: Integración de Social Media en Android
Appcircus Academy: Integración de Social Media en AndroidAlberto Ruibal
 
Temario java web_j2_ee_02
Temario java web_j2_ee_02Temario java web_j2_ee_02
Temario java web_j2_ee_02anyeni
 
TEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLOTEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLOAnyeni Garay
 
Temario java web_j2_ee_02
Temario java web_j2_ee_02Temario java web_j2_ee_02
Temario java web_j2_ee_02anyeni
 
TEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLOTEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLOanyeni
 
TEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLOTEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLOanyeni
 
Desarrollando mi primera App para Windows 8 con C#
Desarrollando mi primera App para Windows 8 con C#Desarrollando mi primera App para Windows 8 con C#
Desarrollando mi primera App para Windows 8 con C#Vicente Gerardo Guzman Lucio
 
Manual acceso a datos vb.net
Manual acceso a datos vb.netManual acceso a datos vb.net
Manual acceso a datos vb.netcedido
 
Cesnavarra 2009-boletín 5
Cesnavarra 2009-boletín 5Cesnavarra 2009-boletín 5
Cesnavarra 2009-boletín 5Cein
 
Tutorial windows azure con visual studio 2010
Tutorial windows azure con visual studio 2010Tutorial windows azure con visual studio 2010
Tutorial windows azure con visual studio 2010Naim Jhon Cruzado Paredes
 

Similar a Web API ASP. NET XAMARIN - Luis Fernando Aguas (20)

Anexo 15 actividad 4 instalacion de maquina virtual y sistemas operativos en red
Anexo 15 actividad 4 instalacion de maquina virtual y sistemas operativos en redAnexo 15 actividad 4 instalacion de maquina virtual y sistemas operativos en red
Anexo 15 actividad 4 instalacion de maquina virtual y sistemas operativos en red
 
Configurando Ambiente de Desarrollo WEB en Eclipse Neón para Desarrolladores
Configurando Ambiente de Desarrollo WEB en Eclipse Neón para DesarrolladoresConfigurando Ambiente de Desarrollo WEB en Eclipse Neón para Desarrolladores
Configurando Ambiente de Desarrollo WEB en Eclipse Neón para Desarrolladores
 
Practica 3
Practica 3Practica 3
Practica 3
 
Construcción de un siti web
Construcción de un siti webConstrucción de un siti web
Construcción de un siti web
 
Act 1 comercio
Act 1 comercioAct 1 comercio
Act 1 comercio
 
Reportes
ReportesReportes
Reportes
 
"Los Imprescindibles de .NetCore"
"Los Imprescindibles de .NetCore""Los Imprescindibles de .NetCore"
"Los Imprescindibles de .NetCore"
 
Servidor de correo en Zentyal 3.5
Servidor de correo en Zentyal 3.5Servidor de correo en Zentyal 3.5
Servidor de correo en Zentyal 3.5
 
Manual jira , Instalación, Creación de Proyecto, Incidencias, Usuarios
Manual jira , Instalación, Creación de Proyecto, Incidencias, UsuariosManual jira , Instalación, Creación de Proyecto, Incidencias, Usuarios
Manual jira , Instalación, Creación de Proyecto, Incidencias, Usuarios
 
Appcircus Academy: Integración de Social Media en Android
Appcircus Academy: Integración de Social Media en AndroidAppcircus Academy: Integración de Social Media en Android
Appcircus Academy: Integración de Social Media en Android
 
Temario java web_j2_ee_02
Temario java web_j2_ee_02Temario java web_j2_ee_02
Temario java web_j2_ee_02
 
TEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLOTEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLO
 
Temario java web_j2_ee_02
Temario java web_j2_ee_02Temario java web_j2_ee_02
Temario java web_j2_ee_02
 
TEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLOTEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLO
 
TEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLOTEMA Nº 2: ENTORNO DE DESARROLLO
TEMA Nº 2: ENTORNO DE DESARROLLO
 
Desarrollando mi primera App para Windows 8 con C#
Desarrollando mi primera App para Windows 8 con C#Desarrollando mi primera App para Windows 8 con C#
Desarrollando mi primera App para Windows 8 con C#
 
Dprn3 u3 a1_hesc
Dprn3 u3 a1_hescDprn3 u3 a1_hesc
Dprn3 u3 a1_hesc
 
Manual acceso a datos vb.net
Manual acceso a datos vb.netManual acceso a datos vb.net
Manual acceso a datos vb.net
 
Cesnavarra 2009-boletín 5
Cesnavarra 2009-boletín 5Cesnavarra 2009-boletín 5
Cesnavarra 2009-boletín 5
 
Tutorial windows azure con visual studio 2010
Tutorial windows azure con visual studio 2010Tutorial windows azure con visual studio 2010
Tutorial windows azure con visual studio 2010
 

Más de Luis Fernando Aguas Bucheli (20)

EFC-ISW-Luis Fernando Aguas.pptx
EFC-ISW-Luis Fernando Aguas.pptxEFC-ISW-Luis Fernando Aguas.pptx
EFC-ISW-Luis Fernando Aguas.pptx
 
P-S2.pptx
P-S2.pptxP-S2.pptx
P-S2.pptx
 
EBTS-S1.pptx
EBTS-S1.pptxEBTS-S1.pptx
EBTS-S1.pptx
 
P-S3.pptx
P-S3.pptxP-S3.pptx
P-S3.pptx
 
EBTS-S4.pptx
EBTS-S4.pptxEBTS-S4.pptx
EBTS-S4.pptx
 
P-S4.pptx
P-S4.pptxP-S4.pptx
P-S4.pptx
 
P-S1.pptx
P-S1.pptxP-S1.pptx
P-S1.pptx
 
EBTS-S3.pptx
EBTS-S3.pptxEBTS-S3.pptx
EBTS-S3.pptx
 
EBTS-S2.pptx
EBTS-S2.pptxEBTS-S2.pptx
EBTS-S2.pptx
 
PDIDTI-S7.pptx
PDIDTI-S7.pptxPDIDTI-S7.pptx
PDIDTI-S7.pptx
 
PDIDTI-S4.pptx
PDIDTI-S4.pptxPDIDTI-S4.pptx
PDIDTI-S4.pptx
 
PDIDTI-S2.pptx
PDIDTI-S2.pptxPDIDTI-S2.pptx
PDIDTI-S2.pptx
 
PDIDTI-S1.pptx
PDIDTI-S1.pptxPDIDTI-S1.pptx
PDIDTI-S1.pptx
 
PDIDTI-S8.pptx
PDIDTI-S8.pptxPDIDTI-S8.pptx
PDIDTI-S8.pptx
 
PDIDTI-S6.pptx
PDIDTI-S6.pptxPDIDTI-S6.pptx
PDIDTI-S6.pptx
 
PDIDTI-S5.pptx
PDIDTI-S5.pptxPDIDTI-S5.pptx
PDIDTI-S5.pptx
 
PDIDTI-S3.pptx
PDIDTI-S3.pptxPDIDTI-S3.pptx
PDIDTI-S3.pptx
 
TIC-S4.pptx
TIC-S4.pptxTIC-S4.pptx
TIC-S4.pptx
 
TIC-S3.pptx
TIC-S3.pptxTIC-S3.pptx
TIC-S3.pptx
 
TIC-S2.pptx
TIC-S2.pptxTIC-S2.pptx
TIC-S2.pptx
 

Último

Proyecto de iluminación "guia" para proyectos de ingeniería eléctrica
Proyecto de iluminación "guia" para proyectos de ingeniería eléctricaProyecto de iluminación "guia" para proyectos de ingeniería eléctrica
Proyecto de iluminación "guia" para proyectos de ingeniería eléctricaXjoseantonio01jossed
 
4.6 DEFINICION DEL PROBLEMA DE ASIGNACION.pptx
4.6 DEFINICION DEL PROBLEMA DE ASIGNACION.pptx4.6 DEFINICION DEL PROBLEMA DE ASIGNACION.pptx
4.6 DEFINICION DEL PROBLEMA DE ASIGNACION.pptxGARCIARAMIREZCESAR
 
Curso intensivo de soldadura electrónica en pdf
Curso intensivo de soldadura electrónica  en pdfCurso intensivo de soldadura electrónica  en pdf
Curso intensivo de soldadura electrónica en pdfFernandaGarca788912
 
PPT SERVIDOR ESCUELA PERU EDUCA LINUX v7.pptx
PPT SERVIDOR ESCUELA PERU EDUCA LINUX v7.pptxPPT SERVIDOR ESCUELA PERU EDUCA LINUX v7.pptx
PPT SERVIDOR ESCUELA PERU EDUCA LINUX v7.pptxSergioGJimenezMorean
 
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdfAnthonyTiclia
 
Flujo multifásico en tuberias de ex.pptx
Flujo multifásico en tuberias de ex.pptxFlujo multifásico en tuberias de ex.pptx
Flujo multifásico en tuberias de ex.pptxEduardoSnchezHernnde5
 
Calavera calculo de estructuras de cimentacion.pdf
Calavera calculo de estructuras de cimentacion.pdfCalavera calculo de estructuras de cimentacion.pdf
Calavera calculo de estructuras de cimentacion.pdfyoseka196
 
estadisticasII Metodo-de-la-gran-M.pdf
estadisticasII   Metodo-de-la-gran-M.pdfestadisticasII   Metodo-de-la-gran-M.pdf
estadisticasII Metodo-de-la-gran-M.pdfFlorenciopeaortiz
 
TALLER PAEC preparatoria directamente de la secretaria de educación pública
TALLER PAEC preparatoria directamente de la secretaria de educación públicaTALLER PAEC preparatoria directamente de la secretaria de educación pública
TALLER PAEC preparatoria directamente de la secretaria de educación públicaSantiagoSanchez353883
 
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESAIPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESAJAMESDIAZ55
 
MANIOBRA Y CONTROL INNOVATIVO LOGO PLC SIEMENS
MANIOBRA Y CONTROL INNOVATIVO LOGO PLC  SIEMENSMANIOBRA Y CONTROL INNOVATIVO LOGO PLC  SIEMENS
MANIOBRA Y CONTROL INNOVATIVO LOGO PLC SIEMENSLuisLobatoingaruca
 
Residente de obra y sus funciones que realiza .pdf
Residente de obra y sus funciones que realiza  .pdfResidente de obra y sus funciones que realiza  .pdf
Residente de obra y sus funciones que realiza .pdfevin1703e
 
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONAL
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONALCHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONAL
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONALKATHIAMILAGRITOSSANC
 
183045401-Terminal-Terrestre-de-Trujillo.pdf
183045401-Terminal-Terrestre-de-Trujillo.pdf183045401-Terminal-Terrestre-de-Trujillo.pdf
183045401-Terminal-Terrestre-de-Trujillo.pdfEdwinAlexanderSnchez2
 
SSOMA, seguridad y salud ocupacional. SST
SSOMA, seguridad y salud ocupacional. SSTSSOMA, seguridad y salud ocupacional. SST
SSOMA, seguridad y salud ocupacional. SSTGestorManpower
 
clases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdfclases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdfDanielaVelasquez553560
 
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdf
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdfReporte de simulación de flujo del agua en un volumen de control MNVA.pdf
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdfMikkaelNicolae
 
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.ariannytrading
 
Una estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NISTUna estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NISTFundación YOD YOD
 
Manual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdfManual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdfedsonzav8
 

Último (20)

Proyecto de iluminación "guia" para proyectos de ingeniería eléctrica
Proyecto de iluminación "guia" para proyectos de ingeniería eléctricaProyecto de iluminación "guia" para proyectos de ingeniería eléctrica
Proyecto de iluminación "guia" para proyectos de ingeniería eléctrica
 
4.6 DEFINICION DEL PROBLEMA DE ASIGNACION.pptx
4.6 DEFINICION DEL PROBLEMA DE ASIGNACION.pptx4.6 DEFINICION DEL PROBLEMA DE ASIGNACION.pptx
4.6 DEFINICION DEL PROBLEMA DE ASIGNACION.pptx
 
Curso intensivo de soldadura electrónica en pdf
Curso intensivo de soldadura electrónica  en pdfCurso intensivo de soldadura electrónica  en pdf
Curso intensivo de soldadura electrónica en pdf
 
PPT SERVIDOR ESCUELA PERU EDUCA LINUX v7.pptx
PPT SERVIDOR ESCUELA PERU EDUCA LINUX v7.pptxPPT SERVIDOR ESCUELA PERU EDUCA LINUX v7.pptx
PPT SERVIDOR ESCUELA PERU EDUCA LINUX v7.pptx
 
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
 
Flujo multifásico en tuberias de ex.pptx
Flujo multifásico en tuberias de ex.pptxFlujo multifásico en tuberias de ex.pptx
Flujo multifásico en tuberias de ex.pptx
 
Calavera calculo de estructuras de cimentacion.pdf
Calavera calculo de estructuras de cimentacion.pdfCalavera calculo de estructuras de cimentacion.pdf
Calavera calculo de estructuras de cimentacion.pdf
 
estadisticasII Metodo-de-la-gran-M.pdf
estadisticasII   Metodo-de-la-gran-M.pdfestadisticasII   Metodo-de-la-gran-M.pdf
estadisticasII Metodo-de-la-gran-M.pdf
 
TALLER PAEC preparatoria directamente de la secretaria de educación pública
TALLER PAEC preparatoria directamente de la secretaria de educación públicaTALLER PAEC preparatoria directamente de la secretaria de educación pública
TALLER PAEC preparatoria directamente de la secretaria de educación pública
 
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESAIPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
 
MANIOBRA Y CONTROL INNOVATIVO LOGO PLC SIEMENS
MANIOBRA Y CONTROL INNOVATIVO LOGO PLC  SIEMENSMANIOBRA Y CONTROL INNOVATIVO LOGO PLC  SIEMENS
MANIOBRA Y CONTROL INNOVATIVO LOGO PLC SIEMENS
 
Residente de obra y sus funciones que realiza .pdf
Residente de obra y sus funciones que realiza  .pdfResidente de obra y sus funciones que realiza  .pdf
Residente de obra y sus funciones que realiza .pdf
 
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONAL
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONALCHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONAL
CHARLA DE INDUCCIÓN SEGURIDAD Y SALUD OCUPACIONAL
 
183045401-Terminal-Terrestre-de-Trujillo.pdf
183045401-Terminal-Terrestre-de-Trujillo.pdf183045401-Terminal-Terrestre-de-Trujillo.pdf
183045401-Terminal-Terrestre-de-Trujillo.pdf
 
SSOMA, seguridad y salud ocupacional. SST
SSOMA, seguridad y salud ocupacional. SSTSSOMA, seguridad y salud ocupacional. SST
SSOMA, seguridad y salud ocupacional. SST
 
clases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdfclases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdf
 
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdf
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdfReporte de simulación de flujo del agua en un volumen de control MNVA.pdf
Reporte de simulación de flujo del agua en un volumen de control MNVA.pdf
 
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
 
Una estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NISTUna estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NIST
 
Manual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdfManual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdf
 

Web API ASP. NET XAMARIN - Luis Fernando Aguas

  • 1. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Publicando un WebApi ASP .NET Core con Entity Framework Core en IIS y aplicación cliente de Xamarin Publicación del web api en IIS visible en la red local Paso 1. Primero que nada debemos asegurarnos de que tenemos instalado IIS y no la versión exprés (el caso más común). Para ello, abre Panel de Control y selecciona Programas. Paso 2. Selecciona la opción Activar o desactivar las características de Windows.
  • 2. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 3. Marca las siguientes opciones dentro de Internet Information Services (también las sub-opciones que aparecen palomeadas):
  • 3. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 4. Da clic en Aceptar y espera a que el proceso finalice correctamente.
  • 4. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información En la sesión anterior hablamos del Runtime & Hosting Bundle (paso 32, usamos la versión 2.0.9 que puedes descargar desde este enlace). Cuando lo descargamos se menciona un punto muy importante: Si IIS está instalado en el equipo, el Bundle también agregará el Módulo ASP .NET Core para IIS. Dado que recién agregamos IIS, nuestra instalación del Bundle está incompleta.
  • 5. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 5. Ejecuta el instalador del Runtime & Hosting Bundle nuevamente y selecciona la opción Reparar. Paso 6. Una vez finalizada la reparación, lo más probable es que tengas que reiniciar el equipo.
  • 6. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 7. Una vez de vuelta, busca y ejecuta el Administrador de Internet Information Services (IIS).
  • 7. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 8. Ahora da clic derecho en Sitios y selecciona Agregar sitio web.
  • 8. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 9. Coloca la siguiente información:  Nombre del sitio: Store  Ruta de acceso física: La ubicación donde publicaste el WebApi de la sesión anterior.  Puerto: Uno diferente al 5000, por ejemplo el 5001.  Nombre de host: Comodín, es decir, *.
  • 9. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 10. Ahora selecciona Grupos de aplicaciones, elige el grupo Store (se creó al momento de generar el sitio web) y da clic en Configuración básica.
  • 10. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 11. En Versión de .NET CLR selecciona Sin código administrado y da clic en Aceptar. Paso 12. Vuelve a seleccionar el grupo de aplicación Store y ahora elige Configuración avanzada.
  • 11. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 13. En la categoría Modelo de proceso, da clic en el botón que aparece en la propiedad Identidad. Paso 14. Selecciona la cuenta integrada LocalSystem de la lista y acepta este cambio.
  • 12. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 15. Abre Postman y utilizando la dirección IP de tu equipo realiza una petición a alguno de los controladores disponibles en tu web service. La petición debería ser exitosa. Por ejemplo, consultemos la lista de clientes realizando una petición de tipo GET a la URL http://mi-direccion-ip:puerto/api/customers; como puedes ver en la imagen, en este caso estoy usando:  La dirección IP asignada en el adaptador de red inalámbrico (debido a que el dispositivo con el que probaré la aplicación cliente -un teléfono- está conectado a la misma red inalámbrica.  El puerto 5001 asignado en el paso 9.
  • 13. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Es importante recordar que en nuestro equipo puede haber varias direcciones IP según el número de adaptadores que tengamos; por ejemplo, en mi caso la conexión Ethernet y la red inalámbrica están en diferentes redes. Como mencioné, estoy usando la de la red WiFi porque el teléfono con el que probaré la aplicación también se conecta de manera inalámbrica (y por tanto podrá ver al servidor). Paso 16. Dependiendo la seguridad que tengamos, es altamente probable que debamos agregar una regla de seguridad en nuestro firewall para permitir la comunicación con otros dispositivos. Entonces en primer lugar hay que ejecutar el firewall, por ejemplo el de Windows (si tienes antivirus, usa el firewall de tu antivirus).
  • 14. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 17. Selecciona Configuración avanzada. Paso 18. Selecciona Nueva regla en la sección de Reglas de entrada.
  • 15. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 19. Elige el tipo de regla Puerto. Paso 20. Especifica el puerto 5001 (o el que hayas asignado en el paso 9)
  • 16. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 21. Dado que queremos aceptar las peticiones por este puerto, selecciona la opción Permitir la conexión.
  • 17. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 22. Permite los 3 casos (dominio, privado y público)
  • 18. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 23. Asigna un nombre a esta regla y finaliza el proceso para crear la regla de entrada.
  • 19. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 24. Ahora realiza una petición de tipo GET desde otro dispositivo en la misma red hacia el servidor; a continuación puedes ver que utilicé un teléfono para obtener la lista de clientes con la URL http://direccion-ip-servidor:5001/api/customers y funcionó correctamente.
  • 20. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Así concluimos con la publicación del servicio web. Ahora es turno de desarrollar una pequeña aplicación móvil que utilice el servicio para mostrar datos y modificar la información de algunas tablas. En esta sección crearemos algo muy básico, la aplicación de los Empleados que podrá manipular la tabla de Clientes.
  • 21. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Cabe mencionar que en una sesión futura desarrollaremos otra aplicación (la de los Clientes), por tanto lo ideal es compartir los elementos comunes, como los modelos y los servicios. Por eso, antes de crear la aplicación móvil agregaremos dos proyectos (capas) a la solución Proyectos móviles Paso 1. Abre Visual Studio 2017 y selecciona Soluciones de Visual Studio dentro de la categoría Otros tipos de proyectos. Elige Solución en blanco y asigna el nombre MobileStore. Paso 2. Da clic derecho en la solución vacía y elige la opción Agregar – > Nuevo proyecto…
  • 22. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 3. Selecciona Biblioteca de clases (.NET Standard) dentro de Visual C# –> .NET Standard y asígnale el nombre MyStore.Services al proyecto. Paso 4. Repite el paso 2 para agregar otro proyecto del mismo tipo que el anterior. Este segundo proyecto se llama MyStore.Models.
  • 23. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 5. Elimina Class1.cs en ambos proyectos. Paso 6. Da clic derecho sobre el proyecto MyStore.Models y selecciona Agregar –> Elemento existente…
  • 24. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 7. Selecciona todas las clases DTO del proyecto StoreWebApi (excepto AutoMapperConfiguration, que no es un DTO) Paso 8. Modifica el espacio de nombres de cada clase agregada. En vez de StoreWebApi.DTOs es MyStore.Models. Además, tanto en los modelos EmployeeDTO como CustomerDTO agrega una propiedad de solo lectura FullName que retorne el apellido y el nombre de la persona. Por ejemplo, a continuación se muestra el código de la clase EmployeeDTO.cs: using System; using System.Collections.Generic; namespace MyStore.Models { public class EmployeeDTO { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; }
  • 25. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información public string UserName { get; set; } public string Password { get; set; } public string FullName => $"{LastName} {FirstName}"; } } view rawEmployeeDTO.cs hosted with ❤ by GitHub Recuerda, este paso hay que hacerlo por cada una de las 6 clases DTO del proyecto. Paso 9. Ahora da clic derecho sobre Dependencias dentro del proyecto MyStore.Services. Paso 10. Selecciona el proyecto MyStore.Models de la sección Proyectos. Esto permitirá utilizar las clases de la capa de Modelos en la capa de Servicios.
  • 26. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 11. Vuelve a dar clic derecho sobre Dependencias del proyecto MyStore.Services pero ahora selecciona Administrar paquetes Nuget.
  • 27. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 12. Busca el paquete Newtonsoft.Json en la sección Examinar e instálalo en el proyecto. Paso 13. A continuación agrega una nueva clase al proyecto MyStore.Services. Su nombre es Constants y solo tiene una propiedad de momento, que es la URL que será utilizada como base para acceder al web api. namespace MyStore.Services { public class Constants { public const string StoreWebApiURL = "http://direccion-ip-servidor:5001/api/"; } } view rawConstants.cs hosted with ❤ by GitHub Paso 14. Otra clase que se creará en el proyecto MyStore.Services es MD5Security.cs, la cual convierte una cadena de texto en su equivalente MD5. Será utilizada para insertar el password en la base de datos. Su código es: using System.Text; using System.Linq; using System.Security.Cryptography; namespace MyStore.Services
  • 28. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información { public static class MD5Security { public static string ToMD5Hash(this string str) { if (string.IsNullOrEmpty(str)) return null; return Encoding.ASCII.GetBytes(str).ToMD5Hash(); } public static string ToMD5Hash(this byte[] bytes) { if (bytes == null || bytes.Length == 0) return null; using (var md5 = MD5.Create()) { return string.Join("", md5.ComputeHash(bytes).Select(x => x.ToString("X2"))); } } } } view rawMD5Security.cs hosted with ❤ by GitHub Paso 15. La última clase de este proyecto es la que se comunica con el web api y es una clase con métodos genéricos llamada StoreWebApiClient.cs. Por supuesto, es la clase más importante de la capa de servicios y además implementa el patrón Singleton con una instancia de clase (que a su vez hereda de HttpClient). Esto se hace porque al realizar una conexión a un servidor es mejor preservarla para su futura reutilización. Si durante el ciclo de vida de una aplicación abrimos y cerramos conexiones, en algún momento se agotará el número de conexiones disponibles con el servidor, por lo cual se recomienda una sola instancia.
  • 29. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Además en esta clase se definen métodos CRUD genéricos para llamar a los controladores del web api. Estos métodos genéricos nos sirven para todos los modelos, por lo que no es necesario definir métodos específicos (es decir, uno para el cliente, otro para el empleado, etc.) puesto que ambos se consultan de la misma forma (GET). Sí habrá algunos métodos particulares como el de Login. que se incluye. El código es el siguiente: using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using MyStore.Models; using Newtonsoft.Json; namespace MyStore.Services { public class StoreWebApiClient : HttpClient { private static readonly StoreWebApiClient instance = new StoreWebApiClient(); static StoreWebApiClient() { } private StoreWebApiClient() : base() { Timeout = TimeSpan.FromMilliseconds(15000); MaxResponseContentBufferSize = 256000; BaseAddress = new Uri(Constants.StoreWebApiURL); DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json") } public static StoreWebApiClient Instance { get { return instance;
  • 30. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información } } public async Task<List<T>> GetItems<T>(string service) { var response = await GetAsync(service); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject<List<T>>(content); } //throw new Exception(response.ReasonPhrase); return default(List<T>); } public async Task<List<T>> GetItems<T>(string service, string method) { var response = await GetAsync($"{service}/{method}"); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject<List<T>>(content); } //throw new Exception(response.ReasonPhrase); return default(List<T>); } public async Task<T> GetItem<T>(string service, int id) { var response = await GetAsync($"{service}/{id}"); if (response.IsSuccessStatusCode) {
  • 31. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información var content = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject<T>(content); } //throw new Exception(response.ReasonPhrase); return default(T); } public async Task<T> GetItem<T>(string service, string method) { var response = await GetAsync($"{service}/{method}"); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject<T>(content); } //throw new Exception(response.ReasonPhrase); return default(T); } public async Task<T> PostItem<T>(string service, T item) { var body = JsonConvert.SerializeObject(item); var content = new StringContent(body, Encoding.UTF8, "application/json"); var response = await PostAsync(service, content); if (response.IsSuccessStatusCode) { var json = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject<T>(json); } //throw new Exception(response.ReasonPhrase); return default(T); } public async Task<bool> PutItem<T>(string service, T item, int id)
  • 32. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información { var body = JsonConvert.SerializeObject(item); var content = new StringContent(body, Encoding.UTF8, "application/json"); var response = await PutAsync($"{service}/{id}", content); if (response.IsSuccessStatusCode) return true; //throw new Exception(response.ReasonPhrase); return false; } public async Task<bool> DeleteItem<T>(string service, int id) { var response = await DeleteAsync($"{service}/{id}"); if (response.IsSuccessStatusCode) return true; //throw new Exception(response.ReasonPhrase); return false; } public async Task<EmployeeDTO> Login(string username, string password) { var credentials = new { username = username, password = MD5Security.ToMD5Hash(password) var body = JsonConvert.SerializeObject(credentials); var content = new StringContent(body, Encoding.UTF8, "application/json"); var response = await PostAsync("Employees/Login", content); if (response.IsSuccessStatusCode) { var json = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject<EmployeeDTO>(json); } //throw new Exception(response.ReasonPhrase); return default(EmployeeDTO); }
  • 33. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información } } view rawStoreWebApiClient.cs hosted with ❤ by GitHub Paso 16. Nuevamente da clic derecho a la solución para agregar un proyecto. Sin embargo, en esta ocasión el proyecto será de la categoría Cross-Platform (dentro de Visual C#) –> Mobile App (Xamarin.Forms). El nombre del proyecto es MyStore.EmployeesApp. Paso 17. Selecciona el template de Aplicación vacía y la estrategia de código compartido .NET Standard.
  • 34. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 18. Da clic derecho sobre el proyecto MyStore.EmployeesApp y selecciona Agregar –> Referencia. Paso 19. Selecciona los proyectos MyStore.Models y MyStore.Services de la solución
  • 35. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 20. Nuevamente da clic derecho sobre MyStore.EmployeesApp y agrega una nueva carpeta llamada Pages. Ahora sobre esta carpeta da botón derecho y selecciona Agregar –> Nuevo elemento. Agregarás un Content Page (dentro de la categoría Xamarin.Forms) llamado LoginPage. Paso 21. Esta página tendrá un pequeño formulario para que el usuario ingrese sus credenciales y, solo si son correctas, se le brinde el acceso. El código de la interfaz (XAML) es el siguiente:
  • 36. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MyStore.EmployeesApp.Pages.LoginPage"> <ContentPage.Content> <StackLayout BackgroundColor="White"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="3*"/> </Grid.ColumnDefinitions> <Label Text="UserName: " Grid.Row="0" Grid.Column="0" HorizontalOptions="Start" TextColor="Black"/> <Entry Placeholder="User Name" x:Name="UserNameEntry" Grid.Row="0" Grid.Column="1" WidthRequest="300" HorizontalOptions="Start" TextColor="Black" BackgroundColor="LightGreen"/> <Label Text="Password: " Grid.Row="1" Grid.Column="0" HorizontalOptions="Start" TextColor="Black"/> <Entry x:Name="PasswordEntry" Grid.Row="1" Grid.Column="1" IsPassword="True" WidthRequest="300" HorizontalOptions="Start" TextColor="Black" BackgroundColor="LightGreen"/> <Button x:Name="SignInButton" Text="Sign In" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" BackgroundColor="LightBlue" TextColor="Black"
  • 37. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Clicked="SignInButton_Clicked"/> </Grid> </StackLayout> </ContentPage.Content> </ContentPage> view rawLoginPage.xaml.cs hosted with ❤ by GitHub Y el code-behind es: using System; using Xamarin.Forms; using Xamarin.Forms.Xaml; using MyStore.Services; using MyStore.Models; namespace MyStore.EmployeesApp.Pages { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class LoginPage : ContentPage { public LoginPage () { InitializeComponent (); } public async void SignInButton_Clicked(object sender, EventArgs e) { var username = UserNameEntry.Text; var password = PasswordEntry.Text; var employee = await StoreWebApiClient.Instance.Login(username, password);
  • 38. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información if (employee != default(EmployeeDTO)) { App.CurrentEmployee = employee; await DisplayAlert("Welcome!", $"Welcome {employee.FullName}", "OK"); await Navigation.PushAsync(new CustomerListPage()); } else { await DisplayAlert("Error!", "Wrong credentials!", "OK"); } } } } view rawLoginPage.cs hosted with ❤ by GitHub Paso 22. Ahora agrega un nuevo Content Page (sobre la carpeta Pages) llamado CustomerListPage que mostrará la lista de clientes registrados (y un botón para agregar un nuevo cliente). Además, si se selecciona un cliente se navegará a otra página para conocer su detalle. El código XAML es el siguiente: <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MyStore.EmployeesApp.Pages.CustomerListPage"> <ContentPage.Content> <StackLayout BackgroundColor="White"> <Label Text="Customer List" TextColor="Black" FontSize="Large" Margin="15"/> <ActivityIndicator x:Name="indicator" Color="Green" VerticalOptions="Center" HorizontalOp <ListView x:Name="CustomersListView" ItemSelected="CustomersListView_ItemSelected" HasUne <ListView.ItemTemplate> <DataTemplate> <ViewCell> <Label Text="{Binding FullName}" FontSize="Medium"
  • 39. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información LineBreakMode="WordWrap" TextColor="Black" Margin="10"/> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage.Content> <ContentPage.ToolbarItems> <ToolbarItem x:Name="AddButton" Text="Add" Order="Primary" Priority="0" Clicked="AddButton_Cl </ContentPage.ToolbarItems> </ContentPage> view rawCustomerListPage.xaml.cs hosted with ❤ by GitHub Y el code-behind es. using System; using Xamarin.Forms; using Xamarin.Forms.Xaml; using MyStore.Models; using MyStore.Services; namespace MyStore.EmployeesApp.Pages { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class CustomerListPage : ContentPage { public CustomerListPage () { InitializeComponent (); }
  • 40. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información protected async override void OnAppearing() { base.OnAppearing(); Loading(true); CustomersListView.ItemsSource = await StoreWebApiClient.Instance.GetItems<CustomerDTO>("C Loading(false); } void Loading(bool show) { indicator.IsEnabled = show; indicator.IsRunning = show; } private async void CustomersListView_ItemSelected(object sender, SelectedItemChangedEventArgs { try { var item = (CustomerDTO)e.SelectedItem; await Navigation.PushAsync(new CustomerPage(item)); CustomersListView.SelectedItem = null; } catch (Exception ex) { } } public async void AddButton_Clicked(object sender, EventArgs e) { await Navigation.PushAsync(new CustomerPage(new CustomerDTO())); } } } view rawCustomerListPage.cs hosted with ❤ by GitHub
  • 41. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 23. Nuevamente agregamos un Content Page dentro de la carpeta Pages llamado CustomerPage que mostrará el detalle del cliente seleccionado en la pantalla previa para editar sus datos o permitirá agregar un nuevo cliente (si se seleccionó esta opción en la página anterior). Se tienen 3 botones: Register (para guardar cambios), ViewOrders (para mostrar las órdenes del cliente -aunque de momento solo se navegará a la página-) y Delete (para eliminar el cliente, previa confirmación). El código XAML es el siguiente: <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MyStore.EmployeesApp.Pages.CustomerPage"> <ContentPage.Content> <StackLayout BackgroundColor="White"> <Label Text="Customer Details" TextColor="Black" FontSize="Large" Margin="15"/> <StackLayout Padding="15"> <Label Text="First Name: " TextColor="Blue" FontSize="Large"/> <Entry x:Name="FirstNameTextBox" Text="{Binding FirstName}" TextColor="White" Placeholder="First Name" PlaceholderColor="LightGray" BackgroundColor="Black" FontSize="Medium"/> </StackLayout> <StackLayout Padding="15"> <Label Text="Last Name: " TextColor="Blue" FontSize="Large"/> <Entry x:Name="LastNameTextBox" Text="{Binding LastName}" TextColor="White" Placeholder="Last Name" PlaceholderColor="LightGray" BackgroundColor="Black" FontSize="Medium"/> </StackLayout> <StackLayout Padding="15"> <Label Text="UserName: " TextColor="Blue" FontSize="Large"/> <Entry x:Name="UserNameTextBox" Text="{Binding UserName}" TextColor="White" Placeholder="User Name" PlaceholderColor="LightGray" BackgroundColor="Black" FontSize="Medium"/> </StackLayout>
  • 42. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información <ActivityIndicator x:Name="indicator" Color="Green" VerticalOptions="Center" HorizontalOp </StackLayout> </ContentPage.Content> <ContentPage.ToolbarItems> <ToolbarItem x:Name="RegisterButton" Text="Register | " Order="Primary" Priority="0" Clicked= <ToolbarItem x:Name="ViewCustomerOrdersButton" Text="Orders | " Order="Primary" Priority="1" <ToolbarItem x:Name="DeleteButton" Text="Delete | " Order="Primary" Priority="2" Clicked="Del </ContentPage.ToolbarItems> </ContentPage> view rawCustomerPage.xaml.cs hosted with ❤ by GitHub Y el code-behind es. using System; using Xamarin.Forms; using Xamarin.Forms.Xaml; using MyStore.Models; using MyStore.Services; namespace MyStore.EmployeesApp.Pages { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class CustomerPage : ContentPage { public CustomerPage (CustomerDTO item) { InitializeComponent (); this.BindingContext = item;
  • 43. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información if (item.Id == 0) { this.ToolbarItems.RemoveAt(2); this.ToolbarItems.RemoveAt(1); } } void Loading(bool show) { indicator.IsEnabled = show; indicator.IsRunning = show; } async void RegisterButton_Clicked(object sender, EventArgs e) { Loading(true); var item = (CustomerDTO)this.BindingContext; if (item.Id > 0) await StoreWebApiClient.Instance.PutItem<CustomerDTO>("Customers", item, item.Id); else { item.Password = MD5Security.ToMD5Hash("abc"); await StoreWebApiClient.Instance.PostItem<CustomerDTO>("Customers", item); } Loading(false); await DisplayAlert("Success", "Item registered!", "OK"); await Navigation.PopAsync(); } async void ViewCustomerOrdersButton_Clicked(object sender, EventArgs e) { var item = (CustomerDTO)this.BindingContext;
  • 44. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información await Navigation.PushAsync(new CustomerOrderListPage(item)); } async void DeleteButton_Clicked(object sender, EventArgs e) { if (await DisplayAlert("Warning!", "Do you really want to delete this item?", "Yes", "No")) { Loading(true); var item = (CustomerDTO)this.BindingContext; var op = await StoreWebApiClient.Instance.DeleteItem<CustomerDTO>("Customers", item.Id); Loading(false); if (op) { await DisplayAlert("Success!", "Item deleted!", "OK"); await Navigation.PopAsync(); } else { await DisplayAlert("Error!", "Item was not deleted!", "OK"); } } } } } view rawCustomerPage.cs hosted with ❤ by GitHub Paso 24. Ya casi para terminar, agrega un nuevo Content Page (sobre la carpeta Pages) llamado CustomerOrderListPage que de momento tendrá el código XAML por default. Solo se hará un pequeño cambio en el constructor en el código de C# respectivo, el cual se muestra a continuación:
  • 45. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información using System; using Xamarin.Forms; using Xamarin.Forms.Xaml; using MyStore.Models; namespace MyStore.EmployeesApp.Pages { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class CustomerOrderListPage : ContentPage { public CustomerOrderListPage (CustomerDTO item) { InitializeComponent (); } } } view rawCustomerOrderListPage.cs hosted with ❤ by GitHub Paso 25. Modifica el archivo App.xaml.cs de la siguiente manera: using System; using Xamarin.Forms; using MyStore.Models; namespace MyStore.EmployeesApp { public partial class App : Application
  • 46. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información { public static EmployeeDTO CurrentEmployee; public App () { InitializeComponent(); MainPage = new NavigationPage(new Pages.LoginPage()); } } } view rawApp.xaml.cs hosted with ❤ by GitHub Paso 26. Finalmente, da clic derecho sobre el proyecto que deseas probar, por ejemplo en este caso, el de Android y selecciona la opción Establecer como proyecto de inicio.
  • 47. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Paso 27. Compila y ejecuta la aplicación. Realiza varias pruebas para verificar el correcto funcionamiento de la misma. Inicio de sesión:
  • 48. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Lista de Clientes:
  • 49. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Agregar un cliente:
  • 50. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información
  • 51. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Editar datos del cliente:
  • 52. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información Eliminar un cliente:
  • 53. Mg. Luis FernandoAguas Universidad Israel Cienciasde la Ingeniería Carrera de Sistemasde Información