Consumo de componentes ASP.NET Core Razor de bibliotecas de clases Razor (RCL)

Nota

Esta no es la versión más reciente de este artículo. Para la versión actual, consulta la versión .NET 8 de este artículo.

Advertencia

Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulta la Directiva de soporte técnico de .NET y .NET Core. Para la versión actual, consulta la versión .NET 8 de este artículo.

Importante

Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

Para la versión actual, consulta la versión .NET 8 de este artículo.

Los componentes se pueden compartir entre proyectos en una biblioteca de clases de Razor (RCL). Incluye componentes y recursos estáticos en una aplicación de:

  • Otro proyecto de la solución.
  • Una biblioteca de .NET a la que se hace referencia.
  • Un paquete NuGet.

Del mismo modo que los componentes son tipos normales de .NET, los componentes proporcionados por una RCL son ensamblados .NET normales.

Creación de una RCL

  1. Crea un nuevo proyecto.
  2. En el cuadro de diálogo Crear un proyecto, selecciona Biblioteca de clases de Razor en la lista de plantillas de proyecto de ASP.NET Core. Selecciona Siguiente.
  3. En el cuadro de diálogo Configura tu nuevo proyecto, indica un nombre de proyecto en el campo Nombre del proyecto. En los ejemplos de este tema se usa el nombre de proyecto ComponentLibrary. Selecciona Siguiente.
  4. En el cuadro de diálogo Información adicional, no selecciones Páginas y vistas de soporte. Selecciona Crear.
  5. Agrega la RCL a una solución:
    1. Abre la solución.
    2. Haz clic con el botón derecho en el Explorador de soluciones. Selecciona Agregar>Proyecto existente.
    3. Navega hasta el archivo del proyecto de la RCL.
    4. Selecciona el archivo de proyecto de la RCL (.csproj).
  6. Agrega una referencia a la RCL desde la aplicación:
    1. Haz clic con el botón derecho en el proyecto de la aplicación. Selecciona Agregar>Referencia de proyecto.
    2. Selecciona el proyecto de la RCL. Selecciona Aceptar.

Consumo de un componente Razor de una RCL

Para consumir los componentes de una RCL de otro proyecto, usa cualquiera de los métodos siguientes:

  • Usa el nombre completo del tipo de componente, que incluye el espacio de nombres de la RCL.
  • Los componentes individuales se pueden agregar por nombre sin el espacio de nombres de la RCL si la directiva @using de Razor declara el espacio de nombres de la RCL. Sigue uno de estos procedimientos:
    • Agrega la directiva @using a los componentes individuales.
    • Incluye la directiva @using en el archivo de nivel superior _Imports.razor a fin de que los componentes de la biblioteca estén disponibles para un proyecto completo. Agrega la directiva a un archivo _Imports.razor en cualquier nivel para aplicar el espacio de nombres a un solo componente o a un conjunto de componentes dentro de una carpeta. Cuando se usa un archivo _Imports.razor, los componentes individuales no requieren una directiva @using para el espacio de nombres de la RCL.

En los ejemplos siguientes, ComponentLibrary es una RCL que contiene el componente Component1. El componente Component1 es un componente de ejemplo que se agrega automáticamente a una RCL creada a partir de la plantilla de proyecto de RCL que no se crea para admitir páginas y vistas.

Component1.razor en la RCL ComponentLibrary:

<div class="my-component">
    This component is defined in the <strong>ComponentLibrary</strong> package.
</div>

En la aplicación que consume la RCL, haz referencia al componente Component1 mediante su espacio de nombres, como se muestra en el ejemplo siguiente.

ConsumeComponent1.razor:

@page "/consume-component-1"

<h1>Consume component (full namespace example)</h1>

<ComponentLibrary.Component1 />

También puedes agregar una directiva @using y usar el componente sin su espacio de nombres. La siguiente directiva @using también puede aparecer en cualquier archivo _Imports.razor en el archivo actual o situado por encima del mismo.

ConsumeComponent2.razor:

@page "/consume-component-2"
@using ComponentLibrary

