34 votes

Comment implémenter une API Web ASP.NET Core " pure " en utilisant AddMvcCore()

J'ai vu beaucoup de projets d'API Web ASP.NET Core qui utilisent la version par défaut de l'API Web. AddMvc() sans se rendre compte que l'utilisation AddMvcCore() est une option supérieure en raison du contrôle des services.

Comment implémenter exactement une API Web ASP.NET Core en utilisant AddMvcCore() y pourquoi est-ce mieux ?

83voto

Svek Points 6227

Quelle est la différence entre AddMvc() y AddMvcCore() ?

La première chose essentielle à comprendre est que AddMvc() est juste une version préchargée de AddMvcCore() . Vous pouvez voir l'implémentation exacte de la AddMvc() extension à la Dépôt GitHub .

J'aime utiliser les modèles VS par défaut comme tout le monde, mais il faut parfois savoir quand c'est le mauvais choix. J'ai vu plusieurs guides en ligne qui se penchent davantage sur une tentative de "défaire" ces services par défaut plutôt que d'opter pour une solution qui ne les implémente tout simplement pas en premier lieu.

Avec l'avènement d'ASP.NET Core en open source, il n'y a vraiment aucune raison pour laquelle nous ne pouvons pas retirer une couche et travailler à un niveau inférieur sans craindre de perdre la "magie".


Définition des termes "minimal" et "pur".

Note : Les définitions sont destinées au contexte de cette réponse uniquement. Elles le sont principalement pour des raisons de clarté et pour aider à mieux comprendre.

Cette réponse penche plutôt vers "pur" et non "minimal". J'aimerais expliquer pourquoi, afin que l'on comprenne mieux de quoi je parle.

Minimal. Une solution "minimale" serait une implémentation qui ne fait même pas appel au AddMvcCore() méthode du tout . La raison en est que MVC n'est pas vraiment un composant " obligatoire " pour assembler votre propre API Web, et qu'il alourdit certainement votre code avec les dépendances supplémentaires. Dans ce scénario, puisque vous n'utilisez pas le composant AddMvcCore() vous ne l'injecteriez pas non plus dans votre application, ici

public void Configure(IApplicationBuilder app)
{
    app.UseMvc(); // you don't need this
}

Cela signifie qu'il faut tracer ses propres itinéraires et réagir à la context à votre façon. Ce n'est pas du tout un défi, mais je ne veux pas m'y plonger, car c'est hors sujet. voici un petit aperçu d'une implémentation minimale :

public void Configure(IApplicationBuilder app)
{
    app.Map("/api", HandleMapApi);
    // notice how we don't have app.UseMvc()?
}    

private static void HandleMapApi(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        // implement your own response
        await context.Response.WriteAsync("Hello WebAPI!");
    });
}

Pour de nombreux projets, une approche "minimale" signifie que l'on renonce à certaines des fonctionnalités de MVC. Vous devez vraiment peser vos options et voir si cette voie de conception est le bon choix, car il y a un équilibre entre le modèle de conception, la commodité, la maintenabilité, l'empreinte du code et, surtout, les performances et la latence. En termes simples : une solution "minimale" consisterait à réduire au minimum les services et les intergiciels entre votre code et la demande.

Pure. Une solution "pure" (en ce qui concerne le contexte de cette réponse) consiste à éviter tous les services et intergiciels par défaut qui sont fournis "prêts à l'emploi" avec les systèmes de gestion de l'information. AddMvc() en ne l'appliquant pas en premier lieu. A la place, nous utilisons AddMvcCore() qui est expliqué plus en détail dans la section suivante :


Mise en œuvre de nos propres services / middleware avec AddMvcCore()

La première chose à faire pour commencer est de configurer ConfigureServices à l'utilisation AddMvcCore() . Si vous regardez le Dépôt GitHub vous pouvez voir que AddMvc() appelle AddMvcCore() avec un ensemble standard de services/logiciels intermédiaires :

Voici quelques-uns des services / intergiciels qui se distinguent par leur caractère "inutile" :

var builder = services.AddMvcCore();

builder.AddViews();
builder.AddRazorViewEngine();
builder.AddRazorPages();

Bon nombre de ces services par défaut sont parfaits pour un projet Web général, mais sont généralement indésirables pour une API Web "pure".

Voici un exemple de mise en œuvre de ConfigureServices en utilisant AddMvcCore() pour une API Web :

public void ConfigureServices(IServiceCollection services)
{
    // Build a customized MVC implementation, without using the default AddMvc(),
    // instead use AddMvcCore(). The repository link is below:
    // https://github.com/aspnet/Mvc/blob/release/2.2/src/Microsoft.AspNetCore.Mvc/MvcServiceCollectionExtensions.cs

    services
        .AddMvcCore(options =>
        {
            options.RequireHttpsPermanent = true; // this does not affect api requests
            options.RespectBrowserAcceptHeader = true; // false by default
            //options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();

            // these two are here to show you where to include custom formatters
            options.OutputFormatters.Add(new CustomOutputFormatter());
            options.InputFormatters.Add(new CustomInputFormatter());
        })
        //.AddApiExplorer()
        //.AddAuthorization()
        .AddFormatterMappings()
        //.AddCacheTagHelper()
        //.AddDataAnnotations()
        //.AddCors()
        .AddJsonFormatters();
}

L'implémentation ci-dessus est en grande partie une duplication de l'implémentation de l'option AddMvc() Cependant, j'ai ajouté quelques nouveaux domaines afin que d'autres puissent voir les avantages supplémentaires de cette méthode.

  • Formateurs d'entrée/sortie personnalisés. C'est là que vous pouvez utiliser vos propres sérialiseurs hautement optimisés (tels que Protobuf, Thrift, Avro, Etc) au lieu d'utiliser la sérialisation JSON (ou pire XML).
  • Traitement de l'en-tête de la demande. Vous pouvez vous assurer que le Accept est reconnu, ou non.
  • Traitement des autorisations. Vous pouvez mettre en œuvre votre propre autorisation personnalisée ou tirer parti des fonctions intégrées.
  • ApiExplorer. Pour certains projets, il est probable que vous l'incluiez, sinon certaines WebAPI peuvent ne pas vouloir de cette fonctionnalité.
  • Requêtes croisées (CORS). Si vous avez besoin d'une sécurité plus souple pour votre WebAPI, vous pouvez l'activer.

J'espère qu'avec cet exemple de solution "pure", vous pouvez voir les avantages de l'utilisation de la solution AddMvcCore() et être à l'aise avec son utilisation.

Si vous voulez vraiment contrôler les performances et la latence lorsque vous travaillez au-dessus de l'hôte Web d'ASP.NET Core, vous devriez peut-être vous plonger dans une solution "minimale", où vous vous occupez directement de la périphérie du pipeline de requête, plutôt que de le laisser s'enliser dans le middleware MVC.


Lectures complémentaires

Un regard visuel sur la façon dont le pipeline du middleware se présente... Selon mes définitions, moins de couches signifie "minimal", tandis que "pur" est juste une version propre de MVC.

enter image description here

Vous pouvez en savoir plus à ce sujet sur les documents Microsoft : Principes fondamentaux de l'intergiciel ASP.NET Core

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X