Construcción de un portal informativo para eventos con ASP.NET 5
Tags: webdev, dotnet, csharp, html
Published: 2021-03-03 14:21:31

En muchas ocasiones, cuando organizamos grandes eventos, necesitamos construir un portal web informativo para poder mostrar a nuestros usuarios los datos de un evento, las sesiones que se tendrá, información sobre los organizadores y patrocinadores, y también una sección para que ellos se puedan registrar. 

Para estos propósitos, en este articulo revisaremos como construir un portal web informativo, con ASP.NET 5, partiendo desde la base de datos, hasta el diseño de la página web correspondiente con una tecnología llamada DotVVM sobre .NET, que nos ayudará con el proceso de diseño.

##**Articulo previo: portal web para la administración del evento**

En un artículo previo pudimos analizar cómo construir un dashboard para administrar los datos de nuestro evento, cuyo portal se veía de la siguiente manera: 

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

El articulo tutorial para construir este dashboard lo puedes encontrar aquí: [Portal web para gestionar eventos y conferencias con ASP.NET 5 y DotVVM](https://dev.to/esdanielgomez/portal-web-para-gestionar-eventos-y-conferencias-con-asp-net-5-y-dotvvm-4m1m).

Y el código fuente en este repositorio en GitHub: [EventAdmin](https://github.com/esdanielgomez/EventAdmin).

##**Secciones de la página web informativa**

Esta página web informativa tiene como único propósito presentar datos al usuario (no se guardará ninguna información desde esta página), cuyas secciones destacadas son las siguientes: 

+ **Sección principal o portada**. Aquí se muestra el título del evento y cierta información general, como la fecha y la ubicación de este. 
+ **Programación del evento**, donde se listan las charlas o conferencias con las cuales contará el evento, junto con los speakers, y las horas de inicio para cada una de estas sesiones. 
+ **Organizadores**, para mostrar de manera general a aquellas comunidades y/o instituciones que están organizando el evento. 
+ **Sponsors**. Aquí se pueden mostrar a aquellos auspiciantes que están dando soporte al evento. 
+ **Registro**, donde se indique o se muestre al usuario donde se pueden registrar para ser parte del evento. 

El resultado final de la página web se verá aproximadamente de la siguiente manera:

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

Ahora que ya estamos al tanto de las secciones que serán incluidas, empecemos a construir nuestro portal web.

##**Estructura de la solución**

Todo parte desde la base de datos donde se encuentra almacenada la información del evento. Para esta plataforma, las entidades en la base de datos son: `Organizer`, `Sponsor`, `Event`, `Speaker`, `Session`, `Speaker_has_Session`, `SessionLevel` y `SessionType`. 

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

***Nota***: Como gestor de base de datos, se ha contemplado utilizar SQL Server.  

Ahora bien, si consideramos a Visual Studio como entorno de trabajo para la construcción de esta página web, en esta solución contaremos con tres proyectos:

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

+ **DAL (Data Access Layer)**: una librería de clases para manejar la conexión y el acceso a la base de datos.
+ **BL (Business Layer)**: otra librería de clases para el manejo de los servicios y la lógica del dominio de la página web.
+ **APP - Capa de presentación de la aplicación**. En esta sección es donde tenemos los Views y Viewmodels para el diseño de la página web del evento con DotVVM.
Con esto en cuenta, ahora analicemos los pasos que debemos seguir en estos tres proyectos para la elaboración de nuestro portal web. 

##**DAL – Capa de acceso de datos**

Este primer proyecto corresponde a una librería de clases. En este sentido, como primera tarea tenemos que relacionar nuestro proyecto con la base de datos en SQL Server. Este objetivo lo podemos lograr con Entity Framework, por medio del enfoque Database-First, de tal manera que podamos generar las clases de las entidades existentes desde nuestra base de datos. 

En este proyecto necesitaremos tres paquetes Nuget:

+ `Microsoft.EntityFrameworkCore.Design`
+ `Microsoft.EntityFrameworkCore.Tools`
+ `Microsoft.EntityFrameworkCore.SqlServer`

Desde la consola de administración de paquetes podemos hacer Scaffold, para generar las clases desde las entidades existentes por medio del siguiente comando:

```
Scaffold-DbContext "Server=YOUR_SERVER; Database=DATABASE_NAME; Username=YOUR_USERNAME; Password=YOUR_PASSWORD Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir DAL/Entities
```

Al completarse el proceso por consola tendremos algo como esto:

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

Hasta aquí, la conexión y las configuraciones necesarias para trabajar con la base de datos SQL Server están listas. 

##**BL – Capa lógica de negocios**

Ahora nos toca definir los modelos y crear los servicios para manejar la lógica de nuestra aplicación. En este caso, crearemos una segunda librería de clases para tener un listado general de las entidades (`Event`, `Organizer`, `Session`, `Speaker`, `Sponsor`) y la información específica de cada una de ellas.

En la solución dentro de Visual Studio 2019 sobre el proyecto EventPortal.BL tendremos algo como esto:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hwvet6erk9m60iftab1y.png)

De manera similar con el portal web administrativo, para esta página web existe un aspecto importante por mencionar, y corresponde a la identificación del evento, ya que la base de datos está diseñada para que se puedan manejar varios eventos a la vez. En la clase EventId, dentro de la carpeta `Services`, se puede controlar el identificador del evento con el que queremos trabajar.

```csharp
public class EventId
{
    private static EventId instance { get; set; } = null;

    public int Id { get; set; } = 1;

    private EventId() { }

    public static EventId GetInstance()
    {
        if (instance == null) {
            instance = new EventId();
        }

        return instance;
    }
}
```

Con esto mencionado, en esta librería de clases tenemos dos partes importantes. Como primer punto los modelos para especificar a los atributos con los que deseamos trabajar para cada uno de los casos correspondientes. 

Los modelos son los siguientes:

| **Modelos** |
|------------- |
| `EventModel` | 
| `OrganizerModel` |
| `SessionModel` | 
| `SpeakerModel` |
| `SpeakerHasSessionModel` |  
| `SpeakerModel` | 
| `SponsorModel` |

La segunda parte importante por considerar son los servicios. Todos estos servicios cuentan con métodos, cuya única finalidad constituye el consultar el listado de registros para un caso en particular. En este sentido, los métodos de estos servicios son los siguientes:

| **Servicios** | **Métodos** |
|------------- |------------- |
| `EventService` | `GetEventByIdAsync()` |
| `OrganizerService` | `GetAllOrganizersAsync()` |
| `SessionService` | `GetAllSessionAsync()`, `GetAllSessionByDayAsync(DateTime date)`, y `GetSpeakerHasSessionList(int IdSession)` |
| `SpeakerService` | `GetAllSpeakerAsync()`, y `GetSpeakerByIdAsync(int IdSpeaker)` |
| `SponsorService` | `GetAllSponsorsAsync()` |

La mayoría de los métodos de los servicios tienen como finalidad obtener un listado de registros. Sin embargo, para el caso de `SessionService`, existen dos métodos adicionales, el primero `GetAllSessionByDayAsync(DateTime date)` para obtener todas las sesiones de una fecha determinada, y el segundo `GetSpeakerHasSessionList(int IdSession)` para obtener los speakers asociados a una sesión. De igual manera, en SpeakerService se cuenta con un método adicional llamado `GetSpeakerByIdAsync(int IdSpeaker)`, donde se puede obtener un speaker en específico, junto con el listado de sus sesiones asociadas. 

Con esto mencionado, procedamos a revisar el diseño de la página web para nuestros asistentes. 

##**PL – Capa de presentación**

Ahora que ya tenemos definida toda la parte para el manejo de datos, ya podemos empezar a diseñar cada una de las secciones de la página web. En DotVVM, las páginas se encuentran conformadas por dos partes: 

+ ***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).

Teniendo en cuenta los archivos Views y Viewmodels para la página web, en Visual Studio 2019 para este proyecto visualizaremos lo siguiente: 

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

De acuerdo con cada una de las secciones de la página (portada, programación del evento, organizadores, sponsors y registro), a continuación, vamos a analizar cada una de estas secciones, junto con el formato de la página. 

**Formato general de la página**

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 los archivos CSS & JavaScript, y definir los contenidos que serán visibles en todas las secciones de la página (listados, formularios, registros). 

En el archivo `MasterPage.dotmaster`, la estructura general de la página web es como se muestra a continuación: 

![](https://dev-to-uploads.s3.amazonaws.com/i/202i8g8p0hjfc7s79snd.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***, la cabecera de la página, la cual será de utilidad para mostrar las opciones o el menú de esta página. 

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

+ ***Sección 3***, esta es una de las partes más importantes del MasterPage. En este espacio se visualizará el contenido de la página hija, cuyo identificador corresponde al MainContent.  
+ ***Sección 4***, aquí se encuentra el footer o pie de la página. 

Con esta estructura, ahora veamos el `MainContent`, que será la subpágina donde se encuentren las secciones informativas del evento. Para este caso en particular, solo tendremos una página hija o vista, cuyo archivo lleva por nombre `Default.dothtml`. La estructura de esta vista es la siguiente:

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

Bajo esta misma secuencia, en el correspondiente ViewModel de esta vista, es decir, en el archivo `DefaultViewModel.cs`, nos encontramos con las definiciones de las colecciones que nos permiten consultar los datos de organizadores, sponsors, sesiones y speakers, y la información general del evento.

Algunas de estas definiciones, de acuerdo con los modelos definidos en el BL (Business Layer) son las siguientes:

```csharp
public List<SponsorModel> Sponsors { get; set; }
public List<OrganizerModel> Organizers { get; set; }
public List<CalendarSpeakers> Calendar { get; set; } = new List<CalendarSpeakers>();

public EventModel Event { get; set; }
``` 

Ahora que conocemos la estructura general de la página, ahora analicemos cada una de las secciones correspondientes.

**Portada**

La primera sección de la página corresponde a la portada. Para este caso, esta sección solo está mostrando el título del evento por medio del objeto `Event` definido en el ViewModel. 

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

```html
<section id="about">
	<div class="container" data-aos="fade-up">
		<div class="row">
			<div class="col-lg-6">
				<h2>About the event</h2>
				<p>
					{{value: Event.Description}}
				</p>
			</div>
		</div>
	</div>
</section>
```

Aquí se puede agregar la descripción del evento, la fecha de inicio, y este tipo de atributos. 

**Agenda o programación del evento**

La siguiente parte corresponde a la agenda con las sesiones del evento, podría decirse que esta es la parte más importante de la página. Aquí tenemos un calendario o un listado de sesiones por día, y a su vez, estas sesiones cuentan con su información correspondiente, y con el listado de speakers que formaran parte de esa sesión. 

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

Ya que la intención es que de manera automática se muestren por día cada una de las sesiones, aquí se utiliza un control de DotVVM llamado `Repeater`. Este control tiene como finalidad repetir una plantilla para cada elemento de una colección especificada en el `DataSource`, en este caso, por cada día, se mostrará un listado de sesiones.

Dentro de este Repeater, podemos poner otro control (uno dentro de otro), para armar un listado de sesiones. En cada fila de este listado, se puede mostrar a manera de plantilla todas las sesiones con su fecha de inicio, el nombre de la sesión, el nombre de los speakers involucrados, y el tipo de la sesión (conferencia, taller, panel, etc). 

Estos controles anidados los podemos ver a continuación para los listados `Calendar` y `Sessions` respectivamente. 

```html
<dot:Repeater DataSource="{value: Calendar}" class="tab-content row justify-content-center" data-aos="fade-up" data-aos-delay="200">
	<ItemTemplate>
		<div role="tabpanel" html:id="{{value: NumberOfDayRef}}" class="{{value: Css}}">
			<dot:Repeater DataSource="{value: Sessions}" class="row schedule-item">
				<ItemTemplate>
					<div class="col-md-2"><time><b>{{value: StartDate.Value.ToString("hh:mm tt")}}</b></time></div>
					<div class="col-md-10">
						<div class="speaker">
							<img src="assets/img/speakers/1.png" alt="{{value: SpeakerString}}">
						</div>
						<h4>{{value: Name}}.</h4>
						<span>{{value: SpeakerString}}.</span>
						<p>{{value: NameSessionType}}.</p>
						<p><br /></p>
					</div>
				</ItemTemplate>
			</dot:Repeater>
		</div>
	</ItemTemplate>
</dot:Repeater>
```

**Organizadores**

La siguiente sección involucra a las comunidades, empresas o instituciones que se encuentran organizando el evento.

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

Al igual que para la agenda del evento, aquí también podemos utilizar un control `Repeater` para crear una plantilla de diseño con el listado de todos los organizadores registrados y definidos en el ViewModel. Para este caso, la plantilla constituye a una imagen de la organización (enlace de la imagen almacenado en la base de datos), y sobre esta imagen se muestra el nombre de la comunidad, y una pequeña descripción. Al dar clic en esta imagen, el usuario puede acceder a una de las redes sociales o página web de la comunidad organizadora. 

La plantilla para esta colección esta definida de la siguiente manera: 

```html
<dot:Repeater DataSource="{value: Organizers}" class="row">
	<ItemTemplate>
		<div class="col-lg-4 col-md-6">
			<div class="speaker" data-aos="fade-up" data-aos-delay="100">
				<img src="{{value: LogoLink}}" alt="{{value: Name}}" class="img-fluid">
				<div class="details">
					<h3><a href="{{value: FacebookLink}}" target="_blank">{{value: Name}}</a></h3>
					<p>{{value: Description}}</p>
					<div class="social">
						<a href="{{value: TwitterLink}}" target="_blank"><i class="fa fa-twitter"></i></a>
						<a href="{{value: FacebookLink}}"><i class="fa fa-facebook" target="_blank"></i></a>
					</div>
				</div>
			</div>
		</div>
	</ItemTemplate>
</dot:Repeater>
```

**Sponsors**

Continuando con nuestro análisis, ahora nos encontramos con la sección de sponsors. 

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

Como era de esperarse, aquí también utilizamos un control `Repeater` para listar a todos los patrocinadores de manera automática según los registros almacenados en la base de datos. Para esta plantilla, la colección base corresponde a Sponsors según lo establecido en el ViewModel:

```html
<dot:Repeater DataSource="{value: Sponsors}" class="row no-gutters supporters-wrap clearfix" data-aos="zoom-in" data-aos-delay="100">
	<ItemTemplate>
		<div class="col-lg-3 col-md-4 col-xs-6">
			<div class="supporter-logo">
				<a href="{{value: WebPage}}" target="_blank">
					<img src="{{value: LogoLink}}" class="img-fluid" alt="{{value: Name}}">
				</a>
			</div>
		</div>
	</ItemTemplate>
</dot:Repeater>
```

**Registro y contacto**

Para finalizar, aquí nos encontramos con la sección de registro y de contacto. 

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

Para este caso, se ha considerado que el registro de los asistentes se puede hacer a través de un formulario externo como los Forms de Microsoft o de Google, por lo cual, en esta sección se puede colocar un botón que redirija a ese formulario de registro. Con esto en mente, aquí solo se necesita hacer referencia al atributo `RegistrationLink` del objeto `Event` definido en el ViewModel: 

```html
<form method="POST" action="{{value: Event.RegistrationLink}}">
	<div class="form-row justify-content-center">
		<div class="col-auto">
			<button type="submit">Register</button>
		</div>
	</div>
</form>
```

De igual manera podemos hacer lo mismo para el medio de contacto. 

##**¿Qué sigue?**

Increíble, ya llegamos a la parte final de este articulo donde hemos podido aprender de manera general como construir una página web con ASP.NET 5 & DotVVM para dar a conocer los datos de algún evento que estemos organizando. 

El código fuente de este proyecto lo podemos encontrar en el siguiente repositorio en GitHub: [EventPortal](#).

**Recursos adicionales:**

Son muchas las cosas que podemos construir con ASP.NET, y muchas más las que podemos agregar a este portal que hemos construido. En este sentido, aquí están algunos recursos adicionales para seguir adquiriendo conocimientos en este campo:

+ [.NET 5: Despliegue de aplicaciones web con Azure App Service](https://dev.to/esdanielgomez/net-5-despliegue-de-aplicaciones-web-con-azure-app-service-3i18)
+ [Implementación de aplicaciones web con ASP.NET Core y DotVVM en AWS Elastic Beanstalk](https://dev.to/esdanielgomez/implementacion-de-aplicaciones-web-con-asp-net-core-y-dotvvm-en-aws-elastic-beanstalk-1ceg).
+ [Trabajando con servicios web a través de ASP.NET Core y DotVVM](https://dev.to/esdanielgomez/trabajando-con-servicios-web-a-traves-de-asp-net-core-y-dotvvm-4c76).

Muchas gracias por leer este artículo, espero que este demo pueda ser de ayuda para la organización y difusión de eventos. Si tienes alguna pregunta o alguna idea que necesites discutir, será un gusto poder colaborarte y juntos intercambiar conocimientos entre sí.

Si gustas, podemos estar en contacto por [Facebook](https://www.facebook.com/esDanielGomez), por [Twitter](https://twitter.com/esDanielGomez), o por [Telegram](https://t.me/esdanielgomez) también. :)