Diseño en ASP.NET Core
Por Steve Smith y Dave Brock
Las páginas y las vistas a menudo comparten elementos visuales y elementos mediante programación. En este artículo se explica cómo:
- Usar diseños comunes.
- Compartir directivas.
- Ejecutar código común antes de representar páginas o vistas.
En este documento se analizan los diseños de los dos enfoques diferentes para ASP.NET Core MVC: Razor Páginas y controladores con vistas. Para este tema, las diferencias son mínimas:
- Razor Las páginas se encuentran en la carpeta Pages.
- Los controladores con vistas usan una carpeta Vistas para las vistas.
Qué es un diseño
La mayoría de las aplicaciones web tienen un diseño común que ofrece al usuario una experiencia coherente mientras navegan por sus páginas. El diseño suele incluir elementos comunes en la interfaz de usuario, como el encabezado, los elementos de navegación o de menú y el pie de página de la aplicación.

Las estructuras HTML comunes, como scripts y hojas de estilo, también se usan con frecuencia en muchas páginas dentro de una aplicación. Todos estos elementos compartidos se pueden definir en un archivo de diseño, al que puede hacer referencia cualquier vista que se utilice dentro de la aplicación. Los diseños reducen el código duplicado en las vistas.
Por convención, el diseño predeterminado para una aplicación ASP.NET Core se denomina _Layout.cshtml. Los archivos de diseño para los nuevos proyectos de ASP.NET Core creados con las plantillas son:
Razor Pages: Pages/Shared/_Layout.cshtml

Controlador con vistas: Views/Shared/_Layout.cshtml

