Construyendo un Dashboard con ASP.NET Core y DotVVM
Published: 2020-10-20 23:58:45

Un dashboard o tablero de operaciones es una herramienta que sirve para visualizar y dar seguimiento a determinados indicadores de desempeño o estado. Condensa en un solo lugar la información crítica de una máquina, una empresa, una estrategia, etc.

Existen dashboards con objetivos muy diferentes. Desde los más estratégicos, a los más tácticos. En este caso, vamos a ver de forma práctica como diseñar un dashboard para manejar los datos de los usuarios registrados en una base de datos. Esto lo realizaremos sobre ASP.NET Core y DotVVM, adaptando estilos CSS y algunos componentes JavaScript para el diseño de nuestro portal administrativo. 

El resultado final será el siguiente:

![](https://dev-to-uploads.s3.amazonaws.com/i/medhw019u8t69k7ug5ft.png)

Nota: El código fuente de este proyecto puede ser encontrado en el siguiente repositorio de GitHub: [User Dashboard](https://github.com/esdanielgomez/UserDashboard).  

##**1. Recursos y herramientas necesarias**

Para la construcción del dashboard es necesario utilizar un marco de trabajo que nos permita comunicarnos con la base de datos y administrar los datos correspondientes. En este sentido y aprovechando el aumento de la popularidad del ecosistema de .NET, utilizaremos ASP.NET Core a través del patrón MVVM (Modelo Vista Vista-Modelo) por medio de DotVVM y con una base de datos relacional, en este caso, con PostgreSQL. 

Dadas estas consideraciones, los recursos y herramientas necesarias para establecer nuestro entorno de trabajo son las siguientes: 

+ Visual Studio 2019: [http://visualstudio.microsoft.com/es/downloads/](http://visualstudio.microsoft.com/es/downloads/).
+ La carga de trabajo en Visual Studio 2019: Desarrollo de ASP.NET y web.

![](https://dev-to-uploads.s3.amazonaws.com/i/pn0mcltcahya0e4q3r14.png)

+ Extensión de DotVVM para Visual Studio 2019: [www.dotvvm.com/landing/dotvvm-for-visual-studio-extension](www.dotvvm.com/landing/dotvvm-for-visual-studio-extension).
+ PostgreSQL: [https://www.postgresql.org/download/](https://www.postgresql.org/download/).

Muy bien, si ya tenemos estas herramientas instaladas, una buena opción para empezar a construir nuestro dashboard es buscar una plantilla de esta naturaleza que nos ayude con elementos y estilos ya predefinidos. 

En la web podemos encontrar múltiples plantillas sobre dashboards para adaptarlas a nuestras necesidades, algunas gratuitas y otras de pago. Estos son algunos ejemplos:  

![](https://dev-to-uploads.s3.amazonaws.com/i/t0jk2xrw4lcllh8vc3eu.png)

En este caso utilizaremos la plantilla Material Dashboard. Este es un recurso gratuito basado en Bootstrap 4 con un diseño inspirado en las fuentes de Google.

![](https://dev-to-uploads.s3.amazonaws.com/i/xlt2qsjkwwq087dsp0uc.jpg)

Nota: Esta plantilla puede ser descargada en la siguiente dirección: [https://www.creative-tim.com/product/material-dashboard](https://www.creative-tim.com/product/material-dashboard).

Adicionalmente, puede ser de utilidad tener en cuenta una fuente de iconos que nos permitan acompañar a los enlaces, botones y secciones de nuestro dashboard. Dentro de la base de materiales de diseño de Google, podemos encontrar estos iconos en esta dirección: [https://material.io/resources/icons/](https://material.io/resources/icons/). 

##**2. Entorno de la solución del proyecto**

Para nuestro caso de estudio, ejemplificaremos el diseño de un dashboard al manejar datos de usuarios a través de operaciones CRUD: Crear, Leer, Actualizar y Eliminar. En Visual Studio 2019 tendremos las siguientes secciones: 

![](https://dev-to-uploads.s3.amazonaws.com/i/77mxisve31gwkgv5dilu.png)

Estas secciones tienen los siguientes propósitos: 

+ 1. Implementación DAL (Data Access Layer): para manejar la conexión y el acceso a la base de datos relacional con PostgreSQL. 
+ 2. Implementación BL (Business Layer): para el manejo de los servicios y la lógica del dominio de la aplicación.  
+ 3. Views & ViewModels: Para la implementación de la capa de presentación de la aplicación. En esta sección es donde DotVVM entra en acción para el diseño del dashboard.
+ 4. `wwwroot`: es la carpeta en donde se encuentran todos los elementos estáticos multimedia, por ejemplo, los estilos CSS, las imágenes, archivos JavaScript, entre otros. 
+ 5. `Program`, `Startup` y `DotvvmStartup`: estas son las clases donde se encuentran las configuraciones del proyecto, por ejemplo, las dependencias del proyecto, como son los estilos CSS, la cadena de conexión con la base de datos, los servicios, entre otros parámetros de configuración.   

En las siguientes secciones de este tutorial nos centraremos únicamente en el diseño del dashboard, es decir, de las Views y ViewModels. Si deseas ver cómo crear la capa de acceso a datos y la lógica de la aplicación con una base de datos PostgreSQL, pronto publicaré un artículo al respecto. :)

De forma general, estos son los métodos del servicio ubicado en la capa lógica de la aplicación, los cuales nos permiten trabajar con los datos de la base en PostgreSQL:

+ GetAllUsers.
+ GetCountUsers
+ GetUserByIdAsync
+ InsertUserAsync
+ UpdateUserAsync
+ DeleteUserAsync

Los atributos para manejar los datos de los usuarios son los siguientes:

+ Id.
+ Firstname.
+ Lastname.
+ Username.
+ City.
+ Country.
+ Postalcode.
+ About.
+ Enrollmentdate.

Con esto mencionado, ahora veamos el diseño de nuestro dashboard con DotVVM. 

##**3. Diseño y organización del dashboard**

Para el diseño del dashboard, aquí es donde DotVVM entra en acción. Cada página en DotVVM consta de dos archivos:

+ *Una View*, que se basa en la sintaxis HTML y describe cómo se verá la página. 
+ *Un ViewModel*, que es una clase en C# que describe el estado de la página (por ejemplo, valores en los campos del formulario) y maneja las interacciones del usuario (por ejemplo, clics de botones).

Para nuestro caso tendremos cuatro Views y cuatro ViewModels en el dashboard:

+ *Default*: será la página principal de la aplicación en donde se visualizará el listado de los usuarios registrados. 
+ *Create*: una página conformada por un formulario para crear nuevos usuarios. 
+ *Detail*: para ver a detalle la información de un usuario. 
+ *Edit*: para modificar la información de un usuario o eliminarlo. 

Teniendo en cuenta los archivos Views y Viewmodels, en Visual Studio 2019 visualizaremos algo como esto: 

![](https://dev-to-uploads.s3.amazonaws.com/i/wfsnhhik0v59d7j0wzgz.png)

A continuación, veamos algunos de los componentes principales del dashboard. 

####A.	Masterpage

En DotVVM, las páginas principales o páginas maestras son conocidas como `Masterpage`, cuyos archivos tienen una extensión `.dotmaster`. En este caso, esta página será de utilidad para establecer nuestro esqueleto HTML, importar nuestros archivos CSS & JavaScript, y definir los contenidos que serán visibles en todas las páginas hijas.
  
El `header` de nuestro HTML se verá así:

```html
<head>
    <meta charset="utf-8" />
    <title>Dashboard</title>

    <meta content='width=device-width, initial-scale=1.0, shrink-to-fit=no' name='viewport' />
    <!--     Fonts and icons     -->
    <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Roboto+Slab:400,700|Material+Icons" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css">
    <!-- CSS Files -->

    <dot:RequiredResource Name="Styles" />

</head>
```

Una etiqueta particular es la que se encuentra bajo la sentencia `<dot:RequiredResource Name="Styles" />`. En DotVVM, dentro de la clase de configuración llamada `DotvvmStartUp`, bajo el método `ConfigureResources`, podemos especificar la ubicación de los archivos CSS de nuestro dashboard para que se encuentren organizados en esta sección:

```csharp
private void ConfigureResources(DotvvmConfiguration config, string applicationPath)
{
    config.Resources.Register("Styles", new StylesheetResource()
    {
        Location = new UrlResourceLocation("~/assets/css/material-dashboard.css?v=2.1.2")
    });
}
```

El `MasterPage` con su cuerpo HTML, se visualizará de la siguiente manera:

![](https://dev-to-uploads.s3.amazonaws.com/i/takhrl23ebxcwg8dwni9.png)

Donde, 

+ Sección 1, es el header del HTML donde se encuentra el título de la página, las fuentes CSS y archivos JavaScript referenciados, y otras especificaciones. 
+ Sección 2, corresponde al logotipo de la página, en otras palabras, el título dentro de esta. 
+ Sección 3, es el menú de opciones del dashboard. 
+ Sección 4, es el apartado donde se visualizará todo el contenido de las páginas hijas (listado de registros y los formularios de creación y modificación).

En el dashboard, visualmente los resultados de acuerdo con la numeración de las secciones especificadas previamente son los siguientes:

![](https://dev-to-uploads.s3.amazonaws.com/i/y7ou1yom5z5hort0ejsp.png)

####B. Default

Ahora que ya hemos establecido la estructura que tendrá nuestro portal, ahora veamos una de las páginas hijas o tambien llamadas páginas de contenido, en este caso, la primera sección que será visualizada al cargar el dashboard. 

El objetivo de esta página tiene como objetivo visualizar a través de una tabla los usuarios que se encuentren registrados en la base de datos. En este sentido, en la primera parte de esta página nos encontramos con el ViewModel:

```csharp
public class DefaultViewModel : MasterPageViewModel
{
	public string Title { get; set;}
	public string Subtitle { get; set;}

	private readonly UserService UserService;

	[Bind(Direction.ServerToClient)]
	public List<UserListModel> Users { get; set; }

	public int ContUsers { get; set; }

	public DefaultViewModel(UserService UserService)
	{
		Title = "User dashboard";
		Subtitle = "In this section, you can see the list of users registered in the database.";

		this.UserService = UserService;
	}

	public override async Task PreRender()
	{
		Users = await UserService.GetAllUsersAsync();
		ContUsers = UserService.GetCountUsers();

		await base.PreRender();
	}


}
```
En esta clase del ViewModel definimos el título y subtitulo que va a tener la página. Asimismo, tendremos una instancia de `UserService`, la cual nos permitirá acceder a los métodos para recuperar un listado y un contador de los usuarios registrados de la base de datos a través del servicio `UserService` (implementado en el BL).

En esta misma clase podemos ubicar la definición `List<UserListModel> Users` de tipo `UserListModel` (definido en las clases de los modelos en el BL), que tendrá el listado de los usuarios (`Id`, `Name`, `City`, `Country` y `Enrrolmentdate`) para cargarlos en una tabla en la página principal del dashboard. En este apartado, una declaración interesante es `[Bind(Direction.ServerToClient)]`. Este tipo de propiedades permiten especificar que información va a ser transferida del servidor al cliente o del cliente al servidor al usar los *Binding Directions*. Considerando el caso del listado de los usuarios, en muchas ocasiones no es necesario transferir todo el modelo de vista en ambas direcciones. Del servidor a la vista será suficiente en este caso. 

Finalmente en el Viewmodel de `Default` tenemos el método `PreRender()`, que permite realizar cierto tipo de operaciones que serán llevadas a cabo al momento de cargar la el dashboard. En este caso, se realizarán dos consultas a la base de datos a través de la llamada de los métodos del servicio, el primero `UserService.GetAllUsersAsync()` para registrar a los usuarios en una colección Users de tipo `StudentListModel` y el segundo `UserService.GetCountUsers()` para conocer el número de usuarios registrados. Este último tiene como objetivo el ejemplificar su uso.
 
El segundo apartado corresponde a la View de esta página. 

![](https://dev-to-uploads.s3.amazonaws.com/i/9mwtskpmupbfikz0n6at.png)

En la primera parte nos encontramos con la sentencia `<dot:Content ContentPlaceHolderID="MainContent">`, donde se especifica el identificador de esta página de contenido, el cual está siendo referenciado desde el `MasterPage` a su vez. 

En la segunda parte tenemos un `navbar` donde se muestra el título y subtitulo de esta página de inicio: 

![](https://dev-to-uploads.s3.amazonaws.com/i/0ubhc903ehf6ttxxjkz3.png)

Finalmente, en un tercer apartado tenemos un contador del número de usuarios registrados y la tabla donde se listan estos usuarios.

En la sección del contador solo se muestra el contenido del atributo `ContUsers` establecido en el ViewModel:

```html
<h2 class="card-title">										 
   {{value: ContUsers}}
</h2>	
```

![](https://dev-to-uploads.s3.amazonaws.com/i/qc40woe1m7avhuvdkxga.png)

Esta tabla es diseñada a través de un GridView: `<dot:GridView … >`, un control de DotVVM que nos permite crear una tabla o cuadrilla para visualizar un determinado listado de información. En HTML estaríamos hablando de la etiqueta `<table>`. Uno de sus atributos es `DataSource`: `DataSource="{value: Users}"`, el cual permite especificar la fuente de datos, en este caso hacemos referencia al listado de usuarios: `Users`, el cual fue definido en el Viewmodel como vimos anteriormente.  

```html
<dot:GridView DataSource="{value: Users}" class="table">
	<Columns>

		<dot:GridViewTextColumn ValueBinding="{value: Id}" HeaderText="ID" HeaderCssClass="text-primary" CssClass="text-primary" />
		<dot:GridViewTextColumn ValueBinding="{value: Name}" HeaderText="Name" HeaderCssClass="text-primary" />
		<dot:GridViewTextColumn ValueBinding="{value: Country}" HeaderText="Country" HeaderCssClass="text-primary" />
		<dot:GridViewTextColumn ValueBinding="{value: City}" HeaderText="City" HeaderCssClass="text-primary" />
		<dot:GridViewTextColumn ValueBinding="{value: Enrollmentdate}" HeaderText="Enrollment date" HeaderCssClass="text-primary" />

		<dot:GridViewTemplateColumn>
			<dot:RouteLink Text="" RouteName="Detail" Param-Id="{{value: Id}}" class="btn btn-primary btn-link btn-sm">
				<i class="material-icons">visibility</i> Detail
			</dot:RouteLink>
		</dot:GridViewTemplateColumn>

	</Columns>

</dot:GridView>

```

Siguiendo con nuestro análisis, en el GridView tenemos las columnas `Id`, `Name`, `Country`, `City` y `Enrollmentdate` de los usuarios, pero adicionalmente, nosotros también podemos adicionar columnas para realizar operaciones sobre algún registro en específico. En este caso, con `RouteLink`, podemos definir un hipervínculo que construye una URL a partir de nombres de rutas y valores de parámetros para redirigirnos a otras paginas o realizar operaciones adicionales, por ejemplo, ver en detalle el registro de un usuario en particular según su ID: 

```html
<dot:RouteLink RouteName="Detail" Param-Id="{{value: Id}}" />
```

Estas rutas y sus parámetros correspondientes los tenemos que definir en el archivo `DotvvmStartup.cs` en el método ConfigureRoutes de la siguiente manera:

```csharp
config.RouteTable.Add("Detail", "Detail/{Id}", "Views/Detail.dothtml");  
```

####C.	Operaciones 

Dentro del dashboard, existen otras opciones para crear, modificar y eliminar un registro de un usuario determinado. En este caso, para generalizar, vamos a analizar la página de Crear. Al igual que el Default, la página Create es una que será hija del MasterPage. 

Como su nombre lo indica, esta página tiene como objetivo crear a un nuevo usuario a través de un formulario dentro del dashboard. El resultado es el siguiente:

![](https://dev-to-uploads.s3.amazonaws.com/i/zdjfj610m2e74hkg4tus.png)

En este caso, en el formulario todos los componentes corresponden a cajas de texto para el ingreso de datos. Analicemos uno de ellos, por ejemplo, el campo `Username` en la View será de la siguiente manera:

```html
<div class="col-md-6">
    <div class="form-group" Validator.Value="{value: User.Username}"
            Validator.InvalidCssClass="has-error"
            Validator.SetToolTipText="true">

        <label class="bmd-label-floating">Username</label>
        <dot:TextBox Text="{value: User.Username}" class="form-control" />
    </div>
</div>
```

Aquí podemos comentar dos cosas. La primera que para las cajas de texto podemos utilizar un componente de DotVVM que nos permita asociar un TextBox con un atributo en el ViewModel. 

```csharp
public UserDetailModel User { get; set; } = new UserDetailModel { Enrollmentdate = DateTime.UtcNow.Date };
```

Asimismo, podemos acompañar a este TextBox con un control llamado Validator, el cual nos permita validar ciertas características, por ejemplo, que el campo no pueda ser registrado como nulo. En estos dos componentes podemos agregar especificaciones adicionales, tales como los estilos correspondientes para cada caso. 

El botón para enviar seguirá la misma lógica: 

```html
<dot:Button Text="Insert User" Click="{command: AddUser()}" class="btn btn-primary pull-right" />
```

Este botón, establecido a través de un componente de DotVVM, está llamando a una función establecida en el ViewModel para agregar a un usuario según los datos insertados en el formulario. Esta función se encuentra estructurada de la siguiente manera:

```csharp
public async Task AddUser()
{
    await UserService.InsertUserAsync(User);
    Context.RedirectToRoute("Default");
}
```

En este caso, al insertar el registro satisfactoriamente, desde el ViewModel podemos redirigirnos a la página de Default (página con el listado de usuarios registrados) y visualizar al nuevo usuario insertado en la base de datos y visualizado en el listado general.

Como se menciono anteriormente, las páginas de detalle y edición siguen la misma lógica de diseño en este caso.   

##**¿Qué sigue?**

Con este articulo tutorial hemos aprendido de manera general como trabajar con ASP.NET Core y DotVVM a través de Visual Studio 2019 para el diseño de un dashboard sobre una entidad de usuarios. 

El código de este tutorial lo podemos encontrar en el siguiente repositorio en GitHub: [User Dashboard](https://github.com/esdanielgomez/UserDashboard). 

####Recursos adicionales: 

En la actualidad son muchas las aplicaciones que podemos construir en el ecosistema de .NET, y aún más específicamente en el área del desarrollo páginas web. En este sentido, a continuación, se encuentran algunos recursos adicionales para seguir adquiriendo conocimientos en este campo:

+ [Construcción de páginas web con ASP.NET Core y DotVVM](https://youtu.be/IXde5w4kMho)
+ [Despliegue de aplicaciones web DotVVM y .NET Core en Azure](https://dev.to/dotvvm/despliegue-de-aplicaciones-web-dotvvm-y-net-core-en-azure-44ni).
+ [Trabajando con servicios web a través de ASP.NET Core y DotVVM](https://dev.to/dotvvm/trabajando-con-servicios-web-a-traves-de-asp-net-core-y-dotvvm-4c76). 

####Muchas gracias por leer. 

Si tienes alguna pregunta o alguna idea que necesites discutir, será un gusto poder colaborarte y juntos intercambiar conocimientos entre sí.

¡Nos vemos en [Twitter](https://twitter.com/esDanielGomez)! :)