Utiliser les API ASP.NET Core dans une bibliothèque de classes

Par Scott Addie

Ce document fournit des conseils pour l’utilisation des API ASP.NET Core dans une bibliothèque de classes. Pour tous les autres conseils sur les bibliothèques, consultez le Guide sur les bibliothèques open source.

Déterminer les versions d’ASP.NET Core à prendre en charge

ASP.NET Core adhère à la politique de prise en charge de .NET Core. Consultez la politique de prise en charge pour déterminer les versions d’ASP.NET Core à prendre en charge dans une bibliothèque. Une bibliothèque doit :

  • Faire un effort pour prendre en charge toutes les versions ASP.NET Core classées Support à long terme (LTS).
  • Ne pas s’efforcer de prendre en charge les versions d’ASP.NET Core classées En fin de vie (EOL).

À mesure que les préversions de ASP.NET Core deviennent disponibles, des changements cassants sont publiés dans le dépôt GitHub aspnet/Announcements. Des tests de compatibilité des bibliothèques peuvent être effectués à mesure que des fonctionnalités de framework sont développées.

Utiliser le framework partagé ASP.NET Core

Avec la version .NET Core 3.0, de nombreux assemblys ASP.NET Core ne sont plus publiés sur NuGet en tant que packages. Au lieu de cela, les assemblys sont inclus dans le framework partagé Microsoft.AspNetCore.App, qui est installé avec le SDK .NET Core et les programmes d’installation du runtime. Pour obtenir la liste des packages qui ne sont plus publiés, consultez Supprimer les références de package obsolètes.

À partir de .NET Core 3.0, les projets utilisant le SDK MSBuild Microsoft.NET.Sdk.Web référencent implicitement le framework partagé. Les projets utilisant le SDK Microsoft.NET.Sdk ou Microsoft.NET.Sdk.Razor doivent référencer ASP.NET Core pour utiliser des API ASP.NET Core dans le framework partagé.

Pour référencer ASP.NET Core, ajoutez l’élément <FrameworkReference> suivant à votre fichier projet :

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

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

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

</Project>

Inclure l’extensibilité Blazor

Blazor prend en charge la création de composants Razor des bibliothèques de classes pour des applications côté serveur et côté client. Pour prendre en charge les composants Razor d’une bibliothèque de classes, la bibliothèque de classes doit utiliser le kit de développement logiciel (SDK) Microsoft.NET.Sdk.Razor.

Prendre en charge des applications côté serveur et côté client

Pour que des applications côté serveur et côté client à partir d’une seule bibliothèque prennent en charge la consommation des composants Razor, utilisez les instructions suivantes pour votre éditeur.

Utilisez le modèle de projet Bibliothèque de classes Razor.

Remarque

Ne cochez pas la case Prise en charge des pages et des vues. La sélection de la case à cocher génère une bibliothèque de classes qui prend uniquement en charge des applications côté serveur.

La bibliothèque générée à partir du modèle de projet :

  • Cible le framework .NET actuel en fonction du SDK installé.
  • Active les vérifications de compatibilité des navigateurs pour les dépendances de plateforme en incluant browser en tant que plateforme prise en charge avec l’élément MSBuild SupportedPlatform.
  • Ajoute une référence de package NuGet pour Microsoft.AspNetCore.Components.Web.

RazorClassLibrary-CSharp.csproj(source de référence)

Remarque

Les liens de documentation vers la source de référence .NET chargent généralement la branche par défaut du référentiel, qui représente le développement actuel pour la prochaine version de .NET. Pour sélectionner une balise pour une version spécifique, utilisez la liste déroulante Échanger les branches ou les balises. Pour plus d’informations, consultez Comment sélectionner une balise de version du code source ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Prendre en charge plusieurs versions du framework

Si la bibliothèque doit prendre en charge les fonctionnalités ajoutées à Blazor dans la version actuelle tout en prenant également en charge une ou plusieurs versions antérieures, utilisez le multi-ciblage sur la bibliothèque. Fournissez une liste séparée par des points-virgules des monikers de framework cible (TFM) dans la propriété MSBuild TargetFrameworks :

<TargetFrameworks>{TARGET FRAMEWORKS}</TargetFrameworks>

Dans l’exemple précédent, l’espace réservé {TARGET FRAMEWORKS} représente la liste des TFM séparés par des points-virgules. Par exemple, netcoreapp3.1;net5.0

Prise en charge uniquement de la consommation côté serveur

Les bibliothèques de classes sont rarement conçues pour prendre uniquement en charge des applications côté serveur. Si la bibliothèque de classes nécessite uniquement des fonctionnalités spécifiques côté serveur, comme un accès à CircuitHandler ouMicrosoft.AspNetCore.Components.Server.ProtectedBrowserStorage, ou utilise des fonctionnalités spécifiques à ASP.NET Core, comme un intergiciel, des contrôleurs MVC ou des pages Razor, utilisez l’une des approches suivantes :

  • Spécifiez que la bibliothèque prend en charge les pages et les vues lorsqu’elle est créée avec la case Prendre en charge les pages et les vues (Visual Studio) ou l’option -s|--support-pages-and-views avec la commande dotnet new :

    dotnet new razorclasslib -s
    
  • Fournissez uniquement une référence d’infrastructure à ASP.NET Core dans le fichier projet de la bibliothèque en plus des autres propriétés MS Build obligatoires :

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

Pour plus d’informations sur les bibliothèques contenant des composants Razor, consultez Consommer des composants ASP.NET Core Razor à partir d’une bibliothèque de classes Razor (RCL).

Inclure l’extensibilité MVC

Cette section décrit les recommandations pour les bibliothèques qui incluent :

Cette section ne traite pas du multi-ciblage pour prendre en charge plusieurs versions de MVC. Pour obtenir des conseils sur la prise en charge de plusieurs versions d’ASP.NET Core, consultez Prise en charge de plusieurs versions d’ASP.NET Core.

Vues Razor ou Razor Pages

Un projet qui inclut des vues Razor ou Razor Pages doit utiliser le SDK Microsoft.NET.Sdk.Razor

Si le projet cible .NET Core 3.x, il nécessite :

  • Une propriété MSBuild AddRazorSupportForMvc définie sur true.
  • Un élément <FrameworkReference> pour le framework partagé.

Le modèle de projet bibliothèque de classes Razor satisfait aux exigences précédentes pour les projets ciblant .NET Core. Utilisez les instructions suivantes pour votre éditeur.

Utilisez le modèle de projet Bibliothèque de classes Razor. La case Prendre en charge les pages et vues du modèle doit être cochée.

Par exemple :

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

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

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

</Project>

Si le projet cible .NET Standard à la place, une référence de package Microsoft.AspNetCore.Mvc est requise. Le package Microsoft.AspNetCore.Mvc a été déplacé dans le framework partagé dans ASP.NET Core 3.0 et n’est donc plus publié. Par exemple :

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

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

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

</Project>

Tag Helpers

Un projet qui inclut des Tag Helpers doit utiliser le SDK Microsoft.NET.Sdk. Si vous ciblez .NET Core 3.x, ajoutez un élément <FrameworkReference> pour le framework partagé. Par exemple :

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

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

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

</Project>

Si vous ciblez .NET Standard (pour prendre en charge les versions antérieures à ASP.NET Core 3.x), ajoutez une référence de package à Microsoft.AspNetCore.Mvc.Razor. Le package Microsoft.AspNetCore.Mvc.Razor a été déplacé dans le framework partagé et n’est donc plus publié. Par exemple :

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

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

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

</Project>

Composants de vue

Un projet qui inclut des composants de vue doit utiliser le SDK Microsoft.NET.Sdk. Si vous ciblez .NET Core 3.x, ajoutez un élément <FrameworkReference> pour le framework partagé. Par exemple :

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

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

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

</Project>

Si vous ciblez .NET Standard (pour prendre en charge des versions antérieures à ASP.NET Core 3.x), ajoutez une référence de package à Microsoft.AspNetCore.Mvc.ViewFeatures. Le package Microsoft.AspNetCore.Mvc.ViewFeatures a été déplacé dans le framework partagé et n’est donc plus publié. Par exemple :

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

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

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

</Project>

Prise en charge de plusieurs versions d’ASP.NET Core

Le multi-ciblage est nécessaire pour créer une bibliothèque qui prend en charge plusieurs variantes d’ASP.NET Core. Envisagez un scénario dans lequel une bibliothèque Tag Helpers doit prendre en charge les variantes ASP.NET Core suivantes :

  • ASP.NET Core 2.1 ciblant .NET Framework 4.6.1
  • ASP.NET Core 2.x ciblant .NET Core 2.x
  • ASP.NET Core 3.x ciblant .NET Core 3.x

Le fichier projet suivant prend en charge ces variantes via la propriété 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>

Avec le fichier projet précédent :

  • Le package Markdig est ajouté pour tous les consommateurs.
  • Une référence à Microsoft.AspNetCore.Mvc.Razor est ajoutée pour les consommateurs ciblant .NET Framework 4.6.1 ou version ultérieure ou .NET Core 2.x. La version 2.1.0 du package fonctionne avec ASP.NET Core 2.2 en raison de la compatibilité descendante.
  • Le framework partagé est référencé pour les consommateurs ciblant .NET Core 3.x. Le package Microsoft.AspNetCore.Mvc.Razor est inclus dans l’infrastructure partagée.

Vous pouvez également cibler .NET Standard 2.0 au lieu de cibler à la fois .NET Core 2.1 et .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>

Avec le fichier projet précédent, les mises en garde suivantes existent :

  • Étant donné que la bibliothèque contient uniquement des Tag Helpers, il est plus simple de cibler les plateformes spécifiques sur lesquelles ASP.NET Core s’exécute : .NET Core et .NET Framework. Les Tag Helpers ne peuvent pas être utilisés par d’autres frameworks cibles conformes à .NET Standard 2.0, comme Unity, UWP et Xamarin.
  • L’utilisation de .NET Standard 2.0 dans .NET Framework entraîne certains problèmes qui ont été résolus dans .NET Framework 4.7.2. Vous pouvez améliorer l’expérience des consommateurs utilisant .NET Framework 4.6.1 à 4.7.1 en ciblant .NET Framework 4.6.1.

Si votre bibliothèque doit appeler des API spécifiques à la plateforme, ciblez des implémentations .NET spécifiques au lieu de .NET Standard. Pour plus d’informations, consultez Multiciblage.

Utiliser une API qui n’a pas changé

Imaginez un scénario dans lequel vous mettez à niveau une bibliothèque d’intergiciels de .NET Core 2.2 vers la version 3.1. Les API d’intergiciel ASP.NET Core utilisées dans la bibliothèque n’ont pas changé entre ASP.NET Core 2.2 et 3.1. Pour continuer à prendre en charge la bibliothèque d’intergiciels dans .NET Core 3.1, procédez comme suit :

  • Suivez les instructions de bibliothèque standard.
  • Ajoutez une référence de package pour le package NuGet de chaque API si l’assembly correspondant n’existe pas dans le framework partagé.

Utiliser une API qui a changé

Imaginez un scénario dans lequel vous mettez à niveau une bibliothèque de .NET Core 2.2 vers .NET Core 3.1. Une API ASP.NET Core utilisée dans la bibliothèque présente un changement cassant dans ASP.NET Core 3.1. Déterminez si la bibliothèque peut être réécrite pour ne pas utiliser l’API rompue dans toutes les versions.

Si vous pouvez réécrire la bibliothèque, faites-le et continuez à cibler une infrastructure cible antérieure (par exemple, .NET Standard 2.0 ou .NET Framework 4.6.1) avec des références de package.

Si vous ne pouvez pas réécrire la bibliothèque, procédez comme suit :

  • Ajouter une cible pour .NET Core 3.1.
  • Ajoutez un élément <FrameworkReference> pour l’infrastructure partagée.
  • Utilisez la directive de préprocesseur #if avec le symbole de framework cible approprié pour compiler du code de manière conditionnelle.

Par exemple, les lectures et écritures synchrones sur les flux de requête et de réponse HTTP sont désactivées par défaut à partir d’ASP.NET Core 3.1. ASP.NET Core 2.2 prend en charge le comportement synchrone par défaut. Envisagez une bibliothèque d’intergiciels dans laquelle les lectures et les écritures synchrones doivent être activées là où les E/S se produisent. La bibliothèque doit contenir le code pour activer les fonctionnalités synchrones dans la directive de préprocesseur appropriée. Par exemple :

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

Utiliser une API introduite dans la version 3.1

Imaginez que vous souhaitez utiliser une API ASP.NET Core introduite dans ASP.NET Core 3.1. Posez-vous les questions suivantes :

  1. La bibliothèque nécessite-t-elle fonctionnellement la nouvelle API ?
  2. La bibliothèque peut-elle implémenter cette fonctionnalité d’une autre manière ?

Si la bibliothèque nécessite fonctionnellement l’API et qu’il n’existe aucun moyen de l’implémenter au niveau inférieur :

  • Ciblez .NET Core 3.x uniquement.
  • Ajoutez un élément <FrameworkReference> pour l’infrastructure partagée.

Si la bibliothèque peut implémenter la fonctionnalité d’une autre manière :

  • Ajoutez .NET Core 3.x en tant que framework cible.
  • Ajoutez un élément <FrameworkReference> pour l’infrastructure partagée.
  • Utilisez la directive de préprocesseur #if avec le symbole de framework cible approprié pour compiler du code de manière conditionnelle.

Par exemple, le Tag Helper suivant utilise l’interface IWebHostEnvironment introduite dans ASP.NET Core 3.1. Les consommateurs ciblant .NET Core 3.1 exécutent le chemin de code défini par le symbole du framework cible NETCOREAPP3_1. Le type de paramètre de constructeur du Tag Helper devient IHostingEnvironment pour les consommateurs .NET Core 2.1 et .NET Framework 4.6.1. Cette modification était nécessaire, car ASP.NET Core 3.1 a marqué IHostingEnvironment comme obsolète et recommandé IWebHostEnvironment comme remplacement.

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

Le fichier projet multi-ciblé suivant prend en charge ce scénario 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>

Utiliser une API supprimée du framework partagé

Pour utiliser un assembly ASP.NET Core qui a été supprimé du framework partagé, ajoutez la référence de package appropriée. Pour obtenir la liste des packages supprimés du framework partagé dans ASP.NET Core 3.1, consultez Supprimer les références de package obsolètes.

Par exemple, pour ajouter le client d’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>

Ressources supplémentaires