Vistas de ASP.NET Core MVC

Por Steve Smith y Dave Brock

En este documento se explican las vistas utilizadas en las aplicaciones de ASP.NET Core MVC. Para más información, sobre Razor Pages, consulte Introducción a Razor Pages en ASP.NET Core.

En el patrón de controlador de vista de modelos (MVC), la vista se encarga de la presentación de los datos y de la interacción del usuario. Una vista es una plantilla HTML con marcado de Razor insertado. El marcado de Razor es código que interactúa con el formato HTML para generar una página web que se envía al cliente.

En ASP.NET  Core MVC, las vistas son archivos .cshtml que usan el lenguaje de programación C# en el marcado de Razor. Por lo general, los archivos de vistas se agrupan en carpetas con el nombre de cada uno de los controladores de la aplicación. Las carpetas se almacenan en una carpeta llamadaViews que está ubicada en la raíz de la aplicación:

Views folder in Solution Explorer of Visual Studio is open with the Home folder open to show About.cshtml, Contact.cshtml, and Index.cshtml files

El controlador Home está representado por una carpeta Home situada dentro de la carpeta Views. La carpeta Home contiene las vistas de las páginas web de About, Contact y Index (página principal). Cuando un usuario solicita una de estas tres páginas web, las acciones del controlador Home determinan cuál de las tres vistas se usa para crear y devolver una página web al usuario.

Use diseños para cohesionar las secciones de la página web y reducir la repetición del código. Los diseños suelen contener encabezado, elementos de menú y navegación y pie de página. El encabezado y el pie de página suelen contener marcado reutilizable para muchos elementos de metadatos y vínculos a recursos de script y estilo. Los diseños ayudan a evitar este marcado reutilizable en las vistas.

Las vistas parciales administran las partes reutilizables de las vistas para reducir la duplicación de código. Por ejemplo, resulta útil usar una vista parcial en la biografía de un autor que aparece en varias vistas de un sitio web de blog. Una biografía de autor es contenido de vista normal y no requiere que se ejecute código para generar el contenido de la página web. El contenido de la biografía del autor está disponible para la vista simplemente mediante un enlace de modelos, por lo que resulta ideal usar una vista parcial para este tipo de contenido.

Los componentes de la vista se asemejan a las vistas parciales en que permiten reducir el código repetitivo, pero son adecuados para ver contenido que requiere la ejecución de código en el servidor con el fin de representar la página web. Los componentes de la vista son útiles cuando el contenido representado requiere una interacción con la base de datos, por ejemplo, en el carro de la compra de un sitio web. Los componentes de la vista no se limitan a un enlace de modelos para generar la salida de la página web.

Ventajas de utilizar las vistas

Las vistas separan el marcado de la interfaz de usuario de otras partes de la aplicación con el fin de ayudar a establecer una separación de intereses dentro de una aplicación MVC. Diseñar respetando el principio SoC hace que la aplicación sea modular, lo que ofrece varias ventajas:

  • La aplicación es más fácil de mantener, ya que está mejor organizada. Las vistas generalmente se agrupan por característica de la aplicación. Esto facilita la búsqueda de vistas relacionadas cuando se trabaja en una característica.
  • Las partes de la aplicación están acopladas de forma ligera. Las vistas de la aplicación se pueden compilar y actualizar por separado de los componentes de la lógica de negocios y el acceso a datos. Las vistas de la aplicación se pueden modificar sin necesidad de tener que actualizar otras partes de la aplicación.
  • Es más fácil probar los elementos de la interfaz de usuario de la aplicación, ya que las vistas son unidades independientes.
  • Dada la mejora en la organización, es menos probable que se repitan secciones de la interfaz de usuario de forma accidental.

Creación de una vista

Las vistas que son específicas de un controlador se crean en la carpeta Views/[ControllerName]. Las vistas compartidas entre controladores se colocan en la carpeta Views/Shared. Para crear una vista, agregue un archivo nuevo y asígnele el mismo nombre que a la acción del controlador asociada con la extensión de archivo .cshtml. Para crear una vista que se corresponda con la acción About del controlador Home, cree un archivo About.cshtml en la carpeta Views/Home:

