Guía para organizar y promocionar eventos a través de dos portales web con ASP.NET 5
Tags: webdev, dotnet, html, csharp
Published: 2021-03-16 21:10:37

¡Hola! En esta guía aprenderemos cómo administrar y dar a conocer nuestros eventos, ya sean en persona o en línea, a través de dos portales web.  

##**Criterios por considerar**

Para a administración y difusión de un evento en particular, los datos o funcionalidades a considerar son los siguientes:

+ **Organizadores:** información de las comunidades y/o instituciones que están organizando el evento. 
+ **Speakers:** información de las personas que presentarán una sesión dentro del evento. 
+ **Sesiones:** donde se registran las presentaciones del evento, con sus respectivos speakers asociados, el tipo de la sesión (por ejemplo: Keynote, taller, charla, etc) y el nivel de dificultad (fundamentos, intermedio, avanzada).
+ **Sponsors:** información de las comunidades, instituciones o empresas externas que apoyan al evento.  

Para estos propósitos tendremos dos plataformas con una misma base de datos. La primera para administrar los datos del evento, y la segunda para presentar estos datos a los usuarios o asistentes de nuestro evento. 

Para el caso de la sección de organizadores de un evento, en ambas plataformas tendríamos algo como esto: 

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67tuubo772zop2yazsbz.png)

##**Artículos previos**

En artículos tutoriales previos, la explicación para la construcción de cada uno de estos portales es llevada a cabo de manera detallada. Asimismo, el código fuente de ambos proyectos también los podemos encontrar aquí:

Tutorial 1: [Portal web para gestionar eventos y conferencias con ASP.NET 5](https://dev.to/esdanielgomez/portal-web-para-gestionar-eventos-y-conferencias-con-asp-net-5-y-dotvvm-4m1m).

Demo 1: [Event Admin](https://github.com/esdanielgomez/EventAdmin).

Tutorial 2: [Construcción de un portal informativo para eventos con ASP.NET 5](https://dev.to/esdanielgomez/construccion-de-un-portal-informativo-para-eventos-con-asp-net-5-39gd).

Demo 2: [Event Portal](https://github.com/esdanielgomez/EventPortal).

##**Recursos y herramientas necesarias**##

Ambos portales han sido construidos con ASP.NET 5 & DotVVM. Para las configuraciones o funcionalidades que necesiten ser implementadas, es necesario contar con las siguientes herramientas de trabajo:

+ [Visual Studio 2019](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/kq86b3usxdrei95toa67.png)
+ [Extensión de DotVVM para Visual Studio 2019](www.dotvvm.com/landing/dotvvm-for-visual-studio-extension).

##**La base de datos**

Ambos portales comparten la misma base de datos, cuyo motor corresponde a SQL Server con las entidades: `Organizer`, `Sponsor`, `Event`, `Speaker`, `Session`, `Speaker_has_Session`, `SessionLevel` y `SessionType`. 

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

Lo primero que tendremos que hacer es establecer esta base de datos, para ello, el script SQL lo podemos encontrar aquí: 

```sql
-- -----------------------------------------------------
CREATE TABLE  Event (
  IdEvent INT NOT NULL IDENTITY(1,1),
  Name VARCHAR(45) NOT NULL,
  Description VARCHAR(500) NULL,
  Icon VARCHAR(45) NULL,
  StartDate DATETIME NOT NULL,
  EndDate DATETIME NOT NULL,
  RegistrationLink VARCHAR(45) NULL,
  StreamingLink VARCHAR(45) NULL,
  PRIMARY KEY (IdEvent))
;

-- -----------------------------------------------------
CREATE TABLE  Speaker (
  IdSpeaker INT NOT NULL IDENTITY(1,1),
  FirstName VARCHAR(45) NOT NULL,
  SecondName VARCHAR(45) NULL,
  FirstLastName VARCHAR(45) NOT NULL,
  SecondLastName VARCHAR(45) NULL,
  PhotoLink VARCHAR(45) NULL,
  TwitterLink VARCHAR(45) NULL,
  LinkedInLink VARCHAR(45) NULL,
  IdEvent INT NOT NULL,
  PRIMARY KEY (IdSpeaker),
  INDEX fk_Speaker_Event_idx (IdEvent ASC),
  CONSTRAINT fk_Speaker_Event
    FOREIGN KEY (IdEvent)
    REFERENCES Event (IdEvent)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
;

-- -----------------------------------------------------
CREATE TABLE  SessionType (
  IdSessionType INT NOT NULL IDENTITY(1,1),
  Name VARCHAR(45) NOT NULL,
  Description VARCHAR(45) NULL,
  PRIMARY KEY (IdSessionType))
;

-- -----------------------------------------------------
CREATE TABLE  SessionLevel (
  IdSessionLevel INT NOT NULL IDENTITY(1,1),
  Name VARCHAR(45) NULL,
  Description VARCHAR(45) NULL,
  PRIMARY KEY (IdSessionLevel))
;

-- -----------------------------------------------------
CREATE TABLE  Session (
  IdSession INT NOT NULL IDENTITY(1,1),
  Name VARCHAR(45) NOT NULL,
  Description VARCHAR(500) NULL,
  StartDate DATETIME NULL,
  EndDate DATETIME NULL,
  IconLink VARCHAR(45) NULL,
  IdSessionType INT NOT NULL,
  IdSessionLevel INT NOT NULL,
  PRIMARY KEY (IdSession),
  INDEX fk_Session_SessionType1_idx (IdSessionType ASC),
  INDEX fk_Session_SessionLevel1_idx (IdSessionLevel ASC),
  CONSTRAINT fk_Session_SessionType1
    FOREIGN KEY (IdSessionType)
    REFERENCES SessionType (IdSessionType)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT fk_Session_SessionLevel1
    FOREIGN KEY (IdSessionLevel)
    REFERENCES SessionLevel (IdSessionLevel)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
;

-- -----------------------------------------------------
CREATE TABLE  Speaker_has_Session (
  IdSpeaker INT NOT NULL,
  IdSession INT NOT NULL,
  INDEX fk_Speaker_has_Session_Session1_idx (IdSession ASC),
  INDEX fk_Speaker_has_Session_Speaker1_idx (IdSpeaker ASC),
  CONSTRAINT fk_Speaker_has_Session_Speaker1
    FOREIGN KEY (IdSpeaker)
    REFERENCES Speaker (IdSpeaker)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT fk_Speaker_has_Session_Session1
    FOREIGN KEY (IdSession)
    REFERENCES Session (IdSession)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
;

-- -----------------------------------------------------
CREATE TABLE  Organizer (
  IdOrganizer INT NOT NULL IDENTITY(1,1),
  Name VARCHAR(45) NOT NULL,
  LogoLink VARCHAR(45) NULL,
  WebPage VARCHAR(45) NULL,
  Email VARCHAR(45) NULL,
  Description VARCHAR(45) NULL,
  FacebookLink VARCHAR(45) NULL,
  TwitterLink VARCHAR(45) NULL,
  InstagramLink VARCHAR(45) NULL,
  IdEvent INT NOT NULL,
  PRIMARY KEY (IdOrganizer),
  INDEX fk_Organizer_Event1_idx (IdEvent ASC),
  CONSTRAINT fk_Organizer_Event1
    FOREIGN KEY (IdEvent)
    REFERENCES Event (IdEvent)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
;

-- -----------------------------------------------------
CREATE TABLE  Sponsor (
  IdSponsor INT NOT NULL IDENTITY(1,1),
  Name VARCHAR(45) NOT NULL,
  LogoLink VARCHAR(45) NULL,
  Description VARCHAR(45) NULL,
  WebPage VARCHAR(45) NULL,
  IdEvent INT NOT NULL,
  PRIMARY KEY (IdSponsor),
  INDEX fk_Sponsor_Event1_idx (IdEvent ASC),
  CONSTRAINT fk_Sponsor_Event1
    FOREIGN KEY (IdEvent)
    REFERENCES Event (IdEvent)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
;

```

Una buena opción por considerar para desplegar nuestra base de datos en la nube es Azure SQL Database, que es lo mismo que SQL Server, solo que en la nube. 

Aquí podemos ver un poco más de este recurso: [https://azure.microsoft.com/es-es/services/sql-database/](https://azure.microsoft.com/es-es/services/sql-database/).

##**Organización de los proyectos**

Ambos proyectos han sido desarrollados teniendo en cuenta el patrón arquitectónico Modelo, Vista, VistaModelo (MVVM), donde:

+ **El modelo.** — será responsable de todos los datos de la aplicación y de la lógica de negocios relacionada.
+ **La vista**. — corresponderán a representaciones para el usuario final del modelo de la aplicación. La vista será responsable de mostrar los datos al usuario y de permitir la manipulación de los datos de la aplicación.
+ **El Modelo-Vista o Vista-Modelo.** — uno o más por vista; el modelo-vista será responsable de implementar el comportamiento de la vista para responder a las acciones del usuario y de exponer los datos del modelo fácilmente.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8yt8d12m9xysm0q7bwxj.png)

Y en Visual Studio 2019 podemos visualizar algo como esto para los proyectos *EventAdmin* y *EventPortal* respectivamente:  

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

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

Muy bien, con esto presente, veamos las consideraciones que deberíamos tener en cuenta para utilizar estos dos proyectos.  

##**Ajustes en BL – Business Layer**

Para nuestro caso de estudio, la base de datos esta diseñada para poder manejar varios eventos a la vez. En este sentido, los proyectos en el BL tienen una clase llamada `EventId` para controlar el identificador del evento con el que queremos trabajar. Para ambos casos, en esta clase deberemos colocar el `Id` correspondiente. 

```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;
    }
}
```

##**Ajustes en el PL – Presentation Layer**

A nivel de diseño, nuestras páginas web se encuentran compuestas por los siguientes elementos: 

+ **Una vista**, que se basa en la sintaxis HTML y describe cómo se verá la página. 
+ **Un modelo de la vista**, 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).

####**Portal administrativo**

Para el portal web administrativo nos podemos encontrar algo como esto: 

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

Para este portal en particular, a nivel de diseño no existen cambios que deban ser implementados. A la final, en esta página web podremos visualizar lo siguiente: 

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

####**Portal informativo**

Para nuestro segundo portal, el que verán nuestros asistentes, aquí si existen cambios o estilos de diseño que se pudiesen contemplar.

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

La estructura en Visual Studio 2019 es así:

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

En la cual, la estructura general de la página web se encuentra ubicada en el `MasterPage.dotmaster`:

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

 Y el contenido de la página, definido por el control `ContentPlaceHolder` con el identificador `MainContent`, se encuentra en el `Default.dothtml`.

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

Aquí se pueden realizar los cambios que se consideren pertinentes, teniendo en cuenta el `ViewModel` donde se encuentran las definiciones y colecciones que hacen referencia a los datos correspondientes del evento.

```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; }
```

####**Publicar nuestro portal web informativo**

Para desplegar nuestro proyecto y que este pueda ser accedido desde internet por parte de los usuarios en general, para este caso se puede contemplar el recurso Azure App Service para cumplir con este propósito.

En este articulo tutorial podemos ver ese proceso: [.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).

##**Muchas gracias**##

Muchas gracias por leer, espero que este demo pueda serte de utilidad. 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)! O si gustas también puedes escribirme por [Facebook](https://www.facebook.com/esDanielGomez) o [Telegram](https://t.me/esdanielgomez). :=)