Usare ASP.NET API Core in una libreria di classi

Di Scott Addie

Questo documento fornisce indicazioni per l'uso delle API di base di ASP.NET in una libreria di classi. Per tutte le altre linee guida per le librerie, vedere Linee guida per la libreria open source.

Determinare quali versioni di ASP.NET Core supportare

ASP.NET Core rispetta i criteri di supporto di .NET Core. Consultare i criteri di supporto per determinare quali ASP.NET versioni core da supportare in una libreria. Una libreria deve:

  • Eseguire uno sforzo per supportare tutte le versioni di ASP.NET Core classificate come supporto a lungo termine (LTS).
  • Non sentirsi obbligati a supportare ASP.NET versioni Core classificate come End of Life (EOL).

Man mano che vengono rese disponibili le versioni di anteprima di ASP.NET Core, le modifiche di rilievo vengono pubblicate nel repository GitHub aspnet/Announcements . I test di compatibilità delle librerie possono essere eseguiti durante lo sviluppo di funzionalità del framework.

Usare il framework condiviso ASP.NET Core

Con il rilascio di .NET Core 3.0, molti assembly ASP.NET Core non vengono più pubblicati in NuGet come pacchetti. Gli assembly vengono invece inclusi nel Microsoft.AspNetCore.App framework condiviso, che viene installato con .NET Core SDK e i programmi di installazione di runtime. Per un elenco dei pacchetti non più pubblicati, vedere Rimuovere i riferimenti ai pacchetti obsoleti.

A partire da .NET Core 3.0, i progetti che usano Microsoft.NET.Sdk.Web MSBuild SDK fanno riferimento implicitamente al framework condiviso. I progetti che usano Microsoft.NET.Sdk o Microsoft.NET.Sdk.Razor SDK devono fare riferimento a ASP.NET Core per usare ASP.NET API Core nel framework condiviso.

Per fare riferimento a ASP.NET Core, aggiungere l'elemento seguente <FrameworkReference> al file di progetto:

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

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

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

</Project>

Includi Blazor estendibilità

Blazor supporta la creazione di Razor librerie di classi dei componenti per le app lato server e lato client. Per supportare Razor i componenti in una libreria di classi, la libreria di classi deve usare Microsoft.NET.Sdk.Razor SDK.

Supportare app lato server e lato client

Per supportare l'utilizzo Razor dei componenti da parte di app lato server e lato client da una singola libreria, usare le istruzioni seguenti per l'editor.

Usare il Razor modello di progetto Libreria di classi.

Nota

Non selezionare la casella di controllo Pagine e visualizzazioni di supporto. Se si seleziona la casella di controllo, viene restituita una libreria di classi che supporta solo le app lato server.

Libreria generata dal modello di progetto:

  • È destinato al framework .NET corrente basato sull'SDK installato.
  • Abilita i controlli di compatibilità del browser per verificare la presenza di dipendenze della piattaforma includendo browser come piattaforma supportata con l'elemento SupportedPlatform MSBuild.
  • Aggiunge un riferimento al pacchetto NuGet per Microsoft.AspNetCore.Components.Web.

RazorClassLibrary-CSharp.csproj (origine di riferimento)

Nota

I collegamenti della documentazione all'origine del riferimento .NET in genere caricano il ramo predefinito del repository, che rappresenta lo sviluppo corrente per la versione successiva di .NET. Per selezionare un tag per una versione specifica, usare l'elenco a discesa Switch branches or tags. Per altre informazioni, vedere How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Come selezionare un tag di versione del codice sorgente di ASP.NET - dotnet/AspNetCore.Docs #26205).

Supportare più versioni del framework

Se la libreria deve supportare le funzionalità aggiunte a Blazor nella versione corrente, supportando anche una o più versioni precedenti, la libreria con più entità di destinazione. Specificare un elenco delimitato da punto e virgola dei moniker del framework di destinazione nellaTargetFrameworks proprietà MSBuild:

<TargetFrameworks>{TARGET FRAMEWORKS}</TargetFrameworks>

Nell'esempio precedente il {TARGET FRAMEWORKS} segnaposto rappresenta l'elenco tfms delimitato da punto e virgola. Ad esempio: netcoreapp3.1;net5.0.

Supporta solo l'utilizzo lato server

Le librerie di classi vengono compilate raramente per supportare solo le app lato server. Se la libreria di classi richiede solo funzionalità specifiche del lato server, ad esempio l'accesso a CircuitHandler o Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage, o usa funzionalità specifiche di ASP.NET Core, ad esempio middleware, controller MVC o Razor Pages, usare uno degli approcci seguenti:

  • Specificare che la libreria supporta pagine e visualizzazioni quando la raccolta viene creata con la casella di controllo Pagine e visualizzazioni del supporto (Visual Studio) o l'opzione -s|--support-pages-and-views con il dotnet new comando :

    dotnet new razorclasslib -s
    
  • Fornire solo un riferimento al framework per ASP.NET Core nel file di progetto della libreria, oltre a qualsiasi altra proprietà MSBuild necessaria:

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

Per altre informazioni sulle librerie contenenti Razor componenti, vedere Utilizzare componenti di Razor base ASP.NET da una Razor libreria di classi (RCL).

Includi estendibilità MVC

Questa sezione illustra le raccomandazioni per le librerie che includono:

Questa sezione non illustra il multitargeting per supportare più versioni di MVC. Per indicazioni sul supporto di più versioni di ASP.NET Core, vedere Supportare più versioni di ASP.NET Core.

Razor visualizzazioni o Razor pagine

Un progetto che include Razor visualizzazioni oRazorpagine deve usare Microsoft.NET.Sdk.Razor SDK.

Se il progetto è destinato a .NET Core 3.x, è necessario:

  • Proprietà AddRazorSupportForMvc MSBuild impostata su true.
  • Elemento <FrameworkReference> per il framework condiviso.

Il Razor modello di progetto Libreria di classi soddisfa i requisiti precedenti per i progetti destinati a .NET Core. Usare le istruzioni seguenti per l'editor.

Usare il Razor modello di progetto Libreria di classi. È necessario selezionare la casella di controllo Support pages and views (Pagine e visualizzazioni di supporto) del modello.

Ad esempio:

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

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

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

</Project>

Se invece il progetto è destinato a .NET Standard, è necessario un riferimento al pacchetto Microsoft.AspNetCore.Mvc . Il Microsoft.AspNetCore.Mvc pacchetto è stato spostato nel framework condiviso in ASP.NET Core 3.0 e pertanto non viene più pubblicato. Ad esempio:

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

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

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

</Project>

Helper per i tag

Un progetto che include helper tag deve usare l'SDK Microsoft.NET.Sdk . Se la destinazione è .NET Core 3.x, aggiungere un <FrameworkReference> elemento per il framework condiviso. Ad esempio:

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

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

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

</Project>

Se la destinazione è .NET Standard (per supportare versioni precedenti a ASP.NET Core 3.x), aggiungere un riferimento al pacchetto a Microsoft.AspNetCore.Mvc.Razor Il Microsoft.AspNetCore.Mvc.Razor pacchetto è stato spostato nel framework condiviso e pertanto non viene più pubblicato. Ad esempio:

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

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

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

</Project>

Componenti di visualizzazione

Un progetto che include i componenti di visualizzazione deve usare l'SDK Microsoft.NET.Sdk . Se la destinazione è .NET Core 3.x, aggiungere un <FrameworkReference> elemento per il framework condiviso. Ad esempio:

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

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

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

</Project>

Se la destinazione è .NET Standard (per supportare versioni precedenti a ASP.NET Core 3.x), aggiungere un riferimento al pacchetto a Microsoft.AspNetCore.Mvc.ViewFeatures. Il Microsoft.AspNetCore.Mvc.ViewFeatures pacchetto è stato spostato nel framework condiviso e pertanto non viene più pubblicato. Ad esempio:

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

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

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

</Project>

Supportare più versioni di ASP.NET Core

Per creare una libreria che supporta più varianti di ASP.NET Core, è necessario il multitargeting. Si consideri uno scenario in cui una libreria helper tag deve supportare le varianti principali di ASP.NET seguenti:

  • ASP.NET Core 2.1 destinato a .NET Framework 4.6.1
  • ASP.NET Core 2.x destinato a .NET Core 2.x
  • ASP.NET Core 3.x destinato a .NET Core 3.x

Il file di progetto seguente supporta queste varianti tramite la TargetFrameworks proprietà :

<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 il file di progetto precedente:

  • Il Markdig pacchetto viene aggiunto per tutti i consumer.
  • Viene aggiunto un riferimento a Microsoft.AspNetCore.Mvc perRazor i consumer destinati a .NET Framework 4.6.1 o versioni successive o .NET Core 2.x. La versione 2.1.0 del pacchetto funziona con ASP.NET Core 2.2 a causa della compatibilità con le versioni precedenti.
  • Viene fatto riferimento al framework condiviso per i consumer destinati a .NET Core 3.x. Il Microsoft.AspNetCore.Mvc.Razor pacchetto è incluso nel framework condiviso.

In alternativa, .NET Standard 2.0 potrebbe essere destinato a .NET Core 2.1 e .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 il file di progetto precedente, esistono le avvertenze seguenti:

  • Poiché la libreria contiene solo helper tag, è più semplice definire come destinazione le piattaforme specifiche in cui ASP.NET Core viene eseguito: .NET Core e .NET Framework. Gli helper tag non possono essere usati da altri framework di destinazione conformi a .NET Standard 2.0, ad esempio Unity, UWP e Xamarin.
  • L'uso di .NET Standard 2.0 da .NET Framework presenta alcuni problemi che sono stati risolti in .NET Framework 4.7.2. È possibile migliorare l'esperienza per gli utenti che usano .NET Framework 4.6.1 e 4.7.1 usando .NET Framework 4.6.1.

Se la libreria deve chiamare API specifiche della piattaforma, specificare come destinazione implementazioni .NET invece di .NET Standard. Per altre informazioni, vedere Multi-targeting.

Usare un'API che non è stata modificata

Si immagini uno scenario in cui si sta aggiornando una libreria middleware da .NET Core 2.2 a 3.1. Le API middleware di ASP.NET Core usate nella libreria non sono cambiate tra ASP.NET Core 2.2 e 3.1. Per continuare a supportare la libreria middleware in .NET Core 3.1, seguire questa procedura:

  • Seguire le indicazioni della libreria standard.
  • Aggiungere un riferimento al pacchetto Per ogni API NuGet se l'assembly corrispondente non esiste nel framework condiviso.

Usare un'API modificata

Si immagini uno scenario in cui si sta aggiornando una libreria da .NET Core 2.2 a .NET Core 3.1. Un'API core ASP.NET usata nella libreria presenta una modifica di rilievo in ASP.NET Core 3.1. Valutare se la libreria può essere riscritta per non usare l'API interrotta in tutte le versioni.

Se è possibile riscrivere la libreria, eseguire questa operazione e continuare a usare un framework di destinazione precedente ,ad esempio .NET Standard 2.0 o .NET Framework 4.6.1 con riferimenti al pacchetto.

Se non è possibile riscrivere la libreria, seguire questa procedura:

  • Aggiungere una destinazione per .NET Core 3.1.
  • Aggiungere un <FrameworkReference> elemento per il framework condiviso.
  • Usare la direttiva del preprocessore #if con il simbolo del framework di destinazione appropriato per compilare il codice in modo condizionale.

Ad esempio, le letture e le scritture sincrone nei flussi di richiesta e risposta HTTP sono disabilitate per impostazione predefinita a partire da ASP.NET Core 3.1. ASP.NET Core 2.2 supporta il comportamento sincrono per impostazione predefinita. Si consideri una libreria middleware in cui le letture e le scritture sincrone devono essere abilitate in caso di I/O. La libreria deve racchiudere il codice per abilitare le funzionalità sincrone nella direttiva del preprocessore appropriata. Ad esempio:

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

Usare un'API introdotta nella versione 3.1

Si supponga di voler usare un'API ASP.NET Core introdotta in ASP.NET Core 3.1. Prendere in considerazione le domande seguenti:

  1. La libreria richiede funzionalmente la nuova API?
  2. La libreria può implementare questa funzionalità in modo diverso?

Se la libreria richiede funzionalmente l'API e non è possibile implementarla di livello inferiore:

  • Solo .NET Core 3.x di destinazione.
  • Aggiungere un <FrameworkReference> elemento per il framework condiviso.

Se la libreria può implementare la funzionalità in modo diverso:

  • Aggiungere .NET Core 3.x come framework di destinazione.
  • Aggiungere un <FrameworkReference> elemento per il framework condiviso.
  • Usare la direttiva del preprocessore #if con il simbolo del framework di destinazione appropriato per compilare il codice in modo condizionale.

Ad esempio, l'helper tag seguente usa l'interfaccia IWebHostEnvironment introdotta in ASP.NET Core 3.1. I consumer destinati a .NET Core 3.1 eseguono il percorso del codice definito dal simbolo del NETCOREAPP3_1 framework di destinazione. Il tipo di parametro del costruttore dell'helper tag cambia in IHostingEnvironment per i consumer .NET Core 2.1 e .NET Framework 4.6.1. Questa modifica è stata necessaria perché ASP.NET Core 3.1 contrassegnato IHostingEnvironment come obsoleto e consigliato IWebHostEnvironment come sostituzione.

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

Il file di progetto multi-destinazione seguente supporta questo scenario helper tag:

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

Usare un'API rimossa dal framework condiviso

Per usare un assembly ASP.NET Core rimosso dal framework condiviso, aggiungere il riferimento al pacchetto appropriato. Per un elenco dei pacchetti rimossi dal framework condiviso in ASP.NET Core 3.1, vedere Rimuovere i riferimenti ai pacchetti obsoleti.

Ad esempio, per aggiungere il client 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>

Risorse aggiuntive