@{
    ViewData["Title"] = "About";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p>Use this area to provide additional information.</p>

El marcado de Razor comienza con el símbolo @. Ejecute instrucciones de C# mediante la colocación de código C# en los bloques de código Razor activados por llaves ({ ... }). Por ejemplo, vea la asignación de "About" en ViewData["Title"] mostrada anteriormente. Para mostrar valores en HTML, simplemente haga referencia al valor con el símbolo @. Ver el contenido de los elementos <h2> y <h3> anteriores.

El contenido de la vista mostrado anteriormente es solo una parte de toda la página web que se presenta al usuario. El resto del diseño de la página y otros aspectos comunes de la vista se especifican en otros archivos de vista. Para obtener más información, consulte el tema Diseño.

Cómo especifican los controladores las vistas

Las vistas normalmente las devuelven acciones como ViewResult, que es un tipo de ActionResult. El método de acción puede crear y devolver ViewResult directamente, pero no es lo más común. Puesto que la mayoría de los controladores heredan de Controller, simplemente se usa el método del asistente View para devolver ViewResult:

HomeController.cs:

public IActionResult About()
{
    ViewData["Message"] = "Your application description page.";

    return View();
}

Cuando esta acción devuelve un resultado, la vista About.cshtml mostrada en la última sección se representa como la página web siguiente:

About page rendered in the Edge browser

El método del asistente View tiene varias sobrecargas. También puede especificar:

  • Una vista explícita para devolver:

    return View("Orders");
    
  • Un modelo para pasar a la vista:

    return View(Orders);
    
  • Una vista y un modelo:

    return View("Orders", Orders);
    

Detección de vista

Cuando una acción devuelve una vista, tiene lugar un proceso llamado detección de vista. Este proceso determina qué archivo de vista se utiliza en función del nombre de la vista.

El comportamiento predeterminado del método View (return View();) es devolver una vista con el mismo nombre que el método de acción desde el que se llama. Por ejemplo, el nombre de método AboutActionResult del controlador se usa para buscar un archivo de vista denominado About.cshtml. En primer lugar, el runtime busca la vista en la carpeta Views/[ControllerName]. Si no encuentra una vista que coincida, busca la vista en la carpeta Shared.

Da igual si se devuelve implícitamente ViewResult con return View(); o si se pasa explícitamente el nombre de la vista al método View con return View("<ViewName>");. En ambos casos, la detección de vista busca un archivo de vista coincidente en este orden:

  1. Views/\[ControllerName]/\[ViewName].cshtml
  2. Views/Shared/\[ViewName].cshtml

En lugar del nombre de una vista, se puede proporcionar la ruta de acceso del archivo de vista. Si se utiliza una ruta de acceso absoluta que comience en la raíz de la aplicación (también puede empezar con "/" o "~/"), debe especificarse la extensión .cshtml:

return View("Views/Home/About.cshtml");

También se puede usar una ruta de acceso relativa para especificar vistas de directorios distintos sin la extensión .cshtml. Dentro de HomeController, se puede devolver la vista Index de las vistas Manage con una ruta de acceso relativa:

return View("../Manage/Index");

De forma similar, se puede indicar el directorio específico del controlador actual con el prefijo "./":

return View("./About");

Las vistas parciales y los componentes de vista usan mecanismos de detección similares (aunque no idénticos).

Puede personalizar la convención predeterminada para la localización de las vistas en la aplicación si utiliza una interfaz IViewLocationExpander personalizada.

La detección de vistas se basa en la búsqueda de archivos de vista por nombre de archivo. Si el sistema de archivos subyacente distingue mayúsculas de minúsculas, es probable que también lo hagan los nombres de las vistas. Para que haya compatibilidad entre sistemas operativos, haga coincidir las letras mayúsculas y minúsculas de los nombres de controlador y acción con los nombres de archivo y carpetas de vista asociados. Si mientras trabaja con un sistema de archivos que distingue mayúsculas de minúsculas se produce un error que le indica que no se encuentra un archivo de vista, confirme que el archivo de vista solicitado y el nombre de archivo de vista real coinciden en el uso de mayúsculas.

Siga el procedimiento recomendado de organizar la estructura de archivos de vistas de modo que refleje las relaciones existentes entre controladores, acciones y vistas para una mayor claridad y un mantenimiento más sencillo.

Paso de datos a las vistas

Se pueden pasar datos a vistas con varios métodos:

  • Datos fuertemente tipados: ViewModel
  • Datos débilmente tipados
    • ViewData (ViewDataAttribute)
    • ViewBag

Datos fuertemente tipados (ViewModel)

El enfoque más eficaz consiste en especificar un tipo de modelo en la vista. Este modelo se conoce normalmente como viewmodel (modelo de vista) y en él se pasa una instancia de tipo viewmodel a la vista de la acción.

La utilización de un modelo de vista para pasar datos a una vista permite que la vista se beneficie de las ventajas de la comprobación de tipos seguros. El término establecimiento fuerte de tipos (o fuertemente tipado) significa que cada variable y constante tienen un tipo definido explícitamente, por ejemplo, string, int o DateTime. La validez de los tipos usados en una vista se comprueba en tiempo de compilación.

Visual Studio y Visual Studio Code enumeran los miembros de clase fuertemente tipados mediante una característica denominada IntelliSense. Si quiere ver las propiedades de un modelo de vista, escriba el nombre de variable del modelo de vista seguido por un punto (.). Esto ayuda a escribir código más rápidamente y con menos errores.

Especifique un modelo con la directiva @model. Utilice el modelo con @Model:

@model WebApplication1.ViewModels.Address

<h2>Contact</h2>
<address>
    @Model.Street<br>
    @Model.City, @Model.State @Model.PostalCode<br>
    <abbr title="Phone">P:</abbr> 425.555.0100
</address>

Para proporcionar el modelo a la vista, el controlador lo pasa como un parámetro:

public IActionResult Contact()
{
    ViewData["Message"] = "Your contact page.";

    var viewModel = new Address()
    {
        Name = "Microsoft",
        Street = "One Microsoft Way",
        City = "Redmond",
        State = "WA",
        PostalCode = "98052-6399"
    };

    return View(viewModel);
}

No hay ninguna restricción sobre los tipos de modelo que se pueden proporcionar a una vista. Se recomienda usar modelos de vista POCO (objeto CRL estándar) con poco o ningún comportamiento (métodos) definido. Por lo general, las clases de modelo de vista se almacenan en la carpeta Models o en otra carpeta ViewModels en la raíz de la aplicación. El modelo de vista Address usado en el ejemplo anterior es un modelo de vista POCO almacenado en un archivo denominado Address.cs:

namespace WebApplication1.ViewModels
{
    public class Address
    {
        public string Name { get; set; }
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
    }
}

Nada le impide usar las mismas clases tanto para los tipos de modelo de vista como para los de modelo de negocio. Pero el uso de modelos independientes permite que las vistas varíen de forma independiente de las partes de lógica de negocios y acceso de datos de la aplicación. La separación de los modelos y los modelos de vista también ofrece ventajas de seguridad cuando los modelos utilizan enlace de modelo y validación para los datos enviados a la aplicación por el usuario.

Datos con establecimiento flexible de datos (ViewData, atributo [ViewData] y ViewBag)

ViewBagno está disponible de forma predeterminada para su uso en clases de Razor PagesPageModel.

Además de las vistas fuertemente tipadas, las vistas tienen acceso a una colección de datos débilmente tipados, también denominados imprecisos. A diferencia de los tipos fuertes, en los tipos débiles (o débilmente tipados) no se declara explícitamente el tipo de datos que se está utilizando. Puede usar la colección de datos débilmente tipados para pasar pequeñas cantidades de datos de los controladores y las vistas, tanto en dirección de entrada como de salida.

Pasar datos entre... Ejemplo
Un controlador y una vista Rellenar una lista desplegable con datos.
Una vista y una vista de diseño Establecer el contenido del elemento <title> en la vista de diseño de un archivo de vista.
Una vista parcial y una vista Un widget que muestra datos basados en la página web que el usuario solicitó.

Puede hacer referencia a esta colección a través de las propiedades ViewData o ViewBag en controladores y vistas. La propiedad ViewData es un diccionario de objetos débilmente tipados. La propiedad ViewBag es un contenedor alrededor de ViewData que proporciona propiedades dinámicas para la colección ViewData subyacente. Nota: Las búsquedas de claves no distinguen mayúsculas de minúsculas para ViewData y ViewBag.

ViewData y ViewBag se resuelven de forma dinámica en tiempo de ejecución. Debido a que no ofrecen la comprobación de tipos en tiempo de compilación, ambas son generalmente más propensas a errores que el uso de un modelo de vista. Por esta razón, algunos desarrolladores prefieren prescindir de ViewData y ViewBag o usarlos lo menos posible.

ViewData

ViewData es un objeto ViewDataDictionary al que se accede a través de claves string. Los datos de cadena se pueden almacenar y utilizar directamente sin necesidad de una conversión, pero primero debe convertir otros valores de objeto ViewData a tipos específicos cuando los extrae. Se puede usar ViewData para pasar datos de los controladores a las vistas y dentro de las vistas, incluidas las vistas parciales y los diseños.

En el ejemplo siguiente se usa ViewData en una acción para establecer los valores de saludo y dirección:

public IActionResult SomeAction()
{
    ViewData["Greeting"] = "Hello";
    ViewData["Address"]  = new Address()
    {
        Name = "Steve",
        Street = "123 Main St",
        City = "Hudson",
        State = "OH",
        PostalCode = "44236"
    };

    return View();
}

Trabajar con los datos en una vista:

@{
    // Since Address isn't a string, it requires a cast.
    var address = ViewData["Address"] as Address;
}

@ViewData["Greeting"] World!

<address>
    @address.Name<br>
    @address.Street<br>
    @address.City, @address.State @address.PostalCode
</address>

Atributo [ViewData]

Otro enfoque que usa ViewDataDictionary es ViewDataAttribute. Los valores de las propiedades de controladores o modelos de Razor Page marcados con el atributo [ViewData] se almacenan y cargan desde el diccionario.

En el siguiente ejemplo, el controlador Home contiene una propiedad Title marcada con [ViewData]. El método About establece el título de la vista About:

public class HomeController : Controller
{
    [ViewData]
    public string Title { get; set; }

    public IActionResult About()
    {
        Title = "About Us";
        ViewData["Message"] = "Your application description page.";

        return View();
    }
}

En el diseño, el título se lee desde el diccionario ViewData:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"] - WebApplication</title>
    ...

ViewBag

ViewBagno está disponible de forma predeterminada para su uso en clases de Razor PagesPageModel.

ViewBag es un objeto Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.DynamicViewData que proporciona acceso dinámico a los objetos almacenados en ViewData. ViewBag puede ser más cómodo de trabajar con él, ya que no requiere conversión. En el ejemplo siguiente se muestra cómo usar ViewBag con el mismo resultado que al usar ViewData anteriormente:

public IActionResult SomeAction()
{
    ViewBag.Greeting = "Hello";
    ViewBag.Address  = new Address()
    {
        Name = "Steve",
        Street = "123 Main St",
        City = "Hudson",
        State = "OH",
        PostalCode = "44236"
    };

    return View();
}
@ViewBag.Greeting World!

<address>
    @ViewBag.Address.Name<br>
    @ViewBag.Address.Street<br>
    @ViewBag.Address.City, @ViewBag.Address.State @ViewBag.Address.PostalCode
</address>

Uso de ViewData y ViewBag simultáneamente

ViewBagno está disponible de forma predeterminada para su uso en clases de Razor PagesPageModel.

Puesto que ViewData y ViewBag hacen referencia a la misma colección ViewData subyacente, se pueden utilizar ViewData y ViewBag, y combinarlos entre ellos al leer y escribir valores.

Establezca el título con ViewBag y la descripción con ViewData en la parte superior de una vista About.cshtml:

@{
    Layout = "/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "About Contoso";
    ViewData["Description"] = "Let us tell you about Contoso's philosophy and mission.";
}

Lea las propiedades pero invierta el uso de ViewData y ViewBag. En el archivo _Layout.cshtml, obtenga el título con ViewData y la descripción con ViewBag:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"]</title>
    <meta name="description" content="@ViewBag.Description">
    ...

Recuerde que las cadenas no requieren una conversión para ViewData. Puede usar @ViewData["Title"] sin conversión alguna.

Es posible utilizar ViewData y ViewBag al mismo tiempo, al igual que combinar la lectura y escritura de propiedades. Se representa el marcado siguiente:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>About Contoso</title>
    <meta name="description" content="Let us tell you about Contoso's philosophy and mission.">
    ...

Resumen de las diferencias entre ViewData y ViewBag

ViewBagno está disponible de forma predeterminada para su uso en clases de Razor PagesPageModel.

  • ViewData
    • Se deriva de ViewDataDictionary, por lo que tiene propiedades de diccionario que pueden ser útiles, como ContainsKey, Add, Remove y Clear.
    • Las claves del diccionario son cadenas, por lo que se permiten espacios en blanco. Ejemplo: ViewData["Some Key With Whitespace"]
    • Todos los tipos excepto string deben convertirse en la vista que usa ViewData.
  • ViewBag
    • Se deriva de Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.DynamicViewData, por lo que permite la creación de propiedades dinámicas mediante la notación de puntos (@ViewBag.SomeKey = <value or object>), y no se requiere ninguna conversión. La sintaxis de ViewBag hace que sea más rápido de agregar a controladores y vistas.
    • Es más sencillo comprobar si hay valores null. Ejemplo: @ViewBag.Person?.Name

Cuándo usar ViewData o ViewBag

ViewData y ViewBag son dos enfoques igualmente válidos para pasar pequeñas cantidades de datos entre controladores y vistas. La elección de cuál utilizar se basa en la preferencia. Aunque se pueden combinar objetos ViewData y ViewBag, el código resulta más fácil de leer y mantener si se utiliza un único enfoque de forma sistemática. Ambos enfoques se resuelven dinámicamente en tiempo de ejecución y, por tanto, son propensos a generar errores en tiempo de ejecución. Algunos equipos de desarrollo los evitan.

Vistas dinámicas

Las vistas que no declaran un tipo modelo con @model, pero que tienen una instancia de modelo que se les pasa (por ejemplo, return View(Address);), pueden hacer referencia a las propiedades de la instancia dinámicamente:

<address>
    @Model.Street<br>
    @Model.City, @Model.State @Model.PostalCode<br>
    <abbr title="Phone">P:</abbr> 425.555.0100
</address>

Esta característica proporciona la flexibilidad, pero no ofrece protección de compilación ni IntelliSense. Si la propiedad no existe, se produce un error en la generación de la página web en tiempo de ejecución.

Más características de vista

Los asistentes de etiquetas permiten agregar fácilmente el comportamiento del lado servidor a las etiquetas HTML existentes. El uso de asistentes de etiquetas evita la necesidad de escribir código personalizado o asistentes en las vistas. Los asistentes de etiquetas se aplican como atributos a elementos HTML y son ignoradas por los editores que no pueden procesarlas. Esto permite editar y representar el marcado de la vista con varias herramientas.

Hay muchos asistentes de HTML integradas que permiten generar marcado HTML personalizado. La lógica más compleja de la interfaz de usuario se puede administrar mediante componentes de vista. Los componentes de vista proporcionan la misma SoC que los controladores y las vistas. En este sentido, pueden eliminar la necesidad de acciones y vistas que se encargan de los datos utilizados por elementos comunes de la interfaz de usuario.

Al igual que muchos otros aspectos de ASP.NET Core, las vistas admiten inserción de dependencias, lo que permite que los servicios se puedan insertar en las vistas.

Aislamiento de CSS

Aísle los estilos CSS a páginas, vistas y componentes individuales para reducir o evitar lo siguiente:

  • Dependencias de estilos globales que pueden ser difíciles de mantener.
  • Conflictos de estilo en el contenido anidado.

Para agregar un archivo CSS con ámbito para una página o vista, coloque los estilos CSS en un archivo .cshtml.css complementario que coincida con el nombre del archivo .cshtml. En el ejemplo siguiente, un archivo Index.cshtml.css proporciona estilos CSS que solo se aplican a la página o vista de Index.cshtml.

Pages/Index.cshtml.css (Razor Pages) o Views/Index.cshtml.css (MVC):

h1 {
    color: red;
}

El aislamiento de CSS se produce en tiempo de compilación. El marco reescribe selectores CSS para que coincidan con el marcado representado por las páginas o vistas de la aplicación. Estos estilos de CSS reescritos se unen y se generan como un recurso estático, {APP ASSEMBLY}.styles.css. El nombre del ensamblado del proyecto es el marcador de posición {APP ASSEMBLY}. Se coloca un vínculo a los estilos CSS agrupados en el diseño de la aplicación.

En el contenido de <head> del archivo Pages/Shared/_Layout.cshtml de la aplicación (Razor Pages) o de Views/Shared/_Layout.cshtml (MVC), agregue o confirme la presencia del vínculo a los estilos CSS agrupados:

<link rel="stylesheet" href="~/{APP ASSEMBLY}.styles.css" />

En el ejemplo siguiente, el nombre del ensamblado de la aplicación es WebApp:

<link rel="stylesheet" href="WebApp.styles.css" />

Los estilos definidos en un archivo CSS con ámbito solo se aplican a la salida representada del archivo coincidente. En el ejemplo anterior, cualquier declaración CSS h1 definida en otra parte de la aplicación no entra en conflicto con el estilo de encabezado de Index. Las reglas heredadas y en cascada de los estilos CSS permanecen en vigor para los archivos CSS con ámbito. Por ejemplo, los estilos aplicados directamente a un elemento <h1> del archivo Index.cshtml invalidan los estilos del archivo CSS con ámbito en Index.cshtml.css.

Nota

Para garantizar el aislamiento de estilos CSS en el momento de la unión, no se admite la importación de CSS en bloques de código Razor.

El aislamiento de CSS solo se aplica a los elementos HTML. El aislamiento de CSS no se admite para los asistentes de etiquetas.

Dentro del archivo CSS agrupado, cada página, vista o componente Razor está asociado a un identificador de ámbito en el formato b-{STRING}, donde el marcador de posición {STRING} es una cadena de diez caracteres generada por el marco. En el ejemplo siguiente se proporciona el estilo del elemento <h1> anterior en la página Index de una aplicación de Razor Pages:

/* /Pages/Index.cshtml.rz.scp.css */
h1[b-3xxtam6d07] {
    color: red;
}

En la página Index donde se aplica el estilo CSS desde el archivo agrupado, el identificador de ámbito se anexa como un atributo HTML:

<h1 b-3xxtam6d07>

El identificador es único para una aplicación. En tiempo de compilación, se crea un conjunto del proyecto con la convención {STATIC WEB ASSETS BASE PATH}/Project.lib.scp.css, donde el marcador de posición {STATIC WEB ASSETS BASE PATH} es la ruta de acceso base a los recursos web estáticos.

Si se usan otros proyectos, como paquetes NuGet o bibliotecas de clases de Razor, el archivo unido:

  • Hace referencia a los estilos mediante importaciones de CSS.
  • No se publica como recurso web estático de la aplicación que consume los estilos.

Compatibilidad del preprocesador de CSS

Los preprocesadores de CSS son útiles para mejorar el desarrollo de CSS mediante el uso de características como variables, anidamiento, módulos, mixins y herencia. Aunque el aislamiento de CSS no admite de forma nativa preprocesadores de CSS como Sass o Less, la integración de preprocesadores de CSS se realiza sin problemas siempre que se produzca la compilación del preprocesador antes de que el marco reescriba los selectores de CSS durante el proceso de compilación. Con Visual Studio, por ejemplo, configure la compilación del preprocesador existente como una tarea Antes de la compilación en el Explorador del Ejecutor de tareas de Visual Studio.

Muchos paquetes NuGet de terceros, como AspNetCore.SassCompiler, pueden compilar archivos SASS/SCSS al principio del proceso de compilación antes de que se produzca el aislamiento de CSS y no requieren ninguna configuración adicional.

Configuración del aislamiento de CSS

El aislamiento de CSS permite la configuración de algunos escenarios avanzados, como cuando hay dependencias en herramientas o flujos de trabajo existentes.

Personalización del formato del identificador de ámbito

En esta sección, el marcador de posición {Pages|Views} es Pages para aplicaciones Razor Pages o Views para aplicaciones MVC.

De forma predeterminada, los identificadores de ámbito usan el formato b-{STRING}, donde el marcador de posición {STRING} es una cadena de diez caracteres generada por el marco. Para personalizar el formato de un identificador de ámbito, actualice el archivo del proyecto a un patrón deseado:

<ItemGroup>
  <None Update="{Pages|Views}/Index.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

En el ejemplo anterior, el CSS generado para Index.cshtml.css cambia su identificador de ámbito de b-{STRING} a custom-scope-identifier.

Use identificadores de ámbito para lograr la herencia con archivos CSS de ámbito. En el siguiente ejemplo del archivo del proyecto, un archivo BaseView.cshtml.css contiene estilos comunes en todas las vistas. Un archivo DerivedView.cshtml.css hereda estos estilos.

<ItemGroup>
  <None Update="{Pages|Views}/BaseView.cshtml.css" CssScope="custom-scope-identifier" />
  <None Update="{Pages|Views}/DerivedView.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Use el operador comodín (*) para compartir los identificadores de ámbito en varios archivos:

<ItemGroup>
  <None Update="{Pages|Views}/*.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Cambio de la ruta de acceso base de recursos web estáticos

El archivo CSS con ámbito se genera en la raíz de la aplicación. En el archivo del proyecto, use la propiedad StaticWebAssetBasePath para cambiar la ruta de acceso predeterminada. En el ejemplo siguiente se coloca el archivo CSS con ámbito, y el resto de los recursos de la aplicación, en la ruta de acceso _content:

<PropertyGroup>
  <StaticWebAssetBasePath>_content/$(PackageId)</StaticWebAssetBasePath>
</PropertyGroup>

Deshabilitación de la unión automática

Para no usar el modo en que el marco publica y carga archivos con ámbito en tiempo de ejecución, use la propiedad DisableScopedCssBundling. Al usar esta propiedad, otras herramientas o procesos son responsables de tomar los archivos CSS aislados del directorio obj y de publicarlos y cargarlos en tiempo de ejecución:

<PropertyGroup>
  <DisableScopedCssBundling>true</DisableScopedCssBundling>
</PropertyGroup>

Razor Compatibilidad con la biblioteca de clases (RCL)

Cuando una Razor biblioteca de clases (RCL) proporciona estilos aislados, el atributo href de la etiqueta <link> apunta a {STATIC WEB ASSET BASE PATH}/{PACKAGE ID}.bundle.scp.css, donde los marcadores de posición son los siguientes:

  • {STATIC WEB ASSET BASE PATH}: ruta de acceso base del recurso web estático.
  • {PACKAGE ID}: el identificador del paquete de la biblioteca. El identificador del paquete tiene como valor predeterminado el nombre del ensamblado del proyecto si el identificador del paquete no se especifica en el archivo del proyecto.

En el ejemplo siguiente:

  • La ruta de acceso base del recurso web estático es _content/ClassLib.
  • El nombre del ensamblado de la biblioteca de clases es ClassLib.

Pages/Shared/_Layout.cshtml (Razor Pages) o Views/Shared/_Layout.cshtml (MVC):

<link href="_content/ClassLib/ClassLib.bundle.scp.css" rel="stylesheet">

Para obtener más información sobre RCL, vea los siguientes artículos:

Para obtener información sobre el aislamiento de CSS de Blazor, consulte Aislamiento de CSS de Blazor de ASP.NET Core.