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 biblioteca, consulte guía de la biblioteca de código abierto.
Determinar qué versiones de ASP.NET Core admitir
ASP.NET Core se adhiere a la directiva de compatibilidad de .NET Core . Consulte la directiva de soporte técnico al determinar qué versiones de ASP.NET Core admitir en una biblioteca. Una biblioteca debe:
- Realice un esfuerzo por admitir todas las versiones de ASP.NET Core clasificadas como Long-Term Support (LTS).
- No sentirse obligada a admitir versiones de ASP.NET Core clasificadas como final del ciclo de vida (EOL).
A medida que las versiones preliminares de ASP.NET Core están disponibles, los cambios importantes se publican en el repositorio de GitHub aspnet/Announcements. 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 ASP.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, consulte Quitar referencias de paquete 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 de 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 de Razor en una biblioteca de clases, la biblioteca de clases debe usar el Microsoft.NET.Sdk.Razor SDK.
Compatibilidad con aplicaciones del lado servidor y del lado cliente
Para admitir el consumo de componentes Razor por aplicaciones del lado del servidor y del lado del cliente desde una sola biblioteca, siga estas instrucciones en su 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 produce 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 elementoSupportedPlatform
de MSBuild. - Agrega una referencia de paquete NuGet para Microsoft.AspNetCore.Components.Web.
RazorClassLibrary-CSharp.csproj
(origen de referencia)
Nota
Los vínculos de documentación al origen de referencia de .NET normalmente cargan 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 Cómo seleccionar una etiqueta de versión del 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 y también debe admitir una o más versiones anteriores, entonces configure la biblioteca para varios destinos. 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 la biblioteca con la casilla Páginas y vistas de soporte técnico (Visual Studio) o la opción
-s|--support-pages-and-views
con el comandodotnet new
:dotnet new razorclasslib -s
Proporcione solo una referencia de marco a ASP.NET Core en el archivo de proyecto de la biblioteca, además de cualquier otra propiedad de MSBuild necesaria:
<ItemGroup> <FrameworkReference Include="Microsoft.AspNetCore.App" /> </ItemGroup>
Para obtener más información sobre las bibliotecas que contienen componentes de Razor, consulte Consumir componentes de ASP.NET Core Razor desde una biblioteca de clases Razor (RCL).
Incluir extensibilidad de MVC
En esta sección se describen las recomendaciones para las bibliotecas que incluyen:
- Vistas de Razor o páginas de Razor
- Aplicaciones auxiliares de etiquetas
- Visualización de componentes
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 páginas de Razor
Un proyecto que incluya vistas de Razor o páginas de Razor debe usar el SDK de Microsoft.NET.Sdk.Razor
Si el proyecto tiene como destino .NET Core 3.x, requiere lo siguiente:
- Una propiedad de MSBuild
AddRazorSupportForMvc
establecida entrue
. - Elemento
<FrameworkReference>
para el marco compartido.
La plantilla de proyecto Biblioteca de Clases Razor cumple los requisitos anteriores para los proyectos destinados a .NET Core. Utilice las siguientes instrucciones 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 en su lugar, se requiere una referencia de paquete de Microsoft.AspNetCore.Mvc. El paquete Microsoft.AspNetCore.Mvc
se movió 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 incluya asistentes de etiquetas debe usar 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.Razor. El paquete Microsoft.AspNetCore.Mvc.Razor
se movió 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>
Ver componentes
Un proyecto que incluya componentes de View 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.ViewFeatures. El paquete Microsoft.AspNetCore.Mvc.ViewFeatures
se movió 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. Considere un escenario en el que una biblioteca auxiliar de etiquetas debe admitir las siguientes variantes de ASP.NET Core:
- ASP.NET Core 2.1 destinado a .NET Framework 4.6.1
- 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
Markdig
se ha añadido para 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 debido 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
Microsoft.AspNetCore.Mvc.Razor
se incluye en el marco compartido.
Alternativamente, se podría usar .NET Standard 2.0 en lugar de apuntar a ambos, .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, existen las advertencias siguientes:
- Dado que la biblioteca solo contiene asistentes de etiquetas, es más sencillo tener como destino las plataformas específicas en las que se ejecuta ASP.NET Core: .NET Core y .NET Framework. Otros marcos de destino compatibles con .NET Standard 2.0, como Unity y UWP, no pueden usar asistentes de etiquetas.
- El uso de .NET Standard 2.0 desde .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, tenga como destino implementaciones específicas de .NET 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 va a actualizar una biblioteca de middleware de .NET Core 2.2 a 3.1. Las API de middleware de ASP.NET Core que se usan en la biblioteca no han cambiado entre ASP.NET Core 2.2 y 3.1. Para seguir admitiendo la biblioteca de middleware en .NET Core 3.1, siga estos pasos:
- Siga la guía de la biblioteca estándar .
- Agregue una referencia de paquete para el paquete NuGet de cada API si el ensamblado correspondiente no existe en el marco compartido.
Uso de una API que ha cambiado
Imagine un escenario en el que va a actualizar 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 no usar la API rota en todas las versiones.
Si puede volver a escribir la biblioteca, hágalo y siga teniendo como destino una plataforma de destino anterior (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 #if con el símbolo de marco de destino adecuado para compilar código condicionalmente.
Por ejemplo, las lecturas y escrituras sincrónicas en secuencias de solicitud y respuesta 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 cuando se está llevando a cabo 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 introducida en la versión 3.1
Imagine que desea usar una API de ASP.NET Core que se introdujo en ASP.NET Core 3.1. Tenga en cuenta las siguientes preguntas:
- ¿La biblioteca requiere funcionalmente la nueva API?
- ¿La biblioteca puede implementar esta característica de otra manera?
Si la biblioteca requiere funcionalmente la API y no hay ninguna manera de implementarla de nivel inferior:
- Diríjase solo a .NET Core 3.x.
- Agregue un elemento
<FrameworkReference>
para el marco compartido.
Si la biblioteca puede implementar la característica de una manera diferente:
- Agregue .NET Core 3.x como marco de destino.
- Agregue un elemento
<FrameworkReference>
para el marco compartido. - Use la directiva de preprocesador #if con el símbolo de marco de destino adecuado para compilar código condicionalmente.
Por ejemplo, el siguiente asistente de etiquetas usa la interfaz de IWebHostEnvironment introducida 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 del constructor del asistente de etiquetas cambia a IHostingEnvironment para los consumidores de .NET Core 2.1 y .NET Framework 4.6.1. Este cambio fue necesario porque ASP.NET Core 3.1 marcó IHostingEnvironment
como obsoleto y recomendado IWebHostEnvironment
como reemplazo.
[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 quitada del marco compartido
Para usar un ensamblado ASP.NET Core que se quitó del marco compartido, agregue la referencia de paquete adecuada. Para obtener una lista de paquetes quitados del marco compartido en ASP.NET Core 3.1, consulte Quitar referencias de paquetes obsoletas.
Por ejemplo, para agregar el cliente de 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>