Uso de las API de ASP.NET Core en una biblioteca de clases

Por Scott Addie

En este documento se proporcionan instrucciones para usar las API de ASP.NET Core en una biblioteca de clases. Para obtener todas las demás instrucciones de bibliotecas, consulte Guía de la biblioteca de código abierto.

Determinación de las versiones de ASP.NET Core compatibles

ASP.NET Core sigue la directiva de compatibilidad de .NET Core. Consulte la directiva de compatibilidad al determinar qué versiones de ASP.NET Core se admiten en una biblioteca. Una biblioteca debe cumplir estas condiciones:

  • Hacer todo lo posible para admitir todas las versiones de ASP.NET Core clasificadas como versiones compatibles a largo plazo (LTS).
  • No sentirse obligada a admitir versiones de ASP.NET Core clasificadas como final del ciclo de vida (EOL).

A medida que se lanzan versiones preliminares de ASP.NET Core, se publican los cambios importantes en el repositorio aspnet/Announcements de GitHub. Las pruebas de compatibilidad de las bibliotecas se pueden llevar a cabo a medida que se desarrollan las características del marco.

Uso del marco compartido de .NET Core

Con el lanzamiento de .NET Core 3,0, muchos ensamblados de ASP.NET Core ya no se publican en NuGet como paquetes. Ahora, los ensamblados se incluyen en el marco compartido de Microsoft.AspNetCore.App, que se instala con los instaladores del SDK de .NET Core y el entorno de ejecución. Para obtener una lista de los paquetes que ya no se publican, vea Quitar referencias de paquetes obsoletas.

A partir de .NET Core 3.0, los proyectos que usan el SDK de MSBuild Microsoft.NET.Sdk.Web hacen referencia implícitamente al marco compartido. Los proyectos que usan el SDK de Microsoft.NET.Sdk o Microsoft.NET.Sdk.Razor deben hacer referencia a ASP.NET Core para usar las API de ASP.NET Core en el marco compartido.

Para hacer referencia a ASP.NET Core, agregue el siguiente elemento <FrameworkReference> al archivo del proyecto:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

</Project>

Inclusión de la extensibilidad Blazor

Blazor admite la creación de bibliotecas de clases de componentes Razor para aplicaciones del lado servidor y del lado cliente. Para admitir componentes Razor en una biblioteca de clases, la biblioteca de clases debe usar el SDK Microsoft.NET.Sdk.Razor MICROSOFT.NET.SDK.Razor

Compatibilidad con aplicaciones del lado servidor y del lado cliente

Para admitir el consumo de componentes Razor por parte de las aplicaciones del lado servidor y del lado cliente desde una sola biblioteca, siga estas instrucciones para el editor.

Use la plantilla de proyecto de Biblioteca de clases de Razor .

Nota:

No active la casilla Páginas y vistas de soporte técnico. Al seleccionar la casilla, se crea una biblioteca de clases que solo admite aplicaciones del lado servidor.

La biblioteca generada a partir de la plantilla de proyecto:

  • Tiene como destino la versión actual de .NET Framework en función del SDK instalado.
  • Habilita las comprobaciones de compatibilidad del explorador para las dependencias de plataforma incluyendo browser como plataforma compatible con el elemento SupportedPlatform de MSBuild.
  • Agrega una referencia de paquete NuGet para Microsoft.AspNetCore.Components.Web.

RazorClassLibrary-CSharp.csproj (origen de referencia)

Nota

Los vínculos de la documentación al origen de referencia de .NET cargan normalmente la rama predeterminada del repositorio, que representa el desarrollo actual para la próxima versión de .NET. Para seleccionar una etiqueta de una versión específica, use la lista desplegable Cambiar ramas o etiquetas. Para obtener más información, vea Procedimientos para seleccionar una etiqueta de versión de código fuente de ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Compatibilidad con varias versiones del marco

Si la biblioteca debe admitir características agregadas a Blazor en la versión actual, al mismo tiempo que admite una o varias versiones anteriores, se configurará como biblioteca de destino múltiple. Proporcione una lista separada por punto y coma de monikers de la plataforma de destino (TFM) en la propiedad TargetFrameworks de MSBuild:

<TargetFrameworks>{TARGET FRAMEWORKS}</TargetFrameworks>

En el ejemplo anterior, el marcador de posición {TARGET FRAMEWORKS} representa la lista de TFM separados por punto y coma. Por ejemplo, netcoreapp3.1;net5.0.

Admisión exclusiva del consumo del lado servidor

Las bibliotecas de clases rara vez se compilan para admitir solo aplicaciones del lado servidor. Si la biblioteca de clases solo necesita características específicas del lado servidor, como el acceso a CircuitHandler o Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage, o bien usa características específicas de ASP.NET Core, como middleware, controladores MVC o Razor Pages, utilice uno de los enfoques siguientes:

  • Especifique que la biblioteca admite páginas y vistas cuando se crea con la casilla Páginas y vistas de soporte técnico (Visual Studio) o la opción -s|--support-pages-and-views con el comando dotnet new:

    dotnet new razorclasslib -s
    
  • Proporcione solo una referencia de marco a ASP.NET Core en el archivo del proyecto de la biblioteca, además de cualquier otra propiedad de MS Build necesaria:

    <ItemGroup>
      <FrameworkReference Include="Microsoft.AspNetCore.App" />
    </ItemGroup>
    

Para obtener más información sobre las bibliotecas que contienen componentes de Razor, vea Consumo de componentes Razor de ASP.NET Core de una biblioteca de clases Razor (RCL).

Inclusión de la extensibilidad MVC

En esta sección se describen las recomendaciones para las bibliotecas que incluyen:

En esta sección no se explica la compatibilidad con múltiples versiones de MVC. Para obtener instrucciones sobre cómo admitir varias versiones de ASP.NET Core, consulte Compatibilidad con varias versiones de ASP.NET Core.

Vistas de Razor o Razor Pages

Un proyecto que incluya vistas de Razor o Razor Pages debe usar el SDK Microsoft.NET.Sdk.Razor

Si el proyecto tiene como destino .NET Core 3.x, requiere lo siguiente:

  • Una propiedad de MSBuild AddRazorSupportForMvc establecida en true.
  • Un elemento <FrameworkReference> para el marco compartido.

La plantilla de proyecto Biblioteca de clases de Razor cumple los requisitos anteriores de los proyectos que tienen como destino .NET Core. Utilice las instrucciones siguientes para su editor.

Use la plantilla de proyecto de Biblioteca de clases de Razor . Se activa la casilla Support pages and views (Admitir páginas y vistas) de la plantilla.

Por ejemplo:

<Project Sdk="Microsoft.NET.Sdk.Razor">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

</Project>

Si el proyecto tiene como destino .NET Standard, se requiere una referencia de paquete de Microsoft.AspNetCore.Mvc. El paquete Microsoft.AspNetCore.Mvc se ha migrado al marco compartido en ASP.NET Core 3.0 y, por tanto, ya no se publica. Por ejemplo:

<Project Sdk="Microsoft.NET.Sdk.Razor">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
  </ItemGroup>

</Project>

Asistentes de etiquetas

Un proyecto que incluye asistentes de etiquetas debe usar el SDK Microsoft.NET.Sdk. Si el destino es .NET Core 3.x, agregue un elemento <FrameworkReference> para el marco compartido. Por ejemplo:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

</Project>

Si el destino es .NET Standard (para admitir versiones anteriores a ASP.NET Core 3.x), agregue una referencia de paquete a Microsoft.AspNetCore.Mvc.Razor. El paquete de Microsoft.AspNetCore.Mvc.Razor se ha migrado al marco compartido y, por tanto, ya no se publica. Por ejemplo:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
  </ItemGroup>

</Project>

Componentes de vista

Un proyecto que incluya Componentes de vista debe utilizar el SDK de Microsoft.NET.Sdk. Si el destino es .NET Core 3.x, agregue un elemento <FrameworkReference> para el marco compartido. Por ejemplo:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

</Project>

Si el destino es .NET Standard (para admitir versiones anteriores a ASP.NET Core 3.x), agregue una referencia de paquete a Microsoft.AspNetCore.Mvc.ViewFeatures. El paquete de Microsoft.AspNetCore.Mvc.ViewFeatures se ha migrado al marco compartido y, por tanto, ya no se publica. Por ejemplo:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.2.0" />
  </ItemGroup>

</Project>

Compatibilidad con varias versiones de ASP.NET Core

Se requiere la compatibilidad con múltiples versiones para crear una biblioteca que admita diferentes variantes de ASP.NET Core. Piense en un escenario en el que una biblioteca de asistentes de etiquetas deba admitir las siguientes variantes de ASP.NET Core:

  • ASP.NET Core 2.1 con .NET Framework 4.6.1 como destino
  • ASP.NET Core 2.x con .NET Core 2.x como destino
  • ASP.NET Core 3.x con .NET Core 3.x como destino

El siguiente archivo de proyecto admite estas variantes a través de la propiedad TargetFrameworks:

<Project Sdk="Microsoft.NET.Sdk">
  
  <PropertyGroup>
    <TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net461</TargetFrameworks>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Markdig" Version="0.16.0" />
  </ItemGroup>
  
  <ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor" Version="2.1.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
</Project>

Con el archivo de proyecto anterior:

  • El paquete de Markdig se agrega a todos los consumidores.
  • Se agrega una referencia a Microsoft.AspNetCore.Mvc.Razor para los consumidores que tienen como destino .NET Framework 4.6.1 o posterior, o .NET Core 2.x. La versión 2.1.0 del paquete funciona con ASP.NET Core 2.2 gracias a la compatibilidad con versiones anteriores.
  • Se hace referencia al marco compartido para los consumidores que tienen como destino .NET Core 3.x. El paquete de Microsoft.AspNetCore.Mvc.Razor se incluye en el marco compartido.

Como alternativa, se podría tomar como destino .NET Standard 2.0 en lugar de .NET Core 2.1 y .NET Framework 4.6.1:

<Project Sdk="Microsoft.NET.Sdk">
  
  <PropertyGroup>
    <TargetFrameworks>netstandard2.0;netcoreapp3.1</TargetFrameworks>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Markdig" Version="0.16.0" />
  </ItemGroup>
  
  <ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor" Version="2.1.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
</Project>

Con el archivo de proyecto anterior, hay que tomar en cuenta los siguientes aspectos:

  • Dado que la biblioteca solo contiene asistentes de etiquetas, es más sencillo dirigirse a las plataformas específicas en las que se ejecuta ASP.NET Core: .NET Core y .NET Framework. Los asistentes de etiquetas no se pueden usar en otros marcos de destino compatibles con .NET Standard 2.0 como Unity, UWP y Xamarin.
  • El uso de .NET Standard 2.0 de .NET Framework tiene algunos problemas que se han solucionado en .NET Framework 4.7.2. Puede mejorar la experiencia de los consumidores que usan .NET Framework de 4.6.1 a 4.7.1 tomando como destino .NET Framework 4.6.1.

Si la biblioteca necesita llamar a API específicas de la plataforma, diríjase a implementaciones de .NET específicas en lugar de .NET Standard. Para obtener más información, consulte Compatibilidad con múltiples versiones.

Uso de una API que no ha cambiado

Imagine un escenario en el que está actualizando una biblioteca de middleware de .NET Core 2.2 a 3.1. Las API de middleware ASP.NET Core que se usan en la biblioteca no han cambiado entre ASP.NET Core 2.2 y 3.1. Siga estos pasos para seguir admitiendo la biblioteca de middleware en .NET Core 3.1:

Uso de una API que ha cambiado

Imagine un escenario en el que está actualizando una biblioteca de .NET Core 2.2 a .NET Core 3.1. Una API de ASP.NET Core que se usa en la biblioteca tiene un cambio importante en ASP.NET Core 3.1. Considere si la biblioteca se puede volver a escribir para que no use la API dañada en todas las versiones.

Si puede volver a escribir la biblioteca, hágalo y continúe con el marco anterior como destino (por ejemplo, .NET Standard 2.0 o .NET Framework 4.6.1) con referencias de paquete.

Si no puede volver a escribir la biblioteca, siga estos pasos:

  • Agregue un destino para .NET Core 3.1.
  • Agregue un elemento <FrameworkReference> para el marco compartido.
  • Use la directiva de preprocesador de #if con el símbolo del marco de destino adecuado para compilar el código de forma condicional.

Por ejemplo, las lecturas y escrituras sincrónicas en secuencias de respuesta y solicitud HTTP están deshabilitadas de forma predeterminada a partir de ASP.NET Core 3.1. ASP.NET Core 2.2 admite el comportamiento sincrónico de forma predeterminada. Considere una biblioteca de middleware en la que se deben habilitar las lecturas y escrituras sincrónicas donde se está produciendo la E/S. La biblioteca debe incluir el código para habilitar las características sincrónicas en la directiva de preprocesador adecuada. Por ejemplo:

public async Task Invoke(HttpContext httpContext)
{
    if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal))
    {
        httpContext.Response.StatusCode = (int) HttpStatusCode.OK;
        httpContext.Response.ContentType = "application/json";
        httpContext.Response.ContentLength = _bufferSize;

#if !NETCOREAPP3_1 && !NETCOREAPP5_0
        var syncIOFeature = httpContext.Features.Get<IHttpBodyControlFeature>();
        if (syncIOFeature != null)
        {
            syncIOFeature.AllowSynchronousIO = true;
        }

        using (var sw = new StreamWriter(
            httpContext.Response.Body, _encoding, bufferSize: _bufferSize))
        {
            _json.Serialize(sw, new JsonMessage { message = "Hello, World!" });
        }
#else
        await JsonSerializer.SerializeAsync<JsonMessage>(
            httpContext.Response.Body, new JsonMessage { message = "Hello, World!" });
#endif
        return;
    }

    await _next(httpContext);
}

Uso de una API presentada en 3.1

Imagine que quiere usar una API de ASP.NET Core que se presentó en ASP.NET Core 3.1. Pregúntese lo siguiente:

  1. ¿La biblioteca requiere funcionalmente la nueva API?
  2. ¿La biblioteca puede implementar esta característica de manera diferente?

Si la biblioteca requiere funcionalmente la API y no hay manera de implementarla en el nivel inferior:

  • Diríjase solo a .NET Core 3.x.
  • Agregue un elemento <FrameworkReference> para el marco compartido.

Si la biblioteca puede implementar esta característica de manera diferente:

  • Agregue .NET Core 3.x como plataforma de destino.
  • Agregue un elemento <FrameworkReference> para el marco compartido.
  • Use la directiva de preprocesador de #if con el símbolo del marco de destino adecuado para compilar el código de forma condicional.

Por ejemplo, el siguiente asistente de etiquetas usa la interfaz IWebHostEnvironment presentada en ASP.NET Core 3.1. Los consumidores que tienen como destino .NET Core 3.1 ejecutan la ruta de acceso al código definida por el símbolo del marco de destino NETCOREAPP3_1. El tipo de parámetro de constructor del asistente de etiquetas cambia a IHostingEnvironment para los consumidores de .NET Core 2.1 y .NET Framework 4.6.1. Este cambio era necesario porque ASP.NET Core 3.1 marcó IHostingEnvironment como obsoleto y recomendó su sustitución por IWebHostEnvironment.

[HtmlTargetElement("script", Attributes = "asp-inline")]
public class ScriptInliningTagHelper : TagHelper
{
    private readonly IFileProvider _wwwroot;

#if NETCOREAPP3_1
    public ScriptInliningTagHelper(IWebHostEnvironment env)
#else
    public ScriptInliningTagHelper(IHostingEnvironment env)
#endif
    {
        _wwwroot = env.WebRootFileProvider;
    }

    // code omitted for brevity
}

El siguiente archivo de proyecto de destino múltiple admite este escenario del asistente de etiquetas:

<Project Sdk="Microsoft.NET.Sdk">
  
  <PropertyGroup>
    <TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net461</TargetFrameworks>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Markdig" Version="0.16.0" />
  </ItemGroup>
  
  <ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp3.1'">
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor" Version="2.1.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
</Project>

Uso de una API que se ha quitado del marco compartido

Para usar un ensamblado de ASP.NET Core que se haya quitado del marco de trabajo compartido, agregue la referencia de paquete adecuada. Para obtener una lista de los paquetes que se han quitado del marco compartido en ASP.NET Core 3.1, consulte Quitar referencias de paquetes obsoletas.

Por ejemplo, para agregar el cliente de la API web:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
  </ItemGroup>

</Project>

Recursos adicionales