viernes, 14 de febrero de 2020

Angular CRUD con WEB API VB.NET usando MongoDB. Parte II. Angular y Bootstrap

Ya que tenemos lista nuestra API, lo siguiente es trabajar en Angular. Procedemos a crear un nuevo proyecto desde la consola de Node JS:

1.-Creación de Proyecto, Instalación Bootstrap y complementos

ng new CrudwithMongoDB

Después nos posicionamos en nuestra carpeta de proyecto e instalemos algunas cosas que necesitaremos:

npm install bootstrap --save
npm install --save ngx-pagination
npm i ng2-search-filter --save
npm install jquery
npm install popper.js

Instalamos Bootstrap que es framework de desarrollo orientado a la capa de presentación, es decir que sirve para darle más vista a nuestros desarrollos. Además jquery y popper, que son usados por Bootstrap. De esa manera podemos prescindir de mucho código CSS, ya que Bootstrap tiene plantillas y estilos predefinidos.

Después, localiza el archivo angular.json en tu carpeta raíz de proyecto, vamos a editarlo así:

Como puedes ver en la sección styles se puso el CSS de Bootstrap. Además en la sección scripts se añadieron jquery y popper, además de bootstrap. De esa manera haz incluido Bootstrap en Angular.

Además de Bootstrap se instalo el modulo de paginación para que se haga la paginación de nuestros resultados, y el modulo de filtrado para búsquedas.

2.-Clase Modelo y Servicio

Creemos ahora una clase:

ng g class empleado

Esta clase representa nuestro modelo de datos, y debe ser compatible con la clase de nuestra API. Modificamos el archivo empleado.ts:

Posteriormente creamos dos componentes:

ng g c empleado
ng g c agregaempleado

Además de los componentes, agregaremos un servicio:

ng g s emprecord

Recordemos que el servicio es el que hará el trabajo de obtener los datos. Veamos como queda nuestro archivo emprecord.service.ts:


Como vemos importamos Observable , que me permite usar este tipo de dato necesario para transferencia de datos HTTP. Un observable tiene mucha relación con programación reactiva. Mediante el observable nos podemos suscribir a eventos que nos permiten hacer cosas cuando cambia lo que se esté observando.

Se puede decir que la programación reactiva es la programación con flujos de datos asíncronos.Para más información sobre programación reactiva, están estos enlaces:


Para eso Microsoft creo Reactive Extensions (Rx) que es una librería para implementar la programación reactiva, creando aplicaciones que son capaces de usar el patrón observable para gestionar operaciones asíncronas. Por su parte RxJS es la implementación en Javascript de ReactiveExtensions, una más de las adaptaciones existentes en muchos otros lenguajes de programación.

Además importamos HttpHeaders y HttClient para comunicarnos con el web service. Y nuestra clase modelo.

Tenemos un constructor y el método InsertEmployee, que hace la llamada a la API vía POST. Es importante notar que se usará el mismo para agrega uno nuevo o actualizar, el id identificará cual es el caso.

El método GetEmployeeRecord obtiene todos los empleados haciendo GET a nuestra API.

Como vemos los métodos GetEmployeeById y DeleteEmployee se usan sobre la misma URL de nuestra API, se distingue por el uso de acciones HTTP. En el caso del GET se retorna un objeto de tipo Empleado.

3.-Componente Agregaempleado


Veamos ahora nuestro componente para agregar empleados:


Hacemos los import necesarios, incluyendo nuestro servicio y clase modelo. Tenemos algunas variables de componente, incluyendo el id del empleado que por default es "0". E inicializamos el servicio.


Este método en sí es el que nos permite hacer el Insert , haciendo un subscribe a nuestro servicio, mandandole la clase empleado. Como vemos al hacer submit se envían los valores a nuestro método. Dependiendo de el id que mandé es una inserción o actualización. Una vez hecha, cambiamos al componente principal que es empleado.


El método EmployeeEdit me permite editar un empleado, por que uso la misma forma para las dos operaciones. En este caso, recibo un id, que envío a mi servicio para obtener un empleado. Si lo recibo, actualizo los datos de mi FormGroup, con los valores de mi empleado.