<h1>Consume component (<code>@@using</code> example)</h1>

<Component1 />

En el caso de los componentes de biblioteca que usan el aislamiento de CSS, los estilos de componente se ponen automáticamente a disposición de la aplicación de consumo. No es necesario vincular ni importar manualmente las hojas de estilos de componentes individuales de la biblioteca ni su archivo CSS agrupado en la aplicación que consume la biblioteca. La aplicación usa importaciones CSS para hacer referencia a los estilos agrupados de la RCL. Los estilos agrupados no se publican como recursos web estáticos de la aplicación que consume la biblioteca. Para una biblioteca de clases denominada ClassLib y una aplicación Blazor con una hoja de estilos BlazorSample.styles.css, la hoja de estilos de la RCL se importa automáticamente en la parte superior de la hoja de estilos de la aplicación en tiempo de compilación:

@import '_content/ClassLib/ClassLib.bundle.scp.css';

En los ejemplos anteriores, la hoja de estilos de Component1 (Component1.razor.css) se agrupa automáticamente.

Component1.razor.css en la RCL ComponentLibrary:

.my-component {
    border: 2px dashed red;
    padding: 1em;
    margin: 1em 0;
    background-image: url('background.png');
}

La imagen de fondo también se incluye desde la plantilla de proyecto de RCL y reside en la carpeta wwwroot de la RCL.

wwwroot/background.png en la RCL ComponentLibrary:

Imagen de fondo seccionada diagonalmente de la plantilla de proyecto de RCL

Para proporcionar estilos de componentes de biblioteca adicionales de hojas de estilos en la carpeta wwwroot de la biblioteca, agrega etiquetas <link> de hoja de estilos al consumidor de la RCL, como se muestra en el ejemplo siguiente.

Importante

Por lo general, los componentes de biblioteca usan el aislamiento CSS para agrupar y proporcionar estilos de componentes. Los estilos de componentes que se basan en el aislamiento CSS están disponibles automáticamente para la aplicación que usa la RCL. No es necesario vincular ni importar manualmente las hojas de estilos de componentes individuales de la biblioteca ni su archivo CSS agrupado en la aplicación que consume la biblioteca. El ejemplo siguiente es para proporcionar hojas de estilos globales fuera del aislamiento CSS, que normalmente no es un requisito para las aplicaciones típicas que consumen RCL.

La siguiente imagen de fondo se usa en el ejemplo siguiente. Si implementas el ejemplo que se muestra en esta sección, haz clic con el botón derecho en la imagen para guardarla localmente.

wwwroot/extra-background.png en la RCL ComponentLibrary:

Imagen de fondo seccionada diagonalmente agregada a la biblioteca por el desarrollador

Agrega una nueva hoja de estilos a la RCL con una clase extra-style.

wwwroot/additionalStyles.css en la RCL ComponentLibrary:

.extra-style {
    border: 2px dashed blue;
    padding: 1em;
    margin: 1em 0;
    background-image: url('extra-background.png');
}

Agrega un componente a la RCL que use la clase extra-style.

ExtraStyles.razor en la RCL ComponentLibrary:

<div class="extra-style">
    <p>
        This component is defined in the <strong>ComponentLibrary</strong> package.
    </p>
</div>

Agrega una página a la aplicación que use el componente ExtraStyles de la RCL.

ConsumeComponent3.razor:

@page "/consume-component-3"
@using ComponentLibrary

<h1>Consume component (<code>additionalStyles.css</code> example)</h1>

<ExtraStyles />

Crea un vínculo a la hoja de estilos de la biblioteca en el marcado <head> de la aplicación (ubicación del contenido de <head>):

Blazor Web App:

<link href="@Assets["_content/ComponentLibrary/additionalStyles.css"]" rel="stylesheet">

Aplicaciones Blazor WebAssembly independientes:

<link href="_content/ComponentLibrary/additionalStyles.css" rel="stylesheet">
<link href="_content/ComponentLibrary/additionalStyles.css" rel="stylesheet">

En el caso de los componentes de biblioteca que usan el aislamiento de CSS, los estilos de componente se ponen automáticamente a disposición de la aplicación de consumo. No es necesario vincular ni importar manualmente las hojas de estilos de componentes individuales de la biblioteca ni su archivo CSS agrupado en la aplicación que consume la biblioteca. La aplicación usa importaciones CSS para hacer referencia a los estilos agrupados de la RCL. Los estilos agrupados no se publican como recursos web estáticos de la aplicación que consume la biblioteca. Para una biblioteca de clases denominada ClassLib y una aplicación Blazor con una hoja de estilos BlazorSample.styles.css, la hoja de estilos de la RCL se importa automáticamente en la parte superior de la hoja de estilos de la aplicación en tiempo de compilación:

@import '_content/ClassLib/ClassLib.bundle.scp.css';

En los ejemplos anteriores, la hoja de estilos de Component1 (Component1.razor.css) se agrupa automáticamente.

Component1.razor.css en la RCL ComponentLibrary:

.my-component {
    border: 2px dashed red;
    padding: 1em;
    margin: 1em 0;
    background-image: url('background.png');
}

La imagen de fondo también se incluye desde la plantilla de proyecto de RCL y reside en la carpeta wwwroot de la RCL.

wwwroot/background.png en la RCL ComponentLibrary:

Imagen de fondo seccionada diagonalmente de la plantilla de proyecto de RCL

El componente de ejemplo Component1 de la RCL usa la imagen de fondo y la hoja de estilos siguientes. No es necesario agregar estos recursos estáticos a una nueva RCL creada a partir de la plantilla de proyecto de RCL, ya que la plantilla de proyecto los agrega automáticamente.

wwwroot/background.png en la RCL ComponentLibrary:

Imagen de fondo seccionada diagonalmente agregada a la biblioteca por la plantilla de proyecto de RCL

wwwroot/styles.css en la RCL ComponentLibrary:

.my-component {
    border: 2px dashed red;
    padding: 1em;
    margin: 1em 0;
    background-image: url('background.png');
}

Para proporcionar la clase CSS my-component de Component1, enlaza a la hoja de estilos de la biblioteca en el marcado de la aplicación <head> (ubicación del <head> contenido):

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

Hacer que los componentes enrutables estén disponibles en la RCL

Para que los componentes enrutables de la RCL estén disponibles para las solicitudes directas, el ensamblado de la RCL debe revelarse al enrutador de la aplicación.

Abre el componente App de la aplicación (App.razor). Asigna una colección Assembly al parámetro AdditionalAssemblies del componente Router para incluir el ensamblado del RCL. En el ejemplo siguiente, el componente ComponentLibrary.Component1 se usa para detectar el ensamblado de la RCL.

AdditionalAssemblies="new[] { typeof(ComponentLibrary.Component1).Assembly }"

Para obtener más información, consulta Enrutamiento y navegación de Blazor de ASP.NET Core.

Creación de una RCL con recursos estáticos en la carpeta wwwroot

Los recursos estáticos de una RCL están disponibles para cualquier aplicación que use la biblioteca.

Coloca los recursos estáticos en la carpeta wwwroot de la RCL y haz referencia a estos con la siguiente ruta de acceso en la aplicación: _content/{PACKAGE ID}/{PATH AND FILE NAME}. El marcador de posición {PACKAGE ID} es el id. de paquete de la biblioteca. El id. de paquete tiene como valor predeterminado el nombre de ensamblado del proyecto si <PackageId> no se especifica en el archivo del proyecto. El marcador de posición {PATH AND FILE NAME} es la ruta de acceso y el nombre de archivo en wwwroot. Este formato de ruta de acceso también se usa en la aplicación para los recursos estáticos proporcionados por un paquete NuGet agregado a la RCL.

En el siguiente ejemplo se muestra el uso de recursos estáticos de RCL con una RCL llamada ComponentLibrary y una aplicación Blazor que use la RCL. La aplicación tiene una referencia de proyecto para la RCL ComponentLibrary.

La siguiente imagen de Jeep® se usa en el ejemplo de esta sección. Si implementas el ejemplo que se muestra en esta sección, haz clic con el botón derecho en la imagen para guardarla localmente.

wwwroot/jeep-yj.png en la RCL ComponentLibrary:

Jeep YJ®

Agrega el siguiente componente JeepYJ a la RCL.

JeepYJ.razor en la RCL ComponentLibrary:

<h3>ComponentLibrary.JeepYJ</h3>

<p>
    <img alt="Jeep YJ&reg;" src="_content/ComponentLibrary/jeep-yj.png" />
</p>

Agrega el siguiente componente Jeep a la aplicación que use la RCL ComponentLibrary. El componente Jeep usa:

  • La imagen de Jeep YJ® de la carpeta wwwroot de la RCL ComponentLibrary.
  • El componente JeepYJ de la RCL.

Jeep.razor:

@page "/jeep"
@using ComponentLibrary

<div style="float:left;margin-right:10px">
    <h3>Direct use</h3>

    <p>
        <img alt="Jeep YJ&reg;" src="_content/ComponentLibrary/jeep-yj.png" />
    </p>
</div>

<JeepYJ />

<p>
    <em>Jeep</em> and <em>Jeep YJ</em> are registered trademarks of 
    <a href="https://www.stellantis.com">FCA US LLC (Stellantis NV)</a>.
</p>

Componente Jeep representado:

Componente Jeep

Para obtener más información, consulta Interfaz de usuario reutilizable de Razor en bibliotecas de clases con ASP.NET Core.

Creación de una RCL con archivos JavaScript colocados con componentes

La colocación de archivos de JavaScript (JS) para componentes Razor es una manera cómoda de organizar los scripts en una aplicación.

Los componentes Razor de aplicaciones Blazor intercalan archivos JS mediante la extensión .razor.js y se pueden direccionar públicamente mediante la ruta de acceso al archivo del proyecto:

{PATH}/{COMPONENT}.razor.js

  • El marcador de posición {PATH} es la ruta de acceso al componente.
  • El marcador de posición {COMPONENT} es el componente.

Cuando se publica la aplicación, el marco mueve automáticamente el script a la raíz web. Los scripts se mueven a bin/Release/{TARGET FRAMEWORK MONIKER}/publish/wwwroot/{PATH}/{COMPONENT}.razor.js, donde los marcadores de posición son:

No se requiere ningún cambio en la dirección URL relativa del script, ya que Blazor se encarga de colocar el archivo JS en los recursos estáticos publicados por ti.

Esta sección y los ejemplos siguientes se centran principalmente en explicar la intercalación de archivos JS. En el primer ejemplo se muestra un archivo intercalado JS con una función normal JS. En el segundo ejemplo se muestra el uso de un módulo para cargar una función, que es el enfoque recomendado para la mayoría de las aplicaciones de producción. Las llamadas JS desde .NET se tratan completamente en Llamar a funciones de JavaScript desde métodos de .NET en ASP.NET Core Blazor, donde hay más explicaciones de la BlazorJS API con ejemplos adicionales. La eliminación de componentes, que está presente en el segundo ejemplo, se trata en ASP.NET Core Razor ciclo de vida de componentes.

El siguiente JsCollocation1 componente carga un script a través de un HeadContent componente y llama a una JS función con IJSRuntime.InvokeAsync. El marcador de posición {PATH} es la ruta de acceso al componente.

Importante

Si usas el código siguiente para una demostración en una aplicación de prueba, cambie el {PATH} marcador de posición a la ruta de acceso del componente (ejemplo: Components/Pages en .NET 8 o posterior o Pages en .NET 7 o anterior). En una Blazor Web App (.NET 8 o posterior), el componente requiere un modo de representación interactivo aplicado globalmente a la aplicación o a la definición del componente.

Agrega el siguiente script después del script Blazor (ubicación del Blazor script de inicio ):

<script src="{PATH}/JsCollocation1.razor.js"></script>

Componente JsCollocation1 ({PATH}/JsCollocation1.razor):

@page "/js-collocation-1"
@inject IJSRuntime JS

<PageTitle>JS Collocation 1</PageTitle>

<h1>JS Collocation Example 1</h1>

<button @onclick="ShowPrompt">Call showPrompt1</button>

@if (!string.IsNullOrEmpty(result))
{
    <p>
        Hello @result!
    </p>
}

@code {
    private string? result;

    public async void ShowPrompt()
    {
        result = await JS.InvokeAsync<string>(
            "showPrompt1", "What's your name?");
        StateHasChanged();
    }
}

El archivo colocado JS se coloca junto al archivo de JsCollocation1 componente con el nombre de archivoJsCollocation1.razor.js. En el componente JsCollocation1, se hace referencia al script en la ruta de acceso del archivo intercalado. En el ejemplo siguiente, la función showPrompt1 acepta el nombre del usuario de un Window prompt() y lo devuelve al componente JsCollocation1 para mostrarlo.

{PATH}/JsCollocation1.razor.js:

function showPrompt1(message) {
  return prompt(message, 'Type your name here');
}

El enfoque anterior no se recomienda para su uso general en aplicaciones de producción porque contamina el cliente con funciones globales. Un mejor enfoque para las aplicaciones de producción es usar módulos JS. Los mismos principios generales se aplican a la carga JS de un módulo desde un archivo combinado JS, como se muestra en el siguiente ejemplo.

El método del siguiente componente JsCollocation2 OnAfterRenderAsync carga un módulo JS en module, que es una IJSObjectReference de la clase de componente. module se usa para llamar a la función showPrompt2. El marcador de posición {PATH} es la ruta de acceso al componente.

Importante

Si usas el código siguiente para una demostración en una aplicación de prueba, cambia el {PATH} marcador de posición a la ruta de acceso del componente. En una Blazor Web App (.NET 8 o posterior), el componente requiere un modo de representación interactivo aplicado globalmente a la aplicación o a la definición del componente.

Componente JsCollocation2 ({PATH}/JsCollocation2.razor):

@page "/js-collocation-2"
@implements IAsyncDisposable
@inject IJSRuntime JS

<PageTitle>JS Collocation 2</PageTitle>

<h1>JS Collocation Example 2</h1>

<button @onclick="ShowPrompt">Call showPrompt2</button>

@if (!string.IsNullOrEmpty(result))
{
    <p>
        Hello @result!
    </p>
}

@code {
    private IJSObjectReference? module;
    private string? result;

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            /*
                Change the {PATH} placeholder in the next line to the path of
                the collocated JS file in the app. Examples:

                ./Components/Pages/JsCollocation2.razor.js (.NET 8 or later)
                ./Pages/JsCollocation2.razor.js (.NET 7 or earlier)
            */
            module = await JS.InvokeAsync<IJSObjectReference>("import",
                "./{PATH}/JsCollocation2.razor.js");
        }
    }

    public async void ShowPrompt()
    {
        if (module is not null)
        {
            result = await module.InvokeAsync<string>(
                "showPrompt2", "What's your name?");
            StateHasChanged();
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
}

{PATH}/JsCollocation2.razor.js:

export function showPrompt2(message) {
  return prompt(message, 'Type your name here');
}

El uso de scripts y módulos para JS intercalados en una biblioteca de clases (RCL) de Razor solo se admite para el mecanismo de interoperabilidad JS de Blazor basado en la interfaz de IJSRuntime. Si vas a implementar interoperabilidad JavaScript [JSImport]/[JSExport], consulta Interoperabilidad JSImport/JSExport de JavaScript con ASP.NET Core Blazor.

En el caso de scripts o módulos proporcionados por una biblioteca de clases (RCL) de Razor mediante la interoperabilidad de JS basada en IJSRuntime, se usa la siguiente ruta de acceso:

./_content/{PACKAGE ID}/{PATH}/{COMPONENT}.{EXTENSION}.js

  • El segmento de trazado del directorio actual (./) es necesario para crear la ruta de recurso estático correcta para el archivo JS.
  • El marcador de posición {PACKAGE ID} es el identificador de paquete de la RCL (o el nombre de la biblioteca para una biblioteca de clases a la que hace referencia la aplicación).
  • El marcador de posición {PATH} es la ruta de acceso al componente. Si un componente Razor se encuentra en la raíz de la RCL, no se incluye el segmento de ruta.
  • El marcador de posición {COMPONENT} es el componente.
  • El marcador de posición {EXTENSION} coincide con la extensión de la componente, ya sea razor o cshtml.

En el ejemplo siguiente de aplicación Blazor:

  • El identificador de paquete de la RCL es AppJS.
  • Los scripts de un módulo se cargan para el componente JsCollocation3 (JsCollocation3.razor).
  • El componente JsCollocation3 está en la carpeta Components/Pages de la RCL.
module = await JS.InvokeAsync<IJSObjectReference>("import", 
    "./_content/AppJS/Components/Pages/JsCollocation3.razor.js");

Proporcionar componentes y recursos estáticos a varias aplicaciones de Blazor hospedadas

Para más información, consulte Varias aplicaciones de ASP.NET Core Blazor WebAssembly hospedadas.

Analizador de compatibilidad del explorador del cliente

Las aplicaciones del lado del cliente aprovechan toda la superficie de las API de .NET, pero no todas las API de .NET son compatibles con WebAssembly debido a las limitaciones del entorno aislado del navegador. Las API no compatibles inician la excepción PlatformNotSupportedException cuando se ejecutan en WebAssembly. Un analizador de compatibilidad de plataforma advierte al desarrollador cuando la aplicación usa API que no son compatibles con las plataformas de destino de la aplicación. Para las aplicaciones del lado del cliente, esto significa comprobar que las API son compatibles con los exploradores. La anotación de API de .NET Framework para el analizador de compatibilidad es un proceso constante, por lo que no todas las API de .NET Framework están anotadas actualmente.

Los objetos Blazor Web App que permiten componentes interactivos WebAssembly, aplicaciones Blazor WebAssembly y proyectos RCL habilitan automáticamente las comprobaciones de compatibilidad del explorador agregando browser como plataforma compatible con el elemento MSBuild SupportedPlatform. Los desarrolladores de bibliotecas pueden agregar manualmente el elemento SupportedPlatform al archivo de proyecto de una biblioteca para habilitar la característica:

<ItemGroup>
  <SupportedPlatform Include="browser" />
</ItemGroup>

Al crear una biblioteca, especifique browser en UnsupportedOSPlatformAttribute para indicar que los exploradores no admiten una API determinada:

using System.Runtime.Versioning;

...

[UnsupportedOSPlatform("browser")]
private static string GetLoggingDirectory()
{
    ...
}

Para más información, vea Anotación de API como no compatibles en plataformas específicas (repositorio dotnet/designs de GitHub).

Aislamiento de JavaScript en módulos de JavaScript

Blazor permite el aislamiento de JavaScript en módulos de JavaScript estándar. El aislamiento de JavaScript reporta las siguientes ventajas:

  • El código JavaScript importado no contamina el espacio de nombres global.
  • No es necesario que los consumidores de la biblioteca y los componentes importen manualmente el código JavaScript relacionado.

Para más información, vea Llamada a funciones de JavaScript desde métodos de .NET en Blazor de ASP.NET Core.

Prevención del recorte de los métodos de .NET invocables de JavaScript

La revinculación en tiempo de ejecución recorta los métodos de .NET invocables de la instancia de clase JavaScript a menos que se conserven explícitamente. Para obtener más información, vea Llamada a métodos de .NET desde funciones de JavaScript en ASP.NET Core Blazor.

Compilación, empaquetado y envío de bibliotecas a NuGet

Dado que las bibliotecas de clases Razor que contienen componentes Razor son bibliotecas estándar de .NET, se empaquetan y se envían a NuGet de la misma manera que cualquier otra biblioteca. El empaquetado se realiza mediante el comando dotnet pack en un shell de comandos:

dotnet pack

Cargue el paquete en NuGet usando el comando dotnet nuget push en un shell de comandos.

Marcas comerciales

Jeep y Jeep YJ son marcas registradas de FCA US LLC (Stellantis NV).

Recursos adicionales