Este diseño define una plantilla de nivel superior para las vistas en la aplicación. Las aplicaciones no requieren un diseño. Las aplicaciones pueden definir más de un diseño, con otras vistas que especifiquen otros diseños.
Este código muestra el archivo de diseño para un proyecto creado mediante plantilla con un controlador y vistas:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebApplication1</title>
<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a asp-page="/Index" class="navbar-brand">WebApplication1</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-page="/Index">Home</a></li>
<li><a asp-page="/About">About</a></li>
<li><a asp-page="/Contact">Contact</a></li>
</ul>
</div>
</div>
</nav>
<partial name="_CookieConsentPartial" />
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© 2018 - WebApplication1</p>
</footer>
</div>
<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
@RenderSection("Scripts", required: false)
</body>
</html>
Especificar un diseño
Razor las vistas tienen una Layout propiedad . Las vistas individuales especifican un diseño al configurar esta propiedad:
@{
Layout = "_Layout";
}
El diseño especificado puede usar una ruta de acceso completa (por ejemplo, /Pages/Shared/_Layout.cshtml o /Views/Shared/_Layout.cshtml) o un nombre parcial (ejemplo: _Layout). Cuando se proporciona un nombre parcial, el motor de vistas Razor busca el archivo de diseño mediante su proceso de detección estándar. Primero se busca la carpeta donde existe el método de controlador (o controlador), seguida de la carpeta Shared. Este proceso de detección es idéntico al que se usa para detectar vistas parciales.
De forma predeterminada, todos los diseños deben llamar a RenderBody. Cada vez que se realiza la llamada a RenderBody, se representa el contenido de la vista.
Secciones
Opcionalmente, un diseño puede hacer referencia a una o varias secciones mediante una llamada a RenderSection. Las secciones permiten organizar dónde se deben colocar determinados elementos de la página. Cada llamada a RenderSection puede especificar si esa sección es obligatoria u opcional:
<script type="text/javascript" src="~/scripts/global.js"></script>
@RenderSection("Scripts", required: false)
Si no se encuentra una sección obligatoria, se produce una excepción. Las vistas individuales especifican el contenido que se va a representar dentro de una sección mediante la @section Razor sintaxis . Si una página o una vista define una sección, se debe representar (o se producirá un error).
Una definición @section de ejemplo en la vista Razor Páginas:
@section Scripts {
<script type="text/javascript" src="~/scripts/main.js"></script>
}
En el código anterior, scripts/main.js se agrega a la sección scripts en una página o vista. Es posible que otras páginas o vistas de la misma aplicación no necesiten este script y no definan una sección de script.
El marcado siguiente usa el asistente de etiquetas parcial para representar _ValidationScriptsPartial.cshtml:
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
El marcado anterior se generó mediante scaffolding Identity .
Las secciones definidas en una vista o una vista solo están disponibles en su página de diseño inmediato. No se puede hacer referencia a ellas desde líneas de código parcialmente ejecutadas, componentes de vista u otros elementos del sistema de vistas.
Omitir secciones
De forma predeterminada, el cuerpo y todas las secciones de una página de contenido deben representarse mediante la página de diseño. El motor de vistas aplica esto mediante el seguimiento de si se han representado el cuerpo y Razor cada sección.
Para indicar al motor de vistas que pase por alto el cuerpo o las secciones, llame a los métodos IgnoreBody y IgnoreSection.
El cuerpo y todas las secciones de Razor una página deben representarse o omitirse.
Importar directivas compartidas
Las vistas y páginas pueden usar Razor directivas para importar espacios de nombres y usar la inserción de dependencias. Se pueden especificar varias directivas compartidas por muchas vistas en un archivo _ViewImports.cshtml común. El archivo _ViewImports es compatible con estas directivas:
@addTagHelper@removeTagHelper@tagHelperPrefix@using@model@inherits@inject
El archivo no admite otras Razor características, como funciones y definiciones de sección.
Archivo _ViewImports.cshtml de ejemplo:
@using WebApplication1
@using WebApplication1.Models
@using WebApplication1.Models.AccountViewModels
@using WebApplication1.Models.ManageViewModels
@using Microsoft.AspNetCore.Identity
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
El archivo _ViewImports.cshtml para una aplicación ASP.NET Core MVC normalmente se coloca en la carpeta Pages (o Views). Un archivo _ViewImports.cshtml puede colocarse dentro de cualquier carpeta, en cuyo caso solo se aplicará a páginas o vistas dentro de esa carpeta y sus subcarpetas. Los archivos _ViewImports se procesan a partir del nivel de raíz y, después, para cada carpeta que llevó a la ubicación de la propia página o vista. La configuración _ViewImports especificada en el nivel de raíz se puede reemplazar en el nivel de carpeta.
Por ejemplo, supongamos que:
- El archivo _ViewImports.cshtml del nivel de raíz incluye
@model MyModel1y@addTagHelper *, MyTagHelper1. - Un archivo _ViewImports.cshtml de subcarpeta incluye
@model MyModel2y@addTagHelper *, MyTagHelper2.
Las páginas y las vistas de la subcarpeta tendrán acceso a los asistentes de etiquetas y al modelo MyModel2.
Si hay varios _ViewImports.cshtml en la jerarquía de archivos, el comportamiento combinado de las directivas es:
@addTagHelper,@removeTagHelper: todos se ejecutan en orden@tagHelperPrefix: el más cercano a la vista invalida los demás@model: el más cercano a la vista invalida los demás@inherits: el más cercano a la vista invalida los demás@using: todos se incluyen y se omiten los duplicados@inject: para cada propiedad, la más cercana a la vista invalida cualquier otra con el mismo nombre de propiedad
Ejecutar código antes de cada vista
El código que debe ejecutarse antes de cada vista o página se debería colocar en el archivo _ViewStart.cshtml. Por convención, el archivo _ViewStart.cshtml se encuentra en la carpeta Pages (o Views). Las instrucciones que aparecen en _ViewStart.cshtml se ejecutan antes de cada vista completa (no los diseños ni las vistas parciales). Al igual que ViewImports.cshtml, _ViewStart.cshtml tiene una estructura jerárquica. Si se define un archivo _ViewStart.cshtml en la carpeta de vista o de página, se ejecutará después del que esté definido en la raíz de la carpeta Pages (o Views) (si existe).
Un archivo _ViewStart.cshtml de ejemplo:
@{
Layout = "_Layout";
}
El archivo anterior especifica que todas las vistas usarán el diseño _Layout.cshtml.
_ViewStart.cshtml y _ViewImports.cshtml normalmente no se colocan en la carpeta /Pages/Shared (o /Views/Shared). Las versiones de nivel de aplicación de estos archivos deben colocarse directamente en la carpeta /Pages (o /Views).