Algo que podrás notar es el uso de debugger, es una instrucción de JavaScript que indica que si tienes abierta la consola (Herramientas para desarrollador) hace un punto de interrupción y permite ejecutar el código paso a paso.

El método clearForm simplemente limpia mi FormGroup.


Finalmente en OnInit, inicializo mi FormGroup, recupero el Id, si es diferente de null, invoco el metodo EmployeeEdit ya que es una edición.

Veamos ahora su HTML:



Como vemos es un simple formulario.

4.- Componente Empleado

Este será nuestro componente principal:


Hacemos nuestros import y declaramos algunas variables. Inicializamos el servicio. Y programamos un método que cargue el listado del empleados, usando nuestro servicio.


En el caso del método EmployeeEdit permite editar un empleado, mandando llamar nuestro componente para agregar empleados pero seteando el id a usar.

El método Deleteemploye primero pide confirmación y luego manda llamar a mi servicio, en caso de eliminar exitosamente el empleado manda un mensaje de éxito.

Finalmente en ngOnInit se manda llamad Loademployee para cargar el empleado.

Veamos el HTML:


Este HTML nos permite agregar un empleado, así como hacer búsquedas.


Luego contiene una tabla con los empelados. Esta se carga con el array recibido del servicio usando *ngFor. Además tiene el filtro y la paginación.

Así como botones para editar y borrar.

5.- Routing, app.module y app.component


Como esta app es más compleja, necesitaremos el routing. Así quedará nuestro archivo app-routing.module.ts:


A pesar de que parece un enrutamiento sencillo, hay que tomar en cuenta que con path:"**" le decimos que nuestro componente default será EmpleadoComponent. Es decir nuestra página de Inicio.

Ahora veamos los modulos que usaremos:


Y finalmente nuestro app.component que ahora no tiene mucho:


Y menos el HTML:

<router-outlet></router-outlet>

Esto solo indica que el resultado de router se pone ahí. Veamos ahora la app fucional:

6.- Resultado



Como vemos Bootstrap le da un toque muy profesional, además con la paginación y el filtrado tiene más funcionalidad. Esa es una ventaja de Angular y Bootstrap , crear aplicaciones web con una buena presentación y con poco código, sin meternos mucho en CSS.


Y listo así tenemos nuestra app Angular, comunicándose con un API en VB.NET con MongoDB y usando Bootstrap para la presentación.

Angular CRUD con WEB API VB.NET usando MongoDB. Parte I. MongoDB y Web API

Ahora que ya sabemos crear WEB APIS, vamos a hacer un ejercicio usando BD. Pero ahora no nos vamos a ir por las clásicas MariaDB o SQL-SERVER. Queremos usar MongoDB. Este es el ejemplo base del cual nos basamos, escrito en C#.

Instalación MongoDB


MongoDB es una base de datos documental, lo que significa que almacena datos en forma de documentos tipo JSON. Es sistema de base de datos NoSQL orientado a documentos de código abierto. Una mayor definición de NoSQL, aquí.

En lugar de guardar los datos en tablas, tal y como se hace en las bases de datos relacionales, MongoDB guarda estructuras de datos BSON (una especificación similar a JSON) con un esquema dinámico, haciendo que la integración de los datos en ciertas aplicaciones sea más fácil y rápida. Por supuesto al no ser una BD relacional , no garantiza ACID por lo que no es idónea para todos los sistemas, pero permite ingresar y consultar grandes volúmenes de datos con rapidez, es idónea para aplicaciones WEB de grandes volúmenes de datos donde la consistencia de los mismos no es prioridad (Facebook por ejemplo):

Así que primero la instalaremos. Para ello tenemos este enlace.
Solamente daremos click en Download y se nos bajara un instalador. Luego procedemos a realizar la instalación de MongoDB haciendo doble click:


Podemos dejar todas las opciones predeterminadas. Con eso se instalará nuestra BD. Ahora bien necesitaremos un cliente para accederla. Usaremos Robo3T que puede ser descargado de aquí.

Una vez descargado el instalador, procedemos a su instalación.


Una vez instalado, abrimos nuestro cliente Robo3T. Para empezar haremos la conexión a la BD.


Como vemos es muy sencilla, solo especificamos un nombre, la dirección es localhost en el puerto 27017.

Una vez conectamos creamos nuestra BD. 

Como vemos en el panel derecho aparece nuestra conexión.

Damos click secundario y elegimos Create Database. Y después le damos nombre a nuestra Base de Datos.

Ahora que ha sido creada, podemos empezar a trabajar con ella.

Sin embargo necesitamos algo más: una colección.

Las colecciones en MongoDB son análogas a las tablas de una BD relacional, son contenedores donde podemos guardar Documentos.

Recordemos que MongoDB guarda documentos en ves de registros, cada documento a su vez puede contener datos complejos, formados por campos simples, además de arrays y otro tipo de datos (incluso otros documentos o arreglos de documentos). Todo en formato JSON.

Otra particularidad de MongoDB es que las colecciones no tienen un esquema, ya que cada documento puede tener diferentes campos, los datos que guarda no tienen por que ser homogéneos.

Creemos entonces una colección: click derecho en nuestra BD, luego elegimos Create Collection.

En la siguiente pantalla solo nombramos nuestra coleccion:


Ya tenemos todo listo. Ahora bien antes de proseguir, veamos solo un ejemplo de un documento en MongoDB

var mydoc = {
               _id: ObjectId("5099803df3f4948bd2f98391"),
               name: { first: "Alan", last: "Turing" },
               birth: new Date('Jun 23, 1912'),
               death: new Date('Jun 07, 1954'),
               contribs: [ "Turing machine", "Turing test", "Turingery" ],
               views : NumberLong(1250000)
            }

Aunque hay similitudes con una base de datos relacional, vemos las diferencias. Por ejemplo el campo name se compone a su vez de dos campos, first y last; esto es imposible en una BD relacional, debemos usar dos campos. Otro ejemplo contribs tiene un array de strings. En una base de datos relacional esto es imposible: debemos usar dos tablas extra, una para guardar los datos de contribs y otra para hacer la relación con nuestra tabla principal (así se normaliza un arreglo). 

En MongoDB la ventaja es la velocidad, leer los datos de Alan Turing será mucho más rápido que una BD relacional pues no tiene que unir diversas tablas, todo se guarda en el mismo documento. Pero si estos datos estuvieran a la vez relacionados con otros, sería imposible relacionarlos.

Como su nombre lo dice, una BD relacional es especial para obtener relaciones entre los datos. Pensemos que ahora el array lista una serie de materias, que pueden cursar varios estudiantes. En este caso el modelo documental no nos garantiza consistencia de datos, un alumno puede tener una materia llamada "español" y otro una llamada "Español" y serían diferentes. Además de que relacionar todos los alumnos que cursan una determinada materia, se vuelve más complicado.

Es por eso que ambos modelos, son para escenarios diferentes.

Crear WEB API EN VB.NET

Para iniciar crearemos un proyecto ASP.NET WEB API, como hemos hecho anteriormente. Y en la consola de paquetes Nuget, ejecutamos lo siguiente:

Install-Package MongoDB.Driver
Install-Package Microsoft.AspNet.WebApi.Cors

De esta manera instalamos el driver para MongoDB y además el paquete para CORS.

Ahora modificaremos el archivo Web.config y añade lo siguiente:

Es decir nuestra cadena de conexión. También modificamos el archivo WebApiConfig.vb para añadir CORS:

 Además creamos nuestro modelo de clases:


Debemos notar que para nuestro modelo importamos MongoDB.Bson. Esto por que usamos  la anotación <BsonRepresentation(BsonType.ObjectId)> que identifica uno de nuestros campos como ObjectId. Este campo es necesario para todo documento de MongoDB , hablaremos de el mas adelante. Ya con esto solo falta nuestro controlador, empecemos con los Imports:


Este controlador nos va a permitir hacer las acciones básicas, y necesitaremos el driver de MongoDB para ejecutar estas operaciones sobre la Base de Datos.


El primer método que analizamos es el GET. Este se activa cuando queremos ver todos los empleados. Usamos nuestra cadena de conexión y creamos un cliente Mongo. Luego nos posicionamos en la DB empleado. Después obtenemos una colección, con una lista de todos nuestros documentos. Y lo pasamos a JSON como respuesta.


El método para obtener por id es muy similar, pero creamos un filter, que nos permitirá filtrar por el id.

Aquí hay que puntualizar algo : MongoDB utiliza un tipo especial de id, diferente a lo que podría ser una llave primaria de una BD relacional, que es un simple consecutivo. Quizá debido al gran volumen de transacciones, el caso es que es más complicado de manejar.

Este es un campo que como dijimos se llama ObjectId con un valor hexadecimal. Y es un poco más complejo hacer consultas con el mismo que con un string, en el caso de nuestro filter, tuvimos que usar ObjectId.Parse para convertir nuestro string en un ObjectId e indicarle al filtro que íbamos a buscar por ese tipo de dato. En el caso del método Eq, debemos especificar el tipo de dato a buscar entre paréntesis, antes de definir el nombre del campo y el valor a buscar.

Luego buscamos con el método Find usando nuestro filter. De es manera devolvemos un único documento en formato JSON.

El método para POST es más complicado:




En este caso hicimos un único método, que maneja inserción y actualización de registros vía POST. Así nos ahorramos el PUT. En realidad....ya viste el truco verdad: por más que tu mandes una acción HTTP, en realidad el controlador decide que hace, es donde realmente se controla el acceso a los datos. Es decir aquí implementamos la lógica de negocio, podemos hacer validaciones, actualizar múltiples tablas...en fin.

En este caso controlamos la actualización e inserción con el id, cuando nos llega con valor "0" indica una inserción, cuando tiene un valor indica actualización.

Recordemos que el ObjectId de MongoDB es especial, así que lo mejor es dejar que lo genere la propia BD. Por eso seteamos el valor del objeto.Id en nulo. De esa manera MongoDB lo genera en automático. Finalmente con el método InsertOne insertamos nuestro documento.

Para la actualización es similar, pero primero debemos encontrar el documento a actualizar. Para eso de la misma manera necesitamos un filtro por el ObjectId, esta vez el filtro lo incluimos en el método FindOneAndUpdateAsync que recibe el filtro, además Builders(Of Empleado).Update.Set que nos permite actualizar los campos. Es importante notar que el método Set debe indicarsele que tipo de dato se actualizará (Of String), el nombre del campo y el valor a actualizar. Quedaría así:

Dim update = Collection.FindOneAndUpdateAsync(Builders(Of Empleado).Filter.Eq(Of ObjectId)("Id", ObjectId.Parse(objVM.Id)), Builders(Of Empleado).Update.Set(Of String)("Nombre", objVM.Nombre).Set(Of String)("Departamento", objVM.Departamento).Set(Of String)("Direccion", objVM.Direccion).Set(Of String)("Ciudad", objVM.Ciudad).Set(Of String)("Pais", objVM.Pais))

De esta manera completamos el POST. Quedaría solo ver el DELETE:


Para el DELETE es muy parecido, solo usamos DeleteOneAsync. Además le indicamos con el filtro cual borrar.

Y con eso ya tenemos nuestra API WEB VB.NET usando una BD MongoDB.




lunes, 10 de febrero de 2020

Angular consumiendo WEB API creada en VB.NET : POST,PUT, DELETE. WEB API Parte IV.


Ya que logramos crear nuestra primer app Angular que consume una API hecha en VB.NET , agreguemos más funciones. En concreto agreguemos las operaciones POST, PUT y DELETE, y una pequeña interfaz gráfica a nuestra app Angular.

Para eso, primera debemos modificar nuestro API para hacer más sencillo su acceso. Primero abrimos el archivo Web.config y añadimos lo siguiente:


Este header es para que se acepten todos los métodos que necesitamos. Y es que por default, si habilitamos CORS los métodos GET funcionan, pero el método PUT o POST no se desbloquean tan fácil.

Es por eso que también modifique mi archivo WebApiConfig para poder usar CORS de manera global:


Para poder usar CORS es importante usar este Import:

Imports System.Web.Http.Cors

Otra cosa que debemos tener en cuenta es que CORS solo esta habilitado para la ruta raíz de nuestra API: https://localhost:44355/api/Personas/. Si añadimos otras dirección, por ejemplo con  <Route> para redirigir los métodos, estás no tendrás habilitado CORS. Así que de momento haré todas las operaciones sobre la misMa dirección, lo que las diferencia son los verbos HTTP

Con esto en mente, nuestra API esta terminada. Ahora veamos que modificaremos en nuestra App Angular. Primero en cuanto a los servicios:


Como podemos observar creamos 3 métodos nuevos. En dos recibimos una clase PersonaModel, y en otro, solo el id. Además para el POST y el PUT usamos un header, este header indica que en vez de una dato simple, estaremos anexando un JSON, que contendrá nuestro objeto Persona.

Al invocar el PUT y el POST, pasamos como parámetros nuestro header y nuestro objeto, Angular lo formatea en automático a JSON.

Para el DELETE solo anexamos el id tal como haríamos en el GET, en este caso se diferencian solo por el verbo.

Veamos ahora nuestro componente:

Como vemos tengo un arreglo de objetos persona y un objeto persona que usaré para manipular los datos. Además en ngOnInit, al iniciar mi componente, recupero todo mi listado de personas con el método recuperarTodos de mi servicio que hace un GET de todos los registros.

El método seleccionar, ejecuta el GET pero solo de una persona. Veamos como implemento los demás métodos:


Como vemos cada componente solo manda llamar el método de mi servicio. Y uso el objeto person como contenedor, ya sea de una nueva persona o de una actual para modificar. Cuando finaliza la operación solo utilizo un alert para avisar.

Veamos ahora la plantilla HTML:


Como vemos es más compleja. Uso un *ngIf para asegurarme de que haya registros, si los hay itero sobre mi arreglo personas con un *ngFor y creo una tabla con el detalle. Hay un botón para borrar el registro y otro para seleccionarlo, en caso de seleccionarlo se hará el GET por id y mostraré el resultado en los campos de abajo.

En la parte inferior tengo una serie de campos, que usaré para editar registros o crear nuevos.

De esta manera al final tengo un par de botones , uno para agregar y otro para modificar. Ya que uso [(ngModel)] se hace un binding de el contenido de los campos con mi objeto person. Así que siempre tengo contenidos los datos que necesito.

El resultado ya en ejecución, se ve así:




jueves, 6 de febrero de 2020

Consumir un WEB API VB.NET con Angular. WEB API Parte III.

Ahora que tengo una WEB API desarrollada, deseo consumirla con una aplicación Angular. Pudiera sonar sencillo, pero no lo es tanto.

Empecemos por lo primero, para que tu WEB API pueda ser consumida desde otra aplicación, debes habilitar CORS.   Y es que cuando se abre una página web, cargar datos de servidores ajenos está, en teoría, estrictamente prohibido.

Pero si los administradores de ambas webs han acordado trabajar juntos, no hay por qué evitar el intercambio. En estos casos, el llamado cross-origin resource sharing (CORS) regula la colaboración. La same-origin policy (SOP o política de seguridad del mismo origen) prohíbe que se carguen datos de servidores ajenos al acceder a una página web. Todos los datos deben provenir de la misma fuente, es decir, corresponder al mismo servidor.

Pero en el caso de las WEB API, nuestro deseo es que precisamente permitan intercambiar datos con otros servidores. En este caso  nuestra WEB API puede permitir entonces el acceso mediante cross-origin resource sharing, en castellano, intercambio de recursos de origen cruzado. ¿Como podemos habilitar CORS en una API .NET?

Habilitar CORS WEB API


En primer lugar, debemos instalar un paquete vía NuGet.  Para ello necesitamos abrir nuestra Consola del Administrador de paquetes, que se encuentra en el Menú Herramientas-> Adminstrador de paquetes NuGet:


Una vez abierta nuestra consola ejecutamos el siguiente comando:

Install-Package Microsoft.AspNet.WebApi.Cors

Que nos hará la instalación del paquete que necesitamos para habilitar CORS.


Una vez hecho esto, tenemos que modificar un par de archivos de nuestra API. Primero el archivo WebApiConfig.vb que se encuentra en la carpeta App_Start.


Como podrás notar en este archivo solo se añadió la línea config.EnableCors, que habilita el uso de CORS en nuestro proyecto.

El segundo archivo que debemos modificar es nuestro controlador.


En este caso solo agregue la línea :

<EnableCors("*", "*", "*")>

Esta línea habilita el uso de CORS para mi controlador. Puedo hacerlo para mi controlador, como lo hice en este caso o para un método solamente, poniendo esa línea arriba del método. O incluso de manera global, poniendo las siguientes líneas en el archivo WebApiConfig.vb

dim cors = new EnableCorsAttribute("*", "*", "*");
 config.EnableCors(cors);

Ahora bien, el método EnableCors recibe 3 valores por defecto:

El primero es origins, donde podemos definir los servidores desde los que permitiremos el acceso. En al usar el comodín *, estoy permitiendo acceso desde cualquier servidor, pero no se recomienda hacer esto.

El segundo parámetro es headers , que especifica que headers son permitidos. Por ejemplo:
"accept,content-type,origin,x-my-header"

El tercer parámetro es methods, que nos permite especificar para que métodos permitimos CORS, por ejemplo: "get,post".

Con esto nuestra WEB API ya permite acceso remoto. Procedamos ahora con Angular.

Crear Aplicación Angular


Como quizá ya sabes, el primer paso es crear la aplicación en la consola de Node JS, con el comando:

ng new ConsumeAspNetWebAPI

Una vez creado nuestro directorio, posicionate en la carpeta /src/app/

Después crea un carpeta llamada model. En esta carpeta crearemos una clase que será el modelo, debe ser un espejo de nuestra clase modelo en .NET. Puedes crearla posionandote en el carpeta model que acabas de crear en la consola de Node JS y ejecutando este comando:

ng g class personaModel

Eso creara los archivos de nuestra clase. Abre el archivo persona-model.ts y pon el siguiente código:

Como puedes ver usamos los mismos campos que en VB.NET por supuesto, con las consiguientes conversiones de tipos.

Ahora crearemos un servicio para consumir nuestra web api. Para eso dentro de /src/app/ crea una carpeta llamada services. Y posicionate dentro de esa carpeta en la consola Node JS para ejecutar este comando:

ng g service persona

Con eso se crea tu servicio. Abre el archivo persona.service.ts y editalo así:


Algunas cosas importantes, hacemos el import de HttpClient, es muy impotante ya que es el modulo que nos permite la comunicación para realizar la petición GET al WEB API. Además usaremos la clase PersonaModel. En este caso, yo copie la carpeta model dentro de la carpeta services para poder usarla. Pero podrías tener ambos archivos typescript (servicio y clase) y también funcionaría.

También importamos 'rxjs/add/operator/map'. Para importar este componente primero debemos ejecutar en la consola de Node JS:

npm install --save rxjs-compat

Lo más importante aquí es el método GetAllMembers. En este ejecuto sobre mi objeto http de tipo HttpClient un get, casteando lo obtenido a un array de objetos PersonaModel. De esta manera puedo usarlo en el resto de mi aplicación. Le paso la url de mi API, puedes notar que es la misma con que probamos del navegador en el ejemplo inicial.

Ahora veamos como queda el archivo app.module.ts, donde importaremos los elementos a usar:


Como vemos solo importo mi servicio, además del HttpClientModule. Veamos ahora el archivo app.component.ts 


Como vemos importo mi servicio y además mi clase de modelo. En el código propiamente dicho, creo un array de objetos PersonaModel. Luego en el constructor, inicializo un objeto PersonaService, y después ejecuto el método GetAllMembers().subscribe. Esto me regresará un array de personas, que lo asigno a mi propiedad del mismo tipo de mi componente. Y listo es todo.

Pasemos finalmente a la vista. Ya que tenemos nuestros datos, solo tenemos que mostrarlos:

Usando un ciclo *ngFor leemos nuestro array y lo mostramos. Así de sencillo ya consumimos nuestra API. Ahora veamos el resultado:




Angular CRUD con WEB API VB.NET usando MongoDB. Parte II. Angular y Bootstrap

Ya que tenemos lista nuestra API, lo siguiente es trabajar en Angular. Procedemos a crear un nuevo proyecto desde la consola de Node JS: ...