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:
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: