Compartilhar via


Usar APIs do ASP.NET Core em uma biblioteca de classes

Por Scott Addie

Este documento fornece diretrizes para o uso de APIs do ASP.NET Core em uma biblioteca de classes. Para obter todas as outras diretrizes da biblioteca, consulte diretrizes de biblioteca de software livre.

Determinar quais versões do ASP.NET Core dar suporte

O ASP.NET Core adere à política de suporte do .NET Core. Consulte a política de suporte ao determinar quais versões do ASP.NET Core dar suporte em uma biblioteca. Uma biblioteca deve:

  • Faça um esforço para dar suporte a todas as versões do ASP.NET Core classificadas como LTS (Long-Term Support).
  • Não se sentir obrigada a dar suporte a versões do ASP.NET Core classificadas como EOL (End of Life).

À medida que as versões prévias do ASP.NET Core são disponibilizadas, as alterações significativas são postadas no repositório GitHub aspnet/Announcements. O teste de compatibilidade de bibliotecas pode ser realizado à medida que os recursos da estrutura estão sendo desenvolvidos.

Usar a estrutura compartilhada do ASP.NET Core

Com o lançamento do .NET Core 3.0, muitos assemblies ASP.NET Core não são mais publicados no NuGet como pacotes. Os assemblies agora são incluídos na estrutura compartilhada Microsoft.AspNetCore.App, que é instalada com o SDK do .NET Core e instaladores de runtime. Para obter uma lista de pacotes que não estão mais sendo publicados, consulte Remover referências de pacote obsoletos.

A partir do .NET Core 3.0, projetos que usam o Microsoft.NET.Sdk.Web SDK do MSBuild referenciam implicitamente a estrutura compartilhada. Os projetos que usam o SDK de Microsoft.NET.Sdk ou Microsoft.NET.Sdk.Razor devem fazer referência ao ASP.NET Core para usar apIs ASP.NET Core na estrutura compartilhada.

Para fazer referência ao ASP.NET Core, adicione o seguinte elemento <FrameworkReference> ao arquivo de projeto:

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

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

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

</Project>

Incluir extensibilidade do Blazor

Blazor dá suporte à criação de bibliotecas de classes de componentes Razor para aplicativos do lado do servidor e do lado do cliente. Para dar suporte a componentes Razor em uma biblioteca de classes, a biblioteca de classes deve usar o Microsoft.NET.Sdk.Razor SDK.

Dar suporte a aplicativos do lado do servidor e do lado do cliente

Para dar suporte ao consumo de componentes Razor por aplicativos do lado do servidor e do lado do cliente a partir de uma única biblioteca, use as instruções a seguir no seu editor.

Use o modelo de projeto Razor Biblioteca de Classes.

Nota

Não marque a caixa de seleção Páginas de suporte e exibições. A seleção da caixa de seleção resulta em uma biblioteca de classes que dá suporte apenas a aplicativos do lado do servidor.

A biblioteca gerada a partir do modelo de projeto:

  • Direciona o .NET Framework atual com base no SDK instalado.
  • Habilita as verificações de compatibilidade do navegador em relação a dependências de plataforma, incluindo browser como plataforma com suporte com o item de MSBuild SupportedPlatform.
  • Adiciona uma referência de pacote NuGet para Microsoft.AspNetCore.Components.Web.

RazorClassLibrary-CSharp.csproj (fonte de referência)

Nota

Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para obter mais informações, consulte Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Suporte a várias versões de estrutura

Se a biblioteca precisar suportar recursos adicionados a Blazor na versão atual e, ao mesmo tempo, dar suporte a uma ou mais versões anteriores, configure a biblioteca para suportar múltiplos alvos. Forneça uma lista separada por ponto e vírgula de TFMs (Monikers da Estrutura de Destino) na propriedade MSBuild TargetFrameworks:

<TargetFrameworks>{TARGET FRAMEWORKS}</TargetFrameworks>

No exemplo anterior, o espaço reservado {TARGET FRAMEWORKS} representa a lista de TFMs separadas por ponto e vírgula. Por exemplo, netcoreapp3.1;net5.0.

Dá suporte apenas ao consumo do lado do servidor

As bibliotecas de classes raramente são criadas para dar suporte apenas a aplicativos do lado do servidor. Se a biblioteca de classes só exigir recursos específicos do servidor, como acesso a CircuitHandler ou Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage, ou o uso de recursos específicos do ASP.NET Core, como middleware, controladores MVC ou Razor Pages, use uma das seguintes abordagens:

  • Especifique que a biblioteca oferece suporte a páginas e exibições quando a biblioteca é criada com a caixa de seleção "Suporte a páginas e exibições" (Visual Studio) ou com a opção -s|--support-pages-and-views do comando dotnet new.

    dotnet new razorclasslib -s
    
  • Forneça apenas uma referência de estrutura ao ASP.NET Core no arquivo de projeto da biblioteca, além de outras propriedades necessárias do MSBuild:

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

Para obter mais informações sobre bibliotecas que contêm componentes Razor, confira Consumir componentes Razor do ASP.NET Core de uma biblioteca de classes Razor (RCL).

Incluir extensibilidade do MVC

Esta seção descreve as recomendações para bibliotecas que incluem:

Esta seção não discute vários direcionamentos para dar suporte a várias versões do MVC. Para obter diretrizes sobre como dar suporte a várias versões do ASP.NET Core, consulte Suporte a várias versões do ASP.NET Core.

Exibições Razor ou Razor Páginas

Um projeto que inclui exibições Razor ou Páginas Razor devem usar o SDK Microsoft.NET.Sdk.Razor.

Se o projeto for direcionado ao .NET Core 3.x, ele exigirá:

  • Uma propriedade MSBuild AddRazorSupportForMvc definida como true.
  • Um elemento <FrameworkReference> para a estrutura compartilhada.

O modelo de projeto Razor Biblioteca de Classes atende aos requisitos anteriores para projetos direcionados ao .NET Core. Use as instruções a seguir para o editor.

Use o modelo de projeto Razor Biblioteca de Classes. A caixa de seleção Páginas de suporte e exibições do modelo devem ser selecionadas.

Por exemplo:

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

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

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

</Project>

Se o projeto for direcionado ao .NET Standard em vez disso, uma referência de pacote Microsoft.AspNetCore.Mvc será necessária. O pacote Microsoft.AspNetCore.Mvc foi movido para o framework compartilhado no ASP.NET Core 3.0 e, portanto, não é mais publicado. Por exemplo:

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

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

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

</Project>

Auxiliares de Marcas

Um projeto que inclui Tag Helpers deve usar o SDK do Microsoft.NET.Sdk. Se estiver direcionando o .NET Core 3.x, adicione um elemento <FrameworkReference> para a estrutura compartilhada. Por exemplo:

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

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

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

</Project>

Se estiver visando o .NET Standard (para dar suporte a versões anteriores ao ASP.NET Core 3.x), adicione uma referência de pacote a Microsoft.AspNetCore.Mvc.Razor. O pacote Microsoft.AspNetCore.Mvc.Razor foi movido para a estrutura compartilhada e, portanto, não é mais publicado. Por exemplo:

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

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

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

</Project>

Exibir componentes

Um projeto que inclui componentes View deve usar o SDK Microsoft.NET.Sdk. Se estiver direcionando o .NET Core 3.x, adicione um elemento <FrameworkReference> para a estrutura compartilhada. Por exemplo:

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

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

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

</Project>

Se o objetivo for o .NET Standard (para dar suporte a versões anteriores ao ASP.NET Core 3.x), adicione uma referência de pacote a Microsoft.AspNetCore.Mvc.ViewFeatures. O pacote Microsoft.AspNetCore.Mvc.ViewFeatures foi movido para a estrutura compartilhada e, portanto, não é mais publicado. Por exemplo:

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

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

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

</Project>

Suporte a várias versões do ASP.NET Core

O direcionamento múltiplo é necessário para criar uma biblioteca que dê suporte a várias variantes do ASP.NET Core. Considere um cenário no qual uma biblioteca de Helpers de Tag deve dar suporte às seguintes variantes do ASP.NET Core:

  • ASP.NET Core 2.1 visando o .NET Framework 4.6.1
  • ASP.NET Core 2.x visando o .NET Core 2.x
  • ASP.NET Core 3.x visando o .NET Core 3.x

O arquivo de projeto a seguir dá suporte a essas variantes por meio da propriedade 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>

Com o arquivo de projeto anterior:

  • O pacote Markdig é adicionado para todos os consumidores.
  • Uma referência a Microsoft.AspNetCore.Mvc.Razor é adicionada para os destinatários que visam o .NET Framework 4.6.1 ou posterior ou o .NET Core 2.x. A versão 2.1.0 do pacote funciona com ASP.NET Core 2.2 devido à retrocompatibilidade.
  • A estrutura compartilhada é referenciada para consumidores que têm como objetivo o .NET Core 3.x. O pacote Microsoft.AspNetCore.Mvc.Razor está incluído na estrutura compartilhada.

Como alternativa, o .NET Standard 2.0 pode ser o alvo, ao invés de destinar-se tanto ao .NET Core 2.1 quanto ao .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>

Com o arquivo de projeto anterior, existem as seguintes ressalvas:

  • Como a biblioteca contém apenas Tag Helpers, é mais simples focar nas plataformas específicas nas quais o ASP.NET Core é executado: .NET Core e .NET Framework. Os Tag Helpers não podem ser usados por outras estruturas de destino compatíveis com o .NET Standard 2.0, como as frameworks Unity e UWP.
  • O uso do .NET Standard 2.0 do .NET Framework tem alguns problemas que foram resolvidos no .NET Framework 4.7.2. Você pode melhorar a experiência dos consumidores que usam o .NET Framework 4.6.1 até 4.7.1, focando no .NET Framework 4.6.1.

Se sua biblioteca precisar chamar APIs específicas da plataforma, direcione implementações específicas do .NET em vez do .NET Standard. Para obter mais informações, confira Multissegmentação.

Usar uma API que não foi alterada

Imagine um cenário no qual você está atualizando uma biblioteca de middleware do .NET Core 2.2 para a 3.1. As APIs de middleware do ASP.NET Core que estão sendo usadas na biblioteca não foram alteradas entre ASP.NET Core 2.2 e 3.1. Para continuar dando suporte à biblioteca de middleware no .NET Core 3.1, execute as seguintes etapas:

  • Siga as diretrizes de biblioteca padrão.
  • Adicione uma referência de pacote para o pacote NuGet de cada API se o assembly correspondente não existir na estrutura compartilhada.

Usar uma API que foi alterada

Imagine um cenário no qual você está atualizando uma biblioteca do .NET Core 2.2 para o .NET Core 3.1. Uma API do ASP.NET Core que está sendo usada na biblioteca tem uma alteração interruptiva no ASP.NET Core 3.1. Considere se a biblioteca pode ser reescrita para não usar a API interrompida em todas as versões.

Se você puder reescrever a biblioteca, faça isso e continue a direcionar uma estrutura de destino anterior (por exemplo, .NET Standard 2.0 ou .NET Framework 4.6.1) com referências de pacote.

Se você não conseguir reescrever a biblioteca, execute as seguintes etapas:

  • Adicione um destino para o .NET Core 3.1.
  • Adicione um elemento <FrameworkReference> para a estrutura compartilhada.
  • Use a diretiva de pré-processador #if com o símbolo de estrutura de destino apropriado para compilar condicionalmente o código.

Por exemplo, leituras e gravações síncronas em fluxos de solicitação e resposta HTTP são desabilitadas por padrão a partir do ASP.NET Core 3.1. ASP.NET Core 2.2 dá suporte ao comportamento síncrono por padrão. Considere uma biblioteca de middleware na qual as leituras e gravações síncronas devem ser habilitadas onde a E/S está ocorrendo. A biblioteca deve colocar o código para habilitar recursos síncronos na diretiva de pré-processador apropriada. Por exemplo:

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);
}

Usar uma API introduzida na 3.1

Imagine que você deseja usar uma API do ASP.NET Core que foi introduzida no ASP.NET Core 3.1. Considere as seguintes perguntas:

  1. A biblioteca requer funcionalmente a nova API?
  2. A biblioteca pode implementar esse recurso de uma maneira diferente?

Se a biblioteca exigir funcionalmente a API e não houver como implementá-la no nível inferior:

  • Tenha como objetivo somente o .NET Core 3.x.
  • Adicione um elemento <FrameworkReference> para a estrutura compartilhada.

Se a biblioteca puder implementar o recurso de uma maneira diferente:

  • Adicione o .NET Core 3.x como uma estrutura de destino.
  • Adicione um elemento <FrameworkReference> para a estrutura compartilhada.
  • Use a diretiva de pré-processador #if com o símbolo de estrutura de destino apropriado para compilar condicionalmente o código.

Por exemplo, o Tag Helper a seguir usa a interface IWebHostEnvironment introduzida no ASP.NET Core 3.1. Os consumidores que visam ao .NET Core 3.1 executam o caminho de código definido pelo símbolo da estrutura de destino NETCOREAPP3_1. O tipo do parâmetro do construtor do Tag Helper muda para IHostingEnvironment para consumidores do .NET Core 2.1 e .NET Framework 4.6.1. Essa alteração foi necessária porque o ASP.NET Core 3.1 marcou IHostingEnvironment como obsoleto e recomendado IWebHostEnvironment como a substituição.

[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
}

O seguinte arquivo de projeto multi-alvo dá suporte a este cenário de Tag Helper:

<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>

Usar uma API removida da estrutura compartilhada

Para usar um assembly ASP.NET Core que foi removido da estrutura compartilhada, adicione a referência de pacote apropriada. Para obter uma lista de pacotes removidos da estrutura compartilhada no ASP.NET Core 3.1, consulte Remover referências de pacote obsoletas.

Por exemplo, para adicionar o cliente da 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 adicionais