15 - Página de diseño (Layout Page)

Otra herramienta que nos provee ASP.Net MVC es agrupar todas aquellas partes que son comunes a un conjunto de páginas en un archivo. Por ejemplo el menú de opciones en la parte superior o lateral del sitio web es conveniente disponerlo en la "Página de diseño" para ser compartido por muchas vistas.

Existen una serie de pasos que debemos cumplir para usar un Layout Page, lo veremos implementando un ejemplo.

Problema (Proyecto15)

Crear un sitio web que permita mostrar un menú con cuatro opciones en la parte superior: "Acerca de este sitio", "Periódicos", "Buscadores" y "Blogs". Según que opción se elija del menú desplegar los enlaces a los sitios web de cada tema.
En la parte inferior del sitio web mostrar un mensaje de Copyright.

Luego de crear el proyecto como siempre procedemos a crear el controlador "HomeController" con las cuatro acciones respectivas que mostrarán las vistas de cada tema:

HomeController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Proyecto15.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Periodicos()
        {
            return View();
        }

        public ActionResult Buscadores()
        {
            return View();
        }

        public ActionResult Blogs()
        {
            return View();
        }

    }
}

Ahora crearemos el archivo compartido por todas las vistas. Para eso debemos crear una carpeta especial en la carpeta "Views".
El nombre de la carpeta a crear debe ser "Shared" (para crearla presionamos el botón derecho del mouse sobre la carpeta "Views" y luego seleccionamos las opciones Agregar -> Nueva carpeta):

paginas de diseño asp.net mvc

Ahora dentro de esta carpeta creamos la vista "_Principal.cshtml", para ello presionamos el botón derecho del mouse sobre la carpeta "Shared" y seleccionamos Agregar -> Nuevo elemento:

paginas de diseño asp.net mvc

Ahora tenemos generado el archivo que luego será compartido por muchas vistas:

_Principal.cshtml

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <div>
        @RenderBody()
    </div>
</body>
</html>

Donde está la llamada a la función @RenderBody() es donde se mostrará la vista. Todo el resto que hay en el archivo será compartido y común a muchas páginas. Procedemos a modificar este archivo con los elementos comunes como son el menú de opciones y el pie de página.

_Principal.cshtml

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <div>
        @Html.ActionLink("Acerca de este sitio","Index") - 
        @Html.ActionLink("Periódicos", "Periodicos") -
        @Html.ActionLink("Buscadores", "Buscadores") -
        @Html.ActionLink("Blog", "Blogs")
        <hr />
        @RenderBody()
        <hr />
        <h3>Copyright 2018</h3>
    </div>
</body>
</html>

Como podemos ver los cuatro enlaces de la parte superior y el mensaje de Copyright de la parte inferior será común a todas las vistas.

Ahora pasemos a crear cada una de las cuatro vistas, como lo venimos haciendo en el archivo HomeController presionamos el botón derecho del mouse sobre el nombre del método "Index()" y elegimos "Agregar vista...":

paginas de diseño asp.net mvc

Lo nuevo es que tildamos la opción de "Usar página de diseño" y seleccionamos el archivo "_Principal.cshtml".

El archivo que se genera tiene el siguiente formato:


@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Principal.cshtml";
}

<h2>Index</h2>

Como podemos comprobar no se genera un archivo con todas las marcas HTML. Si aparece la iniciación de la propiedad "Layout" con la referencia a la página de diseño "_Principal.cshtml".

Completamos el archivo "Index.cshtml":


@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Principal.cshtml";
}

<h2>Objetivos</h2>
<p>Este sitio agrupa enlaces a sitios periodísticos, buscadores y blogs.</p>

Seguimos los mismos pasos para generar la vista para la acción del controlador "Periodicos":

paginas de diseño asp.net mvc

En el archivo "Periodicos.cshtml" codificamos:


@{
    ViewBag.Title = "Periodicos";
    Layout = "~/Views/Shared/_Principal.cshtml";
}

<h2>Periodicos</h2>
<p><a href="http://www.lanacion.com.ar">La Nación</a></p>
<p><a href="http://www.clarin.com.ar">El Clarin</a></p>
<p><a href="http://www.lavoz.com.ar">La Voz</a></p>

La vista "Buscadores.cshtml":


@{
    ViewBag.Title = "Buscadores";
    Layout = "~/Views/Shared/_Principal.cshtml";
}

<h2>Buscadores</h2>

<p><a href="http://www.google.com">Google</a></p>
<p><a href="http://www.yahoo.com">Yahoo</a></p>
<p><a href="http://www.bing.com">Bing</a></p>

Finalmente la última vista es el archivo "Blogs.cshtml":


@{
    ViewBag.Title = "Blogs";
    Layout = "~/Views/Shared/_Principal.cshtml";
}

<h2>Blogs</h2>

<p><a href="http://www.microsiervos.com">Microsiervos</a></p>
<p><a href="http://tecnovortex.com/">Tecnovortex</a></p>
<p><a href="http://www.puntogeek.com">PuntoGeek</a></p>

Si observamos nuestro "Explorador de soluciones" debemos tener los siguientes archivos:

paginas de diseño asp.net mvc

Si ejecutamos alguna de las cuatro vistas podemos ver que todas las páginas comparten el menú y el pie de página:

paginas de diseño asp.net mvc

SI presionamos el botón derecho del mouse en nuestro navegador y seleccionamos "Ver código fuente de la página":

paginas de diseño asp.net mvc

podemos comprobar que se ha combinado el contenido del archivo _Principal.cshtml y Blogs.cshtml.

La páginas de diseño nos evitan repetir código. Todo cambio que se genere en el archivo _Principal.cshtml luego se propaga a todas las vistas que hacen referencia a dicha página.

Este proyecto lo puede descargar en un zip desde este enlace: proyecto15.zip

Acotaciones

Hay una forma alternativa de crear las páginas de diseño sin tener que inicializar la propiedad "Layout" en cada vista.

Volveremos a desarrollar el ejercicio anterior pero con esta otra forma.

Problema (Proyecto16)

Creamos el controlador "HomeController" con las cuatro acciones respectivas que mostrarán las vistas de cada tema:

HomeController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Proyecto16.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Periodicos()
        {
            return View();
        }

        public ActionResult Buscadores()
        {
            return View();
        }

        public ActionResult Blogs()
        {
            return View();
        }

    }
}

Ahora crearemos el archivo compartido por todas las vistas. Para eso debemos crear una carpeta especial en la carpeta "Views".
El nombre de la carpeta a crear debe ser "Shared" (para crearla presionamos el botón derecho del mouse sobre la carpeta "Views" y luego seleccionamos las opciones Agregar -> Nueva carpeta):

paginas de diseño asp.net mvc

Ahora dentro de esta carpeta creamos la vista "_Principal.cshtml", para ello presionamos el botón derecho del mouse sobre la carpeta "Shared" y seleccionamos Agregar -> Nuevo elemento:

paginas de diseño asp.net mvc

Ahora tenemos generado el archivo que luego será compartido por muchas vistas:

_Principal.cshtml

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <div>
        @RenderBody()
    </div>
</body>
</html>

Procedemos a modificar este archivo con los elementos comunes como son el menú de opciones y el pie de página.

_Principal.cshtml

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <div>
        @Html.ActionLink("Acerca de este sitio","Index") - 
        @Html.ActionLink("Periódicos", "Periodicos") -
        @Html.ActionLink("Buscadores", "Buscadores") -
        @Html.ActionLink("Blog", "Blogs")
        <hr />
        @RenderBody()
        <hr />
        <h3>Copyright 2018</h3>
    </div>
</body>
</html>

Como podemos ver los cuatro enlaces de la parte superior y el mensaje de Copyright de la parte inferior será común a todas las vistas.

Ahora aparece lo nuevo que no vimos en el ejercicio anterior. Debemos crear un archivo en la carpeta "Views" llamado "_ViewStart.cshtml" con la referencia a la página de diseño "_Principal.cshtml":

_ViewStart.cshtml


@{
    Layout = "~/Views/Shared/_Principal.cshtml";
}

Ahora pasemos a crear cada una de las cuatro vistas pero dejando en blanco donde hace referencia a la página de diseño.

paginas de diseño asp.net mvc

El archivo que se genera tiene el siguiente formato:


@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

Podemos ver la diferencia con el ejercicio anterior donde se definía un valor para la propiedad "Layout". En realidad ahora la propiedad Layout se inicializa en el archivo _ViewStart.cshtml para todas las vistas.

Las cuatro vistas ahora nos quedan con la siguiente sintaxis:

Index.cshtml


@{
    ViewBag.Title = "Index";
}

<h2>Objetivos</h2>
<p>Este sitio agrupa enlaces a sitios periodísticos, buscadores y blogs.</p>

Periodicos.cshtml


@{
    ViewBag.Title = "Periodicos";
}

<h2>Periodicos</h2>
<p><a href="http://www.lanacion.com.ar">La Nación</a></p>
<p><a href="http://www.clarin.com.ar">El Clarin</a></p>
<p><a href="http://www.lavoz.com.ar">La Voz</a></p>

Buscadores.cshtml


@{
    ViewBag.Title = "Buscadores";
}

<h2>Buscadores</h2>

<p><a href="http://www.google.com">Google</a></p>
<p><a href="http://www.yahoo.com">Yahoo</a></p>
<p><a href="http://www.bing.com">Bing</a></p>

Blogs.cshtml


@{
    ViewBag.Title = "Blogs";
}

<h2>Blogs</h2>

<p><a href="http://www.microsiervos.com">Microsiervos</a></p>
<p><a href="http://tecnovortex.com/">Tecnovortex</a></p>
<p><a href="http://www.puntogeek.com">PuntoGeek</a></p>

Es decir que el único cambio en los archivos de vistas es eliminar la referencia a la página de diseño, además de crear el archivo "_ViewStart.cshtml":

paginas de diseño asp.net mvc

Si necesitamos que una vista no agregue la página de diseño podemos fijar la propiedad "Layout" con null:


@{
    ViewBag.Title = "Index";
    Layout = null;
}

<h2>Objetivos</h2>
<p>Este sitio agrupa enlaces a sitios periodísticos, buscadores y blogs.</p>

Luego cuando ejecutamos esta vista vemos que no se agrega la página de diseño:

paginas de diseño asp.net mvc

Este proyecto lo puede descargar en un zip desde este enlace: proyecto16.zip