Partager via


Créer une API web avec ASP.NET Core et MongoDB

Remarque

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 9 de cet article.

Avertissement

Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la stratégie de support .NET et .NET Core. Pour la version actuelle, consultez la version .NET 9 de cet article.

Important

Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.

Pour la version actuelle, consultez la version .NET 9 de cet article.

Par Pratik Khandelwal et Scott Addie

Ce tutoriel crée une API web qui exécute des opérations de création, lecture, mise à jour et suppression (CRUD) sur une base de données NoSQL MongoDB.

Dans ce tutoriel, vous allez apprendre à :

  • Configurer MongoDB
  • Créer une base de données MongoDB
  • Définir une collection et un schéma MongoDB
  • Effectuer des opérations CRUD MongoDB à partir d’une API web
  • Personnaliser la sérialisation JSON

Prérequis

Configurer MongoDB

Activez l’accès à MongoDB et MongoDB Shell depuis n’importe où sur la machine de développement (Windows/Linux/macOS) :

  1. Téléchargez et installez MongoDB Shell :

    • macOS/Linux : choisissez un répertoire où extraire MongoDB Shell. Ajoutez le chemin d’accès obtenu pour mongosh à la variable d’environnement PATH.
    • Windows : MongoDB Shell (mongosh.exe) est installé dans C:\Users<utilisateur>\AppData\Local\Programs\mongosh. Ajoutez le chemin d’accès obtenu pour mongosh.exe à la variable d’environnement PATH.
  2. Téléchargez et installez MongoDB :

    • macOS/Linux : vérifiez le répertoire où MongoDB a été installé, généralement dans /usr/local/mongodb. Ajoutez le chemin d’accès obtenu pour mongodb à la variable d’environnement PATH.
    • Windows : MongoDB est installé par défaut dans C:\Program Files\MongoDB. Ajoutez C:\Program Files\MongoDB\Server<numéro_version>\bin à la variable d’environnement PATH.
  3. Choisir un répertoire de stockage des données : sélectionnez un répertoire sur votre machine de développement pour stocker les données. Le cas échéant, créez le répertoire. MongoDB Shell ne crée pas nouveaux répertoires :

    • macOS/Linux : par exemple, /usr/local/var/mongodb.
    • Windows : par exemple, C:\\BooksData.
  4. Dans l’interpréteur de commandes du système d’exploitation (et non l’interpréteur de commandes MongoDB), utilisez la commande suivante pour vous connecter à MongoDB sur le port par défaut 27017. Remplacez <data_directory_path> par le répertoire choisi à l’étape précédente.

    mongod --dbpath <data_directory_path>
    

Utilisez l’interpréteur de commandes MongoDB précédemment installé dans les étapes suivantes pour créer une base de données, des collections, et stocker des documents. Pour plus d’informations sur les commandes MongoDB Shell, consultez mongosh.

  1. Ouvrez une instance de l’interpréteur de commandes MongoDB en lançant mongosh.exe.

  2. Dans l’interpréteur de commandes, connectez-vous à la base de données de test par défaut en exécutant la commande suivante :

    mongosh
    
  3. Exécutez la commande suivante dans le shell de commandes :

    use BookStore
    

    Une base de données nommée BookStore est créée si elle n’existe pas déjà. Si la base de données existe déjà, sa connexion est ouverte pour les transactions.

  4. Créez une collection Books à l’aide de la commande suivante :

    db.createCollection('Books')
    

    Le résultat suivant s’affiche :

    { "ok" : 1 }
    
  5. Définissez un schéma pour la collection Books et insérez deux documents à l’aide de la commande suivante :

    db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
    

    Un résultat similaire à ce qui suit s’affiche :

    {
        "acknowledged" : true,
        "insertedIds" : [
            ObjectId("61a6058e6c43f32854e51f51"),
            ObjectId("61a6058e6c43f32854e51f52")
         ]
     }
    

    Remarque

    Les ObjectId affichés dans le résultat précédent ne correspondent pas à ceux affichés dans l’interpréteur de commandes.

  6. Affichez les documents de la base de données à l’aide de la commande suivante :

    db.Books.find().pretty()
    

    Un résultat similaire à ce qui suit s’affiche :

    {
         "_id" : ObjectId("61a6058e6c43f32854e51f51"),
         "Name" : "Design Patterns",
         "Price" : 54.93,
         "Category" : "Computers",
         "Author" : "Ralph Johnson"
     }
     {
         "_id" : ObjectId("61a6058e6c43f32854e51f52"),
         "Name" : "Clean Code",
         "Price" : 43.15,
         "Category" : "Computers",
         "Author" : "Robert C. Martin"
     }
    

    Le schéma ajoute une propriété _id automatiquement générée de type ObjectId pour chaque document.

Créer le projet d’API web ASP.NET Core

  1. Accédez à Fichier>Nouveau>Projet.

  2. Sélectionnez le type de projet API web ASP.NET Core, puis Suivant.

  3. Nommez le projet BookStoreApi, puis sélectionnez Suivant.

  4. Sélectionnez le framework .NET 8.0 (prise en charge à long terme), puis Créer.

  5. Dans la fenêtre Console du Gestionnaire de Package, accédez à la racine du projet. Exécutez la commande suivante afin d’installer le pilote .NET pour MongoDB :

    Install-Package MongoDB.Driver
    

Ajouter un modèle d’entité

  1. Ajoutez un répertoire Models à la racine du projet.

  2. Ajoutez une classe Book au répertoire Models avec le code suivant :

    using MongoDB.Bson;
    using MongoDB.Bson.Serialization.Attributes;
    
    namespace BookStoreApi.Models;
    
    public class Book
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string? Id { get; set; }
    
        [BsonElement("Name")]
        public string BookName { get; set; } = null!;
    
        public decimal Price { get; set; }
    
        public string Category { get; set; } = null!;
    
        public string Author { get; set; } = null!;
    }
    

    Dans la classe précédente, la propriété Id est :

    • Requise pour mapper l’objet Common Language Runtime (CLR) à la collection MongoDB.
    • Annotée avec [BsonId] pour faire de cette propriété la clé primaire du document.
    • Annotée avec [BsonRepresentation(BsonType.ObjectId)] pour autoriser le passage du paramètre en tant que type string au lieu d’une structure ObjectId. Mongo gère la conversion de string en ObjectId.

    La propriété BookName est annotée avec l’attribut [BsonElement]. La valeur de l’attribut de Name représente le nom de propriété dans la collection MongoDB.

Ajouter un modèle de configuration

  1. Ajoutez les valeurs de configuration de base de données suivantes à appsettings.json :

    {
        "BookStoreDatabase": {
            "ConnectionString": "mongodb://localhost:27017",
            "DatabaseName": "BookStore",
            "BooksCollectionName": "Books"
        },
        "Logging": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft.AspNetCore": "Warning"
            }
        },
        "AllowedHosts": "*"
    }
    
  2. Ajoutez une classe BookStoreDatabaseSettings au répertoire Models avec le code suivant :

    namespace BookStoreApi.Models;
    
    public class BookStoreDatabaseSettings
    {
        public string ConnectionString { get; set; } = null!;
    
        public string DatabaseName { get; set; } = null!;
    
        public string BooksCollectionName { get; set; } = null!;
    }
    

    La classe BookStoreDatabaseSettings précédente est utilisée pour stocker les valeurs de propriété BookStoreDatabase du fichier appsettings.json. Les noms de propriétés JSON et C# sont nommés de manière identique pour faciliter le processus de mappage.

  3. Ajoutez le code en surbrillance suivant à Program.cs :

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.Configure<BookStoreDatabaseSettings>(
        builder.Configuration.GetSection("BookStoreDatabase"));
    

    Dans le code précédent, l’instance de configuration à laquelle la section BookStoreDatabase du fichier appsettings.json est liée est inscrite dans le conteneur d’injection de dépendances. Par exemple, la propriété ConnectionString de l’objet BookStoreDatabaseSettings est peuplée avec la propriété BookStoreDatabase:ConnectionString dans appsettings.json.

  4. Ajoutez le code suivant en haut de Program.cs pour résoudre la référence à BookStoreDatabaseSettings :

    using BookStoreApi.Models;
    

Ajouter un service d’opérations CRUD

  1. Ajoutez un répertoire Services à la racine du projet.

  2. Ajoutez une classe BooksService au répertoire Services avec le code suivant :

    using BookStoreApi.Models;
    using Microsoft.Extensions.Options;
    using MongoDB.Driver;
    
    namespace BookStoreApi.Services;
    
    public class BooksService
    {
        private readonly IMongoCollection<Book> _booksCollection;
    
        public BooksService(
            IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings)
        {
            var mongoClient = new MongoClient(
                bookStoreDatabaseSettings.Value.ConnectionString);
    
            var mongoDatabase = mongoClient.GetDatabase(
                bookStoreDatabaseSettings.Value.DatabaseName);
    
            _booksCollection = mongoDatabase.GetCollection<Book>(
                bookStoreDatabaseSettings.Value.BooksCollectionName);
        }
    
        public async Task<List<Book>> GetAsync() =>
            await _booksCollection.Find(_ => true).ToListAsync();
    
        public async Task<Book?> GetAsync(string id) =>
            await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync();
    
        public async Task CreateAsync(Book newBook) =>
            await _booksCollection.InsertOneAsync(newBook);
    
        public async Task UpdateAsync(string id, Book updatedBook) =>
            await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook);
    
        public async Task RemoveAsync(string id) =>
            await _booksCollection.DeleteOneAsync(x => x.Id == id);
    }
    

    Dans le code précédent, une instance de BookStoreDatabaseSettings est récupérée à partir de l’injection de dépendances via l’injection de constructeur. Cette technique permet d’accéder aux valeurs de configuration d’appsettings.json, qui ont été ajoutées à la section Ajouter un modèle de configuration.

  3. Ajoutez le code en surbrillance suivant à Program.cs :

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.Configure<BookStoreDatabaseSettings>(
        builder.Configuration.GetSection("BookStoreDatabase"));
    
    builder.Services.AddSingleton<BooksService>();
    

    Dans le code précédent, la classe BooksService est inscrite auprès de l’injection de dépendances pour permettre la prise en charge de l’injection de constructeur dans les classes consommatrices. La durée de vie de service de singleton est la plus appropriée, car BooksService a une dépendance directe sur MongoClient. Selon les recommandations officielles de réutilisation de Mongo Client, MongoClient doit être inscrit auprès de l’injection de dépendances avec une durée de vie de service de singleton.

  4. Ajoutez le code suivant en haut de Program.cs pour résoudre la référence à BooksService :

    using BookStoreApi.Services;
    

La classe BooksService utilise les membres MongoDB.Driver suivants pour exécuter des opérations CRUD dans la base de données :

  • MongoClient : Lit l’instance de serveur qui permet d’exécuter des opérations de base de données. Le constructeur de cette classe est fourni dans la chaîne de connexion MongoDB :

    public BooksService(
        IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings)
    {
        var mongoClient = new MongoClient(
            bookStoreDatabaseSettings.Value.ConnectionString);
    
        var mongoDatabase = mongoClient.GetDatabase(
            bookStoreDatabaseSettings.Value.DatabaseName);
    
        _booksCollection = mongoDatabase.GetCollection<Book>(
            bookStoreDatabaseSettings.Value.BooksCollectionName);
    }
    
  • IMongoDatabase : Représente la base de données Mongo qui permet d’exécuter des opérations. Ce tutoriel utilise la méthode générique GetCollection<TDocument>(collection) sur l’interface pour accéder aux données d’une collection spécifique. Exécutez des opérations CRUD sur la collection, après l’appel de cette méthode. Dans l’appel à la méthode GetCollection<TDocument>(collection) :

    • collection représente le nom de la collection.
    • TDocument représente le type d’objet CLR stocké dans la collection.

GetCollection<TDocument>(collection) retourne un objet MongoCollection représentant la collection. Dans ce didacticiel, les méthodes suivantes sont appelées sur la collection :

  • DeleteOneAsync : Supprime un seul document correspondant aux critères de recherche fournis.
  • Find<TDocument> : Retourne tous les documents de la collection correspondant aux critères de recherche fournis.
  • InsertOneAsync : Insère l’objet fourni en tant que nouveau document dans la collection.
  • ReplaceOneAsync : Remplace le seul document correspondant aux critères de recherche fournis par l’objet indiqué.

Ajout d'un contrôleur

Ajoutez une classe BooksController au répertoire Contrôleurs avec le code suivant :

using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;

namespace BookStoreApi.Controllers;

[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
    private readonly BooksService _booksService;

    public BooksController(BooksService booksService) =>
        _booksService = booksService;

    [HttpGet]
    public async Task<List<Book>> Get() =>
        await _booksService.GetAsync();

    [HttpGet("{id:length(24)}")]
    public async Task<ActionResult<Book>> Get(string id)
    {
        var book = await _booksService.GetAsync(id);

        if (book is null)
        {
            return NotFound();
        }

        return book;
    }

    [HttpPost]
    public async Task<IActionResult> Post(Book newBook)
    {
        await _booksService.CreateAsync(newBook);

        return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
    }

    [HttpPut("{id:length(24)}")]
    public async Task<IActionResult> Update(string id, Book updatedBook)
    {
        var book = await _booksService.GetAsync(id);

        if (book is null)
        {
            return NotFound();
        }

        updatedBook.Id = book.Id;

        await _booksService.UpdateAsync(id, updatedBook);

        return NoContent();
    }

    [HttpDelete("{id:length(24)}")]
    public async Task<IActionResult> Delete(string id)
    {
        var book = await _booksService.GetAsync(id);

        if (book is null)
        {
            return NotFound();
        }

        await _booksService.RemoveAsync(id);

        return NoContent();
    }
}

Le contrôleur d’API web précédent :

  • Utilise la classe BooksService pour exécuter des opérations CRUD.
  • Contient des méthodes d’action pour prendre en charge les requêtes HTTP GET, POST, PUT et DELETE.
  • Appelle CreatedAtAction dans la méthode d’action Create pour retourner une réponse HTTP 201. Le code d’état 201 est la réponse standard d’une méthode HTTP POST qui crée une ressource sur le serveur. CreatedAtAction ajoute également un en-tête Location à la réponse. L’en-tête Location spécifie l’URI du livre qui vient d’être créé.

Tester l’API web

  1. Générez et exécutez l'application.

  2. Accédez à https://localhost:<port>/api/books, où <port> est le numéro de port attribué automatiquement pour l’application, pour tester la méthode d’action Get sans paramètre du contrôleur, sélectionnez Essayer>Exécuter. Une réponse JSON similaire à la suivante s’affiche :

    [
      {
        "id": "61a6058e6c43f32854e51f51",
        "bookName": "Design Patterns",
        "price": 54.93,
        "category": "Computers",
        "author": "Ralph Johnson"
      },
      {
        "id": "61a6058e6c43f32854e51f52",
        "bookName": "Clean Code",
        "price": 43.15,
        "category": "Computers",
        "author": "Robert C. Martin"
      }
    ]
    
  3. Accédez à https://localhost:<port>/api/books/{id here} pour tester la méthode d’action Get surchargée du contrôleur. Une réponse JSON similaire à la suivante s’affiche :

    {
      "id": "61a6058e6c43f32854e51f52",
      "bookName": "Clean Code",
      "price": 43.15,
      "category": "Computers",
      "author": "Robert C. Martin"
    }
    

Configurer les options de sérialisation JSON

Vous devez changer deux détails concernant les réponses JSON retournées dans la section Tester l’API web :

  • Vous devez changer la casse mixte par défaut des noms de propriétés pour qu’elle corresponde à la casse Pascal des noms de propriétés de l’objet CLR.
  • La propriété bookName doit être retournée sous la forme Name.

Pour satisfaire les exigences précédentes, apportez les changements suivants :

  1. Dans Program.cs, ajoutez le code en surbrillance suivant à l’appel de méthode AddControllers :

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.Configure<BookStoreDatabaseSettings>(
        builder.Configuration.GetSection("BookStoreDatabase"));
    
    builder.Services.AddSingleton<BooksService>();
    
    builder.Services.AddControllers()
        .AddJsonOptions(
            options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
    

    À la suite du changement effectué, les noms de propriétés de la réponse JSON sérialisée de l’API web correspondent aux noms de propriétés équivalents du type d’objet CLR. Par exemple, la propriété Author de la classe Book est sérialisée en tant que Author au lieu de author.

  2. Dans Models/Book.cs, annotez la propriété BookName avec l’attribut [JsonPropertyName] :

    [BsonElement("Name")]
    [JsonPropertyName("Name")]
    public string BookName { get; set; } = null!;
    

    La valeur de l’attribut [JsonPropertyName] de Name représente le nom de propriété dans la réponse JSON sérialisée de l’API web.

  3. Ajoutez le code suivant en haut de Models/Book.cs pour résoudre la référence d’attribut [JsonProperty] :

    using System.Text.Json.Serialization;
    
  4. Répétez les étapes définies dans la section Tester l’API web. Notez la différence des noms de propriétés JSON.

Ajouter la prise en charge de l’authentification à une API web

ASP.NET Core Identity ajoute la fonctionnalité de connexion de l’interface utilisateur aux applications web ASP.NET Core. Pour sécuriser les API web et SPA, utilisez l’une des options suivantes :

Duende Identity Server est un framework OpenID Connect et OAuth 2.0 pour ASP.NET Core. Duende Identity Server active les fonctionnalités de sécurité suivantes :

  • Authentification en tant que service (AaaS)
  • Authentification/déconnexion unique (SSO) sur plusieurs types d’applications
  • Contrôle d’accès pour les API
  • Federation Gateway

Important

Duende Software peut vous demander de payer des frais de licence pour une utilisation en production de Duende Identity Server. Pour plus d’informations, consultez Migrer de ASP.NET Core 5.0 vers 6.0.

Pour plus d’informations, consultez la documentation Duende Identity Server (site web de Duende Software).

Ressources supplémentaires

Ce tutoriel crée une API web qui exécute des opérations de création, lecture, mise à jour et suppression (CRUD) sur une base de données NoSQL MongoDB.

Dans ce tutoriel, vous allez apprendre à :

  • Configurer MongoDB
  • Créer une base de données MongoDB
  • Définir une collection et un schéma MongoDB
  • Effectuer des opérations CRUD MongoDB à partir d’une API web
  • Personnaliser la sérialisation JSON

Prérequis

Configurer MongoDB

Activez l’accès à MongoDB et Mongo DB Shell à partir de n’importe où sur l’ordinateur de développement :

  1. Sur Windows, MongoDB est installé par défaut dans C:\Program Files\MongoDB. Ajoutez C:\Program Files\MongoDB\Server<numéro_version>\bin à la variable d’environnement PATH.

  2. Téléchargez l’interpréteur de commandes MongoDB et choisissez un répertoire dans lequel l’extraire. Ajoutez le chemin d’accès obtenu pour mongosh.exe à la variable d’environnement PATH.

  3. Choisissez sur l’ordinateur de développement un répertoire pour le stockage des données. Par exemple, C:\BooksData sous Windows. Le cas échéant, créez le répertoire. L’interpréteur de commandes mongo ne crée pas nouveaux répertoires.

  4. Dans l’interpréteur de commandes du système d’exploitation (et non l’interpréteur de commandes MongoDB), utilisez la commande suivante pour vous connecter à MongoDB sur le port par défaut 27017. Remplacez <data_directory_path> par le répertoire choisi à l’étape précédente.

    mongod --dbpath <data_directory_path>
    

Utilisez l’interpréteur de commandes MongoDB précédemment installé dans les étapes suivantes pour créer une base de données, des collections, et stocker des documents. Pour plus d’informations sur les commandes MongoDB Shell, consultez mongosh.

  1. Ouvrez une instance de l’interpréteur de commandes MongoDB en lançant mongosh.exe.

  2. Dans l’interpréteur de commandes, connectez-vous à la base de données de test par défaut en exécutant la commande suivante :

    mongosh
    
  3. Exécutez la commande suivante dans le shell de commandes :

    use BookStore
    

    Une base de données nommée BookStore est créée si elle n’existe pas déjà. Si la base de données existe déjà, sa connexion est ouverte pour les transactions.

  4. Créez une collection Books à l’aide de la commande suivante :

    db.createCollection('Books')
    

    Le résultat suivant s’affiche :

    { "ok" : 1 }
    
  5. Définissez un schéma pour la collection Books et insérez deux documents à l’aide de la commande suivante :

    db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
    

    Un résultat similaire à ce qui suit s’affiche :

    {
        "acknowledged" : true,
        "insertedIds" : [
            ObjectId("61a6058e6c43f32854e51f51"),
            ObjectId("61a6058e6c43f32854e51f52")
         ]
     }
    

    Remarque

    Les ObjectId affichés dans le résultat précédent ne correspondent pas à ceux affichés dans l’interpréteur de commandes.

  6. Affichez les documents de la base de données à l’aide de la commande suivante :

    db.Books.find().pretty()
    

    Un résultat similaire à ce qui suit s’affiche :

    {
         "_id" : ObjectId("61a6058e6c43f32854e51f51"),
         "Name" : "Design Patterns",
         "Price" : 54.93,
         "Category" : "Computers",
         "Author" : "Ralph Johnson"
     }
     {
         "_id" : ObjectId("61a6058e6c43f32854e51f52"),
         "Name" : "Clean Code",
         "Price" : 43.15,
         "Category" : "Computers",
         "Author" : "Robert C. Martin"
     }
    

    Le schéma ajoute une propriété _id automatiquement générée de type ObjectId pour chaque document.

Créer le projet d’API web ASP.NET Core

  1. Accédez à Fichier>Nouveau>Projet.

  2. Sélectionnez le type de projet API web ASP.NET Core, puis Suivant.

  3. Nommez le projet BookStoreApi, puis sélectionnez Suivant.

  4. Sélectionnez l’infrastructure .NET 7.0 (support Standard), puis Créer.

  5. Dans le menu Outils, sélectionnez Gestionnaire de package NuGet>Console du gestionnaire de package.

  6. Dans la fenêtre Console du Gestionnaire de Package, accédez à la racine du projet. Exécutez la commande suivante afin d’installer le pilote .NET pour MongoDB :

    Install-Package MongoDB.Driver
    

Ajouter un modèle d’entité

  1. Ajoutez un répertoire Models à la racine du projet.

  2. Ajoutez une classe Book au répertoire Models avec le code suivant :

    using MongoDB.Bson;
    using MongoDB.Bson.Serialization.Attributes;
    
    namespace BookStoreApi.Models;
    
    public class Book
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string? Id { get; set; }
    
        [BsonElement("Name")]
        public string BookName { get; set; } = null!;
    
        public decimal Price { get; set; }
    
        public string Category { get; set; } = null!;
    
        public string Author { get; set; } = null!;
    }
    

    Dans la classe précédente, la propriété Id est :

    • Requise pour mapper l’objet Common Language Runtime (CLR) à la collection MongoDB.
    • Annotée avec [BsonId] pour faire de cette propriété la clé primaire du document.
    • Annotée avec [BsonRepresentation(BsonType.ObjectId)] pour autoriser le passage du paramètre en tant que type string au lieu d’une structure ObjectId. Mongo gère la conversion de string en ObjectId.

    La propriété BookName est annotée avec l’attribut [BsonElement]. La valeur de l’attribut de Name représente le nom de propriété dans la collection MongoDB.

Ajouter un modèle de configuration

  1. Ajoutez les valeurs de configuration de base de données suivantes à appsettings.json :

    {
      "BookStoreDatabase": {
        "ConnectionString": "mongodb://localhost:27017",
        "DatabaseName": "BookStore",
        "BooksCollectionName": "Books"
      },
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*"
    }
    
  2. Ajoutez une classe BookStoreDatabaseSettings au répertoire Models avec le code suivant :

    namespace BookStoreApi.Models;
    
    public class BookStoreDatabaseSettings
    {
        public string ConnectionString { get; set; } = null!;
    
        public string DatabaseName { get; set; } = null!;
    
        public string BooksCollectionName { get; set; } = null!;
    }
    

    La classe BookStoreDatabaseSettings précédente est utilisée pour stocker les valeurs de propriété BookStoreDatabase du fichier appsettings.json. Les noms de propriétés JSON et C# sont nommés de manière identique pour faciliter le processus de mappage.

  3. Ajoutez le code en surbrillance suivant à Program.cs :

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.Configure<BookStoreDatabaseSettings>(
        builder.Configuration.GetSection("BookStoreDatabase"));
    

    Dans le code précédent, l’instance de configuration à laquelle la section BookStoreDatabase du fichier appsettings.json est liée est inscrite dans le conteneur d’injection de dépendances. Par exemple, la propriété ConnectionString de l’objet BookStoreDatabaseSettings est peuplée avec la propriété BookStoreDatabase:ConnectionString dans appsettings.json.

  4. Ajoutez le code suivant en haut de Program.cs pour résoudre la référence à BookStoreDatabaseSettings :

    using BookStoreApi.Models;
    

Ajouter un service d’opérations CRUD

  1. Ajoutez un répertoire Services à la racine du projet.

  2. Ajoutez une classe BooksService au répertoire Services avec le code suivant :

    using BookStoreApi.Models;
    using Microsoft.Extensions.Options;
    using MongoDB.Driver;
    
    namespace BookStoreApi.Services;
    
    public class BooksService
    {
        private readonly IMongoCollection<Book> _booksCollection;
    
        public BooksService(
            IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings)
        {
            var mongoClient = new MongoClient(
                bookStoreDatabaseSettings.Value.ConnectionString);
    
            var mongoDatabase = mongoClient.GetDatabase(
                bookStoreDatabaseSettings.Value.DatabaseName);
    
            _booksCollection = mongoDatabase.GetCollection<Book>(
                bookStoreDatabaseSettings.Value.BooksCollectionName);
        }
    
        public async Task<List<Book>> GetAsync() =>
            await _booksCollection.Find(_ => true).ToListAsync();
    
        public async Task<Book?> GetAsync(string id) =>
            await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync();
    
        public async Task CreateAsync(Book newBook) =>
            await _booksCollection.InsertOneAsync(newBook);
    
        public async Task UpdateAsync(string id, Book updatedBook) =>
            await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook);
    
        public async Task RemoveAsync(string id) =>
            await _booksCollection.DeleteOneAsync(x => x.Id == id);
    }
    

    Dans le code précédent, une instance de BookStoreDatabaseSettings est récupérée à partir de l’injection de dépendances via l’injection de constructeur. Cette technique permet d’accéder aux valeurs de configuration d’appsettings.json, qui ont été ajoutées à la section Ajouter un modèle de configuration.

  3. Ajoutez le code en surbrillance suivant à Program.cs :

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.Configure<BookStoreDatabaseSettings>(
        builder.Configuration.GetSection("BookStoreDatabase"));
    
    builder.Services.AddSingleton<BooksService>();
    

    Dans le code précédent, la classe BooksService est inscrite auprès de l’injection de dépendances pour permettre la prise en charge de l’injection de constructeur dans les classes consommatrices. La durée de vie de service de singleton est la plus appropriée, car BooksService a une dépendance directe sur MongoClient. Selon les recommandations officielles de réutilisation de Mongo Client, MongoClient doit être inscrit auprès de l’injection de dépendances avec une durée de vie de service de singleton.

  4. Ajoutez le code suivant en haut de Program.cs pour résoudre la référence à BooksService :

    using BookStoreApi.Services;
    

La classe BooksService utilise les membres MongoDB.Driver suivants pour exécuter des opérations CRUD dans la base de données :

  • MongoClient : Lit l’instance de serveur qui permet d’exécuter des opérations de base de données. Le constructeur de cette classe reçoit la chaîne de connexion MongoDB :

    public BooksService(
        IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings)
    {
        var mongoClient = new MongoClient(
            bookStoreDatabaseSettings.Value.ConnectionString);
    
        var mongoDatabase = mongoClient.GetDatabase(
            bookStoreDatabaseSettings.Value.DatabaseName);
    
        _booksCollection = mongoDatabase.GetCollection<Book>(
            bookStoreDatabaseSettings.Value.BooksCollectionName);
    }
    
  • IMongoDatabase : Représente la base de données Mongo qui permet d’exécuter des opérations. Ce tutoriel utilise la méthode générique GetCollection<TDocument>(collection) sur l’interface pour accéder aux données d’une collection spécifique. Exécutez des opérations CRUD sur la collection, après l’appel de cette méthode. Dans l’appel à la méthode GetCollection<TDocument>(collection) :

    • collection représente le nom de la collection.
    • TDocument représente le type d’objet CLR stocké dans la collection.

GetCollection<TDocument>(collection) retourne un objet MongoCollection représentant la collection. Dans ce didacticiel, les méthodes suivantes sont appelées sur la collection :

  • DeleteOneAsync : Supprime un seul document correspondant aux critères de recherche fournis.
  • Find<TDocument> : Retourne tous les documents de la collection correspondant aux critères de recherche fournis.
  • InsertOneAsync : Insère l’objet fourni en tant que nouveau document dans la collection.
  • ReplaceOneAsync : Remplace le seul document correspondant aux critères de recherche fournis par l’objet indiqué.

Ajout d'un contrôleur

Ajoutez une classe BooksController au répertoire Contrôleurs avec le code suivant :

using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;

namespace BookStoreApi.Controllers;

[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
    private readonly BooksService _booksService;

    public BooksController(BooksService booksService) =>
        _booksService = booksService;

    [HttpGet]
    public async Task<List<Book>> Get() =>
        await _booksService.GetAsync();

    [HttpGet("{id:length(24)}")]
    public async Task<ActionResult<Book>> Get(string id)
    {
        var book = await _booksService.GetAsync(id);

        if (book is null)
        {
            return NotFound();
        }

        return book;
    }

    [HttpPost]
    public async Task<IActionResult> Post(Book newBook)
    {
        await _booksService.CreateAsync(newBook);

        return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
    }

    [HttpPut("{id:length(24)}")]
    public async Task<IActionResult> Update(string id, Book updatedBook)
    {
        var book = await _booksService.GetAsync(id);

        if (book is null)
        {
            return NotFound();
        }

        updatedBook.Id = book.Id;

        await _booksService.UpdateAsync(id, updatedBook);

        return NoContent();
    }

    [HttpDelete("{id:length(24)}")]
    public async Task<IActionResult> Delete(string id)
    {
        var book = await _booksService.GetAsync(id);

        if (book is null)
        {
            return NotFound();
        }

        await _booksService.RemoveAsync(id);

        return NoContent();
    }
}

Le contrôleur d’API web précédent :

  • Utilise la classe BooksService pour exécuter des opérations CRUD.
  • Contient des méthodes d’action pour prendre en charge les requêtes HTTP GET, POST, PUT et DELETE.
  • Appelle CreatedAtAction dans la méthode d’action Create pour retourner une réponse HTTP 201. Le code d’état 201 est la réponse standard d’une méthode HTTP POST qui crée une ressource sur le serveur. CreatedAtAction ajoute également un en-tête Location à la réponse. L’en-tête Location spécifie l’URI du livre qui vient d’être créé.

Tester l’API web

  1. Générez et exécutez l'application.

  2. Accédez à https://localhost:<port>/api/books, où <port> est le numéro de port attribué automatiquement à l’application, pour tester la méthode d’action Get sans paramètre du contrôleur. Une réponse JSON similaire à la suivante s’affiche :

    [
      {
        "id": "61a6058e6c43f32854e51f51",
        "bookName": "Design Patterns",
        "price": 54.93,
        "category": "Computers",
        "author": "Ralph Johnson"
      },
      {
        "id": "61a6058e6c43f32854e51f52",
        "bookName": "Clean Code",
        "price": 43.15,
        "category": "Computers",
        "author": "Robert C. Martin"
      }
    ]
    
  3. Accédez à https://localhost:<port>/api/books/{id here} pour tester la méthode d’action Get surchargée du contrôleur. Une réponse JSON similaire à la suivante s’affiche :

    {
      "id": "61a6058e6c43f32854e51f52",
      "bookName": "Clean Code",
      "price": 43.15,
      "category": "Computers",
      "author": "Robert C. Martin"
    }
    

Configurer les options de sérialisation JSON

Vous devez changer deux détails concernant les réponses JSON retournées dans la section Tester l’API web :

  • Vous devez changer la casse mixte par défaut des noms de propriétés pour qu’elle corresponde à la casse Pascal des noms de propriétés de l’objet CLR.
  • La propriété bookName doit être retournée sous la forme Name.

Pour satisfaire les exigences précédentes, apportez les changements suivants :

  1. Dans Program.cs, ajoutez le code en surbrillance suivant à l’appel de méthode AddControllers :

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.Configure<BookStoreDatabaseSettings>(
        builder.Configuration.GetSection("BookStoreDatabase"));
    
    builder.Services.AddSingleton<BooksService>();
    
    builder.Services.AddControllers()
        .AddJsonOptions(
            options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
    

    À la suite du changement effectué, les noms de propriétés de la réponse JSON sérialisée de l’API web correspondent aux noms de propriétés équivalents du type d’objet CLR. Par exemple, la propriété Author de la classe Book est sérialisée en tant que Author au lieu de author.

  2. Dans Models/Book.cs, annotez la propriété BookName avec l’attribut [JsonPropertyName] :

    [BsonElement("Name")]
    [JsonPropertyName("Name")]
    public string BookName { get; set; } = null!;
    

    La valeur de l’attribut [JsonPropertyName] de Name représente le nom de propriété dans la réponse JSON sérialisée de l’API web.

  3. Ajoutez le code suivant en haut de Models/Book.cs pour résoudre la référence d’attribut [JsonProperty] :

    using System.Text.Json.Serialization;
    
  4. Répétez les étapes définies dans la section Tester l’API web. Notez la différence des noms de propriétés JSON.

Ajouter la prise en charge de l’authentification à une API web

ASP.NET Core Identity ajoute la fonctionnalité de connexion de l’interface utilisateur aux applications web ASP.NET Core. Pour sécuriser les API web et SPA, utilisez l’une des options suivantes :

Duende Identity Server est un framework OpenID Connect et OAuth 2.0 pour ASP.NET Core. Duende Identity Server active les fonctionnalités de sécurité suivantes :

  • Authentification en tant que service (AaaS)
  • Authentification/déconnexion unique (SSO) sur plusieurs types d’applications
  • Contrôle d’accès pour les API
  • Federation Gateway

Important

Duende Software peut vous demander de payer des frais de licence pour une utilisation en production de Duende Identity Server. Pour plus d’informations, consultez Migrer de ASP.NET Core 5.0 vers 6.0.

Pour plus d’informations, consultez la documentation Duende Identity Server (site web de Duende Software).

Ressources supplémentaires

Ce tutoriel crée une API web qui exécute des opérations de création, lecture, mise à jour et suppression (CRUD) sur une base de données NoSQL MongoDB.

Dans ce tutoriel, vous allez apprendre à :

  • Configurer MongoDB
  • Créer une base de données MongoDB
  • Définir une collection et un schéma MongoDB
  • Effectuer des opérations CRUD MongoDB à partir d’une API web
  • Personnaliser la sérialisation JSON

Prérequis

Configurer MongoDB

Activez l’accès à MongoDB et Mongo DB Shell à partir de n’importe où sur l’ordinateur de développement :

  1. Sur Windows, MongoDB est installé par défaut dans C:\Program Files\MongoDB. Ajoutez C:\Program Files\MongoDB\Server<numéro_version>\bin à la variable d’environnement PATH.

  2. Téléchargez l’interpréteur de commandes MongoDB et choisissez un répertoire dans lequel l’extraire. Ajoutez le chemin d’accès obtenu pour mongosh.exe à la variable d’environnement PATH.

  3. Choisissez sur l’ordinateur de développement un répertoire pour le stockage des données. Par exemple, C:\BooksData sous Windows. Le cas échéant, créez le répertoire. L’interpréteur de commandes mongo ne crée pas nouveaux répertoires.

  4. Dans l’interpréteur de commandes du système d’exploitation (et non l’interpréteur de commandes MongoDB), utilisez la commande suivante pour vous connecter à MongoDB sur le port par défaut 27017. Remplacez <data_directory_path> par le répertoire choisi à l’étape précédente.

    mongod --dbpath <data_directory_path>
    

Utilisez l’interpréteur de commandes MongoDB précédemment installé dans les étapes suivantes pour créer une base de données, des collections, et stocker des documents. Pour plus d’informations sur les commandes MongoDB Shell, consultez mongosh.

  1. Ouvrez une instance de l’interpréteur de commandes MongoDB en lançant mongosh.exe.

  2. Dans l’interpréteur de commandes, connectez-vous à la base de données de test par défaut en exécutant la commande suivante :

    mongosh
    
  3. Exécutez la commande suivante dans le shell de commandes :

    use BookStore
    

    Une base de données nommée BookStore est créée si elle n’existe pas déjà. Si la base de données existe déjà, sa connexion est ouverte pour les transactions.

  4. Créez une collection Books à l’aide de la commande suivante :

    db.createCollection('Books')
    

    Le résultat suivant s’affiche :

    { "ok" : 1 }
    
  5. Définissez un schéma pour la collection Books et insérez deux documents à l’aide de la commande suivante :

    db.Books.insertMany([{ "Name": "Design Patterns", "Price": 54.93, "Category": "Computers", "Author": "Ralph Johnson" }, { "Name": "Clean Code", "Price": 43.15, "Category": "Computers","Author": "Robert C. Martin" }])
    

    Un résultat similaire à ce qui suit s’affiche :

    {
        "acknowledged" : true,
        "insertedIds" : [
            ObjectId("61a6058e6c43f32854e51f51"),
            ObjectId("61a6058e6c43f32854e51f52")
         ]
     }
    

    Remarque

    Les ObjectId affichés dans le résultat précédent ne correspondent pas à ceux affichés dans l’interpréteur de commandes.

  6. Affichez les documents de la base de données à l’aide de la commande suivante :

    db.Books.find().pretty()
    

    Un résultat similaire à ce qui suit s’affiche :

    {
         "_id" : ObjectId("61a6058e6c43f32854e51f51"),
         "Name" : "Design Patterns",
         "Price" : 54.93,
         "Category" : "Computers",
         "Author" : "Ralph Johnson"
     }
     {
         "_id" : ObjectId("61a6058e6c43f32854e51f52"),
         "Name" : "Clean Code",
         "Price" : 43.15,
         "Category" : "Computers",
         "Author" : "Robert C. Martin"
     }
    

    Le schéma ajoute une propriété _id automatiquement générée de type ObjectId pour chaque document.

Créer le projet d’API web ASP.NET Core

  1. Accédez à Fichier>Nouveau>Projet.

  2. Sélectionnez le type de projet API web ASP.NET Core, puis Suivant.

  3. Nommez le projet BookStoreApi, puis sélectionnez Suivant.

  4. Sélectionnez le framework .NET 6.0 (support à long terme), puis Créer.

  5. Dans la fenêtre Console du Gestionnaire de Package, accédez à la racine du projet. Exécutez la commande suivante afin d’installer le pilote .NET pour MongoDB :

    Install-Package MongoDB.Driver
    

Ajouter un modèle d’entité

  1. Ajoutez un répertoire Models à la racine du projet.

  2. Ajoutez une classe Book au répertoire Models avec le code suivant :

    using MongoDB.Bson;
    using MongoDB.Bson.Serialization.Attributes;
    
    namespace BookStoreApi.Models;
    
    public class Book
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string? Id { get; set; }
    
        [BsonElement("Name")]
        public string BookName { get; set; } = null!;
    
        public decimal Price { get; set; }
    
        public string Category { get; set; } = null!;
    
        public string Author { get; set; } = null!;
    }
    

    Dans la classe précédente, la propriété Id est :

    • Requise pour mapper l’objet Common Language Runtime (CLR) à la collection MongoDB.
    • Annotée avec [BsonId] pour faire de cette propriété la clé primaire du document.
    • Annotée avec [BsonRepresentation(BsonType.ObjectId)] pour autoriser le passage du paramètre en tant que type string au lieu d’une structure ObjectId. Mongo gère la conversion de string en ObjectId.

    La propriété BookName est annotée avec l’attribut [BsonElement]. La valeur de l’attribut de Name représente le nom de propriété dans la collection MongoDB.

Ajouter un modèle de configuration

  1. Ajoutez les valeurs de configuration de base de données suivantes à appsettings.json :

    {
        "BookStoreDatabase": {
            "ConnectionString": "mongodb://localhost:27017",
            "DatabaseName": "BookStore",
            "BooksCollectionName": "Books"
        },
        "Logging": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft.AspNetCore": "Warning"
            }
        },
        "AllowedHosts": "*"
    }
    
  2. Ajoutez une classe BookStoreDatabaseSettings au répertoire Models avec le code suivant :

    namespace BookStoreApi.Models;
    
    public class BookStoreDatabaseSettings
    {
        public string ConnectionString { get; set; } = null!;
    
        public string DatabaseName { get; set; } = null!;
    
        public string BooksCollectionName { get; set; } = null!;
    }
    

    La classe BookStoreDatabaseSettings précédente est utilisée pour stocker les valeurs de propriété BookStoreDatabase du fichier appsettings.json. Les noms de propriétés JSON et C# sont nommés de manière identique pour faciliter le processus de mappage.

  3. Ajoutez le code en surbrillance suivant à Program.cs :

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.Configure<BookStoreDatabaseSettings>(
        builder.Configuration.GetSection("BookStoreDatabase"));
    

    Dans le code précédent, l’instance de configuration à laquelle la section BookStoreDatabase du fichier appsettings.json est liée est inscrite dans le conteneur d’injection de dépendances. Par exemple, la propriété ConnectionString de l’objet BookStoreDatabaseSettings est peuplée avec la propriété BookStoreDatabase:ConnectionString dans appsettings.json.

  4. Ajoutez le code suivant en haut de Program.cs pour résoudre la référence à BookStoreDatabaseSettings :

    using BookStoreApi.Models;
    

Ajouter un service d’opérations CRUD

  1. Ajoutez un répertoire Services à la racine du projet.

  2. Ajoutez une classe BooksService au répertoire Services avec le code suivant :

    using BookStoreApi.Models;
    using Microsoft.Extensions.Options;
    using MongoDB.Driver;
    
    namespace BookStoreApi.Services;
    
    public class BooksService
    {
        private readonly IMongoCollection<Book> _booksCollection;
    
        public BooksService(
            IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings)
        {
            var mongoClient = new MongoClient(
                bookStoreDatabaseSettings.Value.ConnectionString);
    
            var mongoDatabase = mongoClient.GetDatabase(
                bookStoreDatabaseSettings.Value.DatabaseName);
    
            _booksCollection = mongoDatabase.GetCollection<Book>(
                bookStoreDatabaseSettings.Value.BooksCollectionName);
        }
    
        public async Task<List<Book>> GetAsync() =>
            await _booksCollection.Find(_ => true).ToListAsync();
    
        public async Task<Book?> GetAsync(string id) =>
            await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync();
    
        public async Task CreateAsync(Book newBook) =>
            await _booksCollection.InsertOneAsync(newBook);
    
        public async Task UpdateAsync(string id, Book updatedBook) =>
            await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook);
    
        public async Task RemoveAsync(string id) =>
            await _booksCollection.DeleteOneAsync(x => x.Id == id);
    }
    

    Dans le code précédent, une instance de BookStoreDatabaseSettings est récupérée à partir de l’injection de dépendances via l’injection de constructeur. Cette technique permet d’accéder aux valeurs de configuration d’appsettings.json, qui ont été ajoutées à la section Ajouter un modèle de configuration.

  3. Ajoutez le code en surbrillance suivant à Program.cs :

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.Configure<BookStoreDatabaseSettings>(
        builder.Configuration.GetSection("BookStoreDatabase"));
    
    builder.Services.AddSingleton<BooksService>();
    

    Dans le code précédent, la classe BooksService est inscrite auprès de l’injection de dépendances pour permettre la prise en charge de l’injection de constructeur dans les classes consommatrices. La durée de vie de service de singleton est la plus appropriée, car BooksService a une dépendance directe sur MongoClient. Selon les recommandations officielles de réutilisation de Mongo Client, MongoClient doit être inscrit auprès de l’injection de dépendances avec une durée de vie de service de singleton.

  4. Ajoutez le code suivant en haut de Program.cs pour résoudre la référence à BooksService :

    using BookStoreApi.Services;
    

La classe BooksService utilise les membres MongoDB.Driver suivants pour exécuter des opérations CRUD dans la base de données :

  • MongoClient : Lit l’instance de serveur qui permet d’exécuter des opérations de base de données. Le constructeur de cette classe reçoit la chaîne de connexion MongoDB :

    public BooksService(
        IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings)
    {
        var mongoClient = new MongoClient(
            bookStoreDatabaseSettings.Value.ConnectionString);
    
        var mongoDatabase = mongoClient.GetDatabase(
            bookStoreDatabaseSettings.Value.DatabaseName);
    
        _booksCollection = mongoDatabase.GetCollection<Book>(
            bookStoreDatabaseSettings.Value.BooksCollectionName);
    }
    
  • IMongoDatabase : Représente la base de données Mongo qui permet d’exécuter des opérations. Ce tutoriel utilise la méthode générique GetCollection<TDocument>(collection) sur l’interface pour accéder aux données d’une collection spécifique. Exécutez des opérations CRUD sur la collection, après l’appel de cette méthode. Dans l’appel à la méthode GetCollection<TDocument>(collection) :

    • collection représente le nom de la collection.
    • TDocument représente le type d’objet CLR stocké dans la collection.

GetCollection<TDocument>(collection) retourne un objet MongoCollection représentant la collection. Dans ce didacticiel, les méthodes suivantes sont appelées sur la collection :

  • DeleteOneAsync : Supprime un seul document correspondant aux critères de recherche fournis.
  • Find<TDocument> : Retourne tous les documents de la collection correspondant aux critères de recherche fournis.
  • InsertOneAsync : Insère l’objet fourni en tant que nouveau document dans la collection.
  • ReplaceOneAsync : Remplace le seul document correspondant aux critères de recherche fournis par l’objet indiqué.

Ajout d'un contrôleur

Ajoutez une classe BooksController au répertoire Contrôleurs avec le code suivant :

using BookStoreApi.Models;
using BookStoreApi.Services;
using Microsoft.AspNetCore.Mvc;

namespace BookStoreApi.Controllers;

[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
    private readonly BooksService _booksService;

    public BooksController(BooksService booksService) =>
        _booksService = booksService;

    [HttpGet]
    public async Task<List<Book>> Get() =>
        await _booksService.GetAsync();

    [HttpGet("{id:length(24)}")]
    public async Task<ActionResult<Book>> Get(string id)
    {
        var book = await _booksService.GetAsync(id);

        if (book is null)
        {
            return NotFound();
        }

        return book;
    }

    [HttpPost]
    public async Task<IActionResult> Post(Book newBook)
    {
        await _booksService.CreateAsync(newBook);

        return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
    }

    [HttpPut("{id:length(24)}")]
    public async Task<IActionResult> Update(string id, Book updatedBook)
    {
        var book = await _booksService.GetAsync(id);

        if (book is null)
        {
            return NotFound();
        }

        updatedBook.Id = book.Id;

        await _booksService.UpdateAsync(id, updatedBook);

        return NoContent();
    }

    [HttpDelete("{id:length(24)}")]
    public async Task<IActionResult> Delete(string id)
    {
        var book = await _booksService.GetAsync(id);

        if (book is null)
        {
            return NotFound();
        }

        await _booksService.RemoveAsync(id);

        return NoContent();
    }
}

Le contrôleur d’API web précédent :

  • Utilise la classe BooksService pour exécuter des opérations CRUD.
  • Contient des méthodes d’action pour prendre en charge les requêtes HTTP GET, POST, PUT et DELETE.
  • Appelle CreatedAtAction dans la méthode d’action Create pour retourner une réponse HTTP 201. Le code d’état 201 est la réponse standard d’une méthode HTTP POST qui crée une ressource sur le serveur. CreatedAtAction ajoute également un en-tête Location à la réponse. L’en-tête Location spécifie l’URI du livre qui vient d’être créé.

Tester l’API web

  1. Générez et exécutez l'application.

  2. Accédez à https://localhost:<port>/api/books, où <port> est le numéro de port attribué automatiquement à l’application, pour tester la méthode d’action Get sans paramètre du contrôleur. Une réponse JSON similaire à la suivante s’affiche :

    [
      {
        "id": "61a6058e6c43f32854e51f51",
        "bookName": "Design Patterns",
        "price": 54.93,
        "category": "Computers",
        "author": "Ralph Johnson"
      },
      {
        "id": "61a6058e6c43f32854e51f52",
        "bookName": "Clean Code",
        "price": 43.15,
        "category": "Computers",
        "author": "Robert C. Martin"
      }
    ]
    
  3. Accédez à https://localhost:<port>/api/books/{id here} pour tester la méthode d’action Get surchargée du contrôleur. Une réponse JSON similaire à la suivante s’affiche :

    {
      "id": "61a6058e6c43f32854e51f52",
      "bookName": "Clean Code",
      "price": 43.15,
      "category": "Computers",
      "author": "Robert C. Martin"
    }
    

Configurer les options de sérialisation JSON

Vous devez changer deux détails concernant les réponses JSON retournées dans la section Tester l’API web :

  • Vous devez changer la casse mixte par défaut des noms de propriétés pour qu’elle corresponde à la casse Pascal des noms de propriétés de l’objet CLR.
  • La propriété bookName doit être retournée sous la forme Name.

Pour satisfaire les exigences précédentes, apportez les changements suivants :

  1. Dans Program.cs, ajoutez le code en surbrillance suivant à l’appel de méthode AddControllers :

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.Configure<BookStoreDatabaseSettings>(
        builder.Configuration.GetSection("BookStoreDatabase"));
    
    builder.Services.AddSingleton<BooksService>();
    
    builder.Services.AddControllers()
        .AddJsonOptions(
            options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
    

    À la suite du changement effectué, les noms de propriétés de la réponse JSON sérialisée de l’API web correspondent aux noms de propriétés équivalents du type d’objet CLR. Par exemple, la propriété Author de la classe Book est sérialisée en tant que Author au lieu de author.

  2. Dans Models/Book.cs, annotez la propriété BookName avec l’attribut [JsonPropertyName] :

    [BsonElement("Name")]
    [JsonPropertyName("Name")]
    public string BookName { get; set; } = null!;
    

    La valeur de l’attribut [JsonPropertyName] de Name représente le nom de propriété dans la réponse JSON sérialisée de l’API web.

  3. Ajoutez le code suivant en haut de Models/Book.cs pour résoudre la référence d’attribut [JsonProperty] :

    using System.Text.Json.Serialization;
    
  4. Répétez les étapes définies dans la section Tester l’API web. Notez la différence des noms de propriétés JSON.

Ajouter la prise en charge de l’authentification à une API web

ASP.NET Core Identity ajoute la fonctionnalité de connexion de l’interface utilisateur aux applications web ASP.NET Core. Pour sécuriser les API web et SPA, utilisez l’une des options suivantes :

Duende Identity Server est un framework OpenID Connect et OAuth 2.0 pour ASP.NET Core. Duende Identity Server active les fonctionnalités de sécurité suivantes :

  • Authentification en tant que service (AaaS)
  • Authentification/déconnexion unique (SSO) sur plusieurs types d’applications
  • Contrôle d’accès pour les API
  • Federation Gateway

Important

Duende Software peut vous demander de payer des frais de licence pour une utilisation en production de Duende Identity Server. Pour plus d’informations, consultez Migrer de ASP.NET Core 5.0 vers 6.0.

Pour plus d’informations, consultez la documentation Duende Identity Server (site web de Duende Software).

Ressources supplémentaires

Ce tutoriel crée une API web qui exécute des opérations de création, lecture, mise à jour et suppression (CRUD) sur une base de données NoSQL MongoDB.

Dans ce tutoriel, vous allez apprendre à :

  • Configurer MongoDB
  • Créer une base de données MongoDB
  • Définir une collection et un schéma MongoDB
  • Effectuer des opérations CRUD MongoDB à partir d’une API web
  • Personnaliser la sérialisation JSON

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)

Prérequis

Configurer MongoDB

Si vous utilisez Windows, MongoDB est installé par défaut dans C:\Program Files\MongoDB. Ajoutez C:\Program Files\MongoDB\Server<numéro_version>\bin à la variable d’environnement Path. Cette modification permet d’accéder à MongoDB depuis n’importe quel emplacement sur votre ordinateur de développement.

Utilisez l’interpréteur de commandes mongo dans les étapes suivantes pour créer une base de données, des collections, et stocker des documents. Pour plus d’informations sur les commandes de l’interpréteur mongo, consultez Utilisation de l’interpréteur de commandes mongo.

  1. Choisissez sur votre ordinateur de développement un répertoire pour le stockage des données. Par exemple, C:\BooksData sous Windows. Le cas échéant, créez le répertoire. L’interpréteur de commandes mongo ne crée pas nouveaux répertoires.

  2. Ouvrez un interpréteur de commandes. Exécutez la commande suivante pour vous connecter à MongoDB sur le port par défaut 27017. N’oubliez pas de remplacer <data_directory_path> par le répertoire que vous avez choisi à l’étape précédente.

    mongod --dbpath <data_directory_path>
    
  3. Ouvrez une autre instance de l’interpréteur de commandes. Connectez-vous à la base de données de test par défaut en exécutant la commande suivante :

    mongo
    
  4. Exécutez la commande suivante dans l’interpréteur de commandes :

    use BookstoreDb
    

    Une base de données nommée BookstoreDb est créée si elle n’existe pas déjà. Si la base de données existe déjà, sa connexion est ouverte pour les transactions.

  5. Créez une collection Books à l’aide de la commande suivante :

    db.createCollection('Books')
    

    Le résultat suivant s’affiche :

    { "ok" : 1 }
    
  6. Définissez un schéma pour la collection Books et insérez deux documents à l’aide de la commande suivante :

    db.Books.insertMany([{'Name':'Design Patterns','Price':54.93,'Category':'Computers','Author':'Ralph Johnson'}, {'Name':'Clean Code','Price':43.15,'Category':'Computers','Author':'Robert C. Martin'}])
    

    Le résultat suivant s’affiche :

    {
      "acknowledged" : true,
      "insertedIds" : [
        ObjectId("5bfd996f7b8e48dc15ff215d"),
        ObjectId("5bfd996f7b8e48dc15ff215e")
      ]
    }
    

    Remarque

    Les ID indiqués dans cet article ne correspondent pas aux ID obtenus quand vous exécutez cet exemple.

  7. Affichez les documents de la base de données à l’aide de la commande suivante :

    db.Books.find({}).pretty()
    

    Le résultat suivant s’affiche :

    {
      "_id" : ObjectId("5bfd996f7b8e48dc15ff215d"),
      "Name" : "Design Patterns",
      "Price" : 54.93,
      "Category" : "Computers",
      "Author" : "Ralph Johnson"
    }
    {
      "_id" : ObjectId("5bfd996f7b8e48dc15ff215e"),
      "Name" : "Clean Code",
      "Price" : 43.15,
      "Category" : "Computers",
      "Author" : "Robert C. Martin"
    }
    

    Le schéma ajoute une propriété _id automatiquement générée de type ObjectId pour chaque document.

La base de données est en lecture seule. Vous pouvez commencer à créer l’API web ASP.NET Core.

Créer le projet d’API web ASP.NET Core

  1. Accédez à Fichier>Nouveau>Projet.

  2. Sélectionnez le type de projet Application web ASP.NET Core, puis sélectionnez Suivant.

  3. Nommez le projet BooksApi, puis sélectionnez Créer.

  4. Sélectionnez le framework cible .NET Core et ASP.NET Core 3.0. Sélectionnez le modèle de projet API, puis sélectionnez Créer.

  5. Visitez la Galerie NuGet : MongoDB.Driver pour déterminer la dernière version stable du pilote .NET pour MongoDB. Dans la fenêtre Console du Gestionnaire de Package, accédez à la racine du projet. Exécutez la commande suivante afin d’installer le pilote .NET pour MongoDB :

    Install-Package MongoDB.Driver -Version {VERSION}
    

Ajouter un modèle d’entité

  1. Ajoutez un répertoire Models à la racine du projet.

  2. Ajoutez une classe Book au répertoire Models avec le code suivant :

    using MongoDB.Bson;
    using MongoDB.Bson.Serialization.Attributes;
    
    namespace BooksApi.Models
    {
        public class Book
        {
            [BsonId]
            [BsonRepresentation(BsonType.ObjectId)]
            public string Id { get; set; }
    
            [BsonElement("Name")]
            public string BookName { get; set; }
    
            public decimal Price { get; set; }
    
            public string Category { get; set; }
    
            public string Author { get; set; }
        }
    }
    

    Dans la classe précédente, la propriété Id est :

    • Requise pour mapper l’objet Common Language Runtime (CLR) à la collection MongoDB.
    • Annotée avec [BsonId] pour faire de cette propriété la clé primaire du document.
    • Annotée avec [BsonRepresentation(BsonType.ObjectId)] pour autoriser le passage du paramètre en tant que type string au lieu d’une structure ObjectId. Mongo gère la conversion de string en ObjectId.

    La propriété BookName est annotée avec l’attribut [BsonElement]. La valeur de l’attribut de Name représente le nom de propriété dans la collection MongoDB.

Ajouter un modèle de configuration

  1. Ajoutez les valeurs de configuration de base de données suivantes à appsettings.json :

    {
      "BookstoreDatabaseSettings": {
        "BooksCollectionName": "Books",
        "ConnectionString": "mongodb://localhost:27017",
        "DatabaseName": "BookstoreDb"
      },
      "Logging": {
        "IncludeScopes": false,
        "Debug": {
          "LogLevel": {
            "Default": "Warning"
          }
        },
        "Console": {
          "LogLevel": {
            "Default": "Warning"
          }
        }
      }
    }
    
  2. Ajoutez un fichier BookstoreDatabaseSettings.cs au répertoire Models avec le code suivant :

    namespace BooksApi.Models
    {
        public class BookstoreDatabaseSettings : IBookstoreDatabaseSettings
        {
            public string BooksCollectionName { get; set; }
            public string ConnectionString { get; set; }
            public string DatabaseName { get; set; }
        }
    
        public interface IBookstoreDatabaseSettings
        {
            string BooksCollectionName { get; set; }
            string ConnectionString { get; set; }
            string DatabaseName { get; set; }
        }
    }
    

    La classe BookstoreDatabaseSettings précédente est utilisée pour stocker les valeurs de propriété BookstoreDatabaseSettings du fichier appsettings.json. Les noms de propriétés JSON et C# sont nommés de manière identique pour faciliter le processus de mappage.

  3. Ajoutez le code en surbrillance suivant à Startup.ConfigureServices :

    public void ConfigureServices(IServiceCollection services)
    {
        // requires using Microsoft.Extensions.Options
        services.Configure<BookstoreDatabaseSettings>(
            Configuration.GetSection(nameof(BookstoreDatabaseSettings)));
    
        services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
            sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);
    
        services.AddControllers();
    }
    

    Dans le code précédent :

    • L’instance de configuration à laquelle la section BookstoreDatabaseSettings du fichier appsettings.json est liée est inscrite dans le conteneur d’injection de dépendances. Par exemple, la propriété ConnectionString d’un objet BookstoreDatabaseSettings est peuplée avec la propriété BookstoreDatabaseSettings:ConnectionString dans appsettings.json.
    • L’interface IBookstoreDatabaseSettings est inscrite auprès de l’injection de dépendances avec une durée de vie de service de singleton. Une fois injectée, l’instance d’interface est résolue en objet BookstoreDatabaseSettings.
  4. Ajoutez le code suivant en haut de Startup.cs pour résoudre les références à BookstoreDatabaseSettings et IBookstoreDatabaseSettings :

    using BooksApi.Models;
    

Ajouter un service d’opérations CRUD

  1. Ajoutez un répertoire Services à la racine du projet.

  2. Ajoutez une classe BookService au répertoire Services avec le code suivant :

    using BooksApi.Models;
    using MongoDB.Driver;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace BooksApi.Services
    {
        public class BookService
        {
            private readonly IMongoCollection<Book> _books;
    
            public BookService(IBookstoreDatabaseSettings settings)
            {
                var client = new MongoClient(settings.ConnectionString);
                var database = client.GetDatabase(settings.DatabaseName);
    
                _books = database.GetCollection<Book>(settings.BooksCollectionName);
            }
    
            public List<Book> Get() =>
                _books.Find(book => true).ToList();
    
            public Book Get(string id) =>
                _books.Find<Book>(book => book.Id == id).FirstOrDefault();
    
            public Book Create(Book book)
            {
                _books.InsertOne(book);
                return book;
            }
    
            public void Update(string id, Book bookIn) =>
                _books.ReplaceOne(book => book.Id == id, bookIn);
    
            public void Remove(Book bookIn) =>
                _books.DeleteOne(book => book.Id == bookIn.Id);
    
            public void Remove(string id) => 
                _books.DeleteOne(book => book.Id == id);
        }
    }
    

    Dans le code précédent, une instance de IBookstoreDatabaseSettings est récupérée à partir de l’injection de dépendances via l’injection de constructeur. Cette technique permet d’accéder aux valeurs de configuration d’appsettings.json, qui ont été ajoutées à la section Ajouter un modèle de configuration.

  3. Ajoutez le code en surbrillance suivant à Startup.ConfigureServices :

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<BookstoreDatabaseSettings>(
            Configuration.GetSection(nameof(BookstoreDatabaseSettings)));
    
        services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
            sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);
    
        services.AddSingleton<BookService>();
    
        services.AddControllers();
    }
    

    Dans le code précédent, la classe BookService est inscrite auprès de l’injection de dépendances pour permettre la prise en charge de l’injection de constructeur dans les classes consommatrices. La durée de vie de service de singleton est la plus appropriée, car BookService a une dépendance directe sur MongoClient. Selon les recommandations officielles de réutilisation de Mongo Client, MongoClient doit être inscrit auprès de l’injection de dépendances avec une durée de vie de service de singleton.

  4. Ajoutez le code suivant en haut de Startup.cs pour résoudre la référence à BookService :

    using BooksApi.Services;
    

La classe BookService utilise les membres MongoDB.Driver suivants pour exécuter des opérations CRUD dans la base de données :

  • MongoClient : Lit l’instance de serveur qui permet d’exécuter des opérations de base de données. Le constructeur de cette classe reçoit la chaîne de connexion MongoDB :

    public BookService(IBookstoreDatabaseSettings settings)
    {
        var client = new MongoClient(settings.ConnectionString);
        var database = client.GetDatabase(settings.DatabaseName);
    
        _books = database.GetCollection<Book>(settings.BooksCollectionName);
    }
    
  • IMongoDatabase : Représente la base de données Mongo qui permet d’exécuter des opérations. Ce tutoriel utilise la méthode générique GetCollection<TDocument>(collection) sur l’interface pour accéder aux données d’une collection spécifique. Exécutez des opérations CRUD sur la collection, après l’appel de cette méthode. Dans l’appel à la méthode GetCollection<TDocument>(collection) :

    • collection représente le nom de la collection.
    • TDocument représente le type d’objet CLR stocké dans la collection.

GetCollection<TDocument>(collection) retourne un objet MongoCollection représentant la collection. Dans ce didacticiel, les méthodes suivantes sont appelées sur la collection :

  • DeleteOne : Supprime un seul document correspondant aux critères de recherche fournis.
  • Find<TDocument> : Retourne tous les documents de la collection correspondant aux critères de recherche fournis.
  • InsertOne : Insère l’objet fourni en tant que nouveau document dans la collection.
  • ReplaceOne : Remplace le seul document correspondant aux critères de recherche fournis par l’objet indiqué.

Ajout d'un contrôleur

Ajoutez une classe BooksController au répertoire Contrôleurs avec le code suivant :

using BooksApi.Models;
using BooksApi.Services;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace BooksApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class BooksController : ControllerBase
    {
        private readonly BookService _bookService;

        public BooksController(BookService bookService)
        {
            _bookService = bookService;
        }

        [HttpGet]
        public ActionResult<List<Book>> Get() =>
            _bookService.Get();

        [HttpGet("{id:length(24)}", Name = "GetBook")]
        public ActionResult<Book> Get(string id)
        {
            var book = _bookService.Get(id);

            if (book == null)
            {
                return NotFound();
            }

            return book;
        }

        [HttpPost]
        public ActionResult<Book> Create(Book book)
        {
            _bookService.Create(book);

            return CreatedAtRoute("GetBook", new { id = book.Id.ToString() }, book);
        }

        [HttpPut("{id:length(24)}")]
        public IActionResult Update(string id, Book bookIn)
        {
            var book = _bookService.Get(id);

            if (book == null)
            {
                return NotFound();
            }

            _bookService.Update(id, bookIn);

            return NoContent();
        }

        [HttpDelete("{id:length(24)}")]
        public IActionResult Delete(string id)
        {
            var book = _bookService.Get(id);

            if (book == null)
            {
                return NotFound();
            }

            _bookService.Remove(id);

            return NoContent();
        }
    }
}

Le contrôleur d’API web précédent :

  • Utilise la classe BookService pour exécuter des opérations CRUD.
  • Contient des méthodes d’action pour prendre en charge les requêtes HTTP GET, POST, PUT et DELETE.
  • Appelle CreatedAtRoute dans la méthode d’action Create pour retourner une réponse HTTP 201. Le code d’état 201 est la réponse standard d’une méthode HTTP POST qui crée une ressource sur le serveur. CreatedAtRoute ajoute également un en-tête Location à la réponse. L’en-tête Location spécifie l’URI du livre qui vient d’être créé.

Tester l’API web

  1. Générez et exécutez l'application.

  2. Accédez à https://localhost:<port>/api/books pour tester la méthode d’action Get sans paramètre du contrôleur. La réponse JSON suivante apparaît :

    [
      {
        "id":"5bfd996f7b8e48dc15ff215d",
        "bookName":"Design Patterns",
        "price":54.93,
        "category":"Computers",
        "author":"Ralph Johnson"
      },
      {
        "id":"5bfd996f7b8e48dc15ff215e",
        "bookName":"Clean Code",
        "price":43.15,
        "category":"Computers",
        "author":"Robert C. Martin"
      }
    ]
    
  3. Accédez à https://localhost:<port>/api/books/{id here} pour tester la méthode d’action Get surchargée du contrôleur. La réponse JSON suivante apparaît :

    {
      "id":"{ID}",
      "bookName":"Clean Code",
      "price":43.15,
      "category":"Computers",
      "author":"Robert C. Martin"
    }
    

Configurer les options de sérialisation JSON

Vous devez changer deux détails concernant les réponses JSON retournées dans la section Tester l’API web :

  • Vous devez changer la casse mixte par défaut des noms de propriétés pour qu’elle corresponde à la casse Pascal des noms de propriétés de l’objet CLR.
  • La propriété bookName doit être retournée sous la forme Name.

Pour satisfaire les exigences précédentes, apportez les changements suivants :

  1. Json.NET a été supprimé du framework partagé ASP.NET. Ajoutez une référence de package à Microsoft.AspNetCore.Mvc.NewtonsoftJson.

  2. Dans Startup.ConfigureServices, ajoutez le code en surbrillance suivant à l’appel de méthode AddControllers :

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<BookstoreDatabaseSettings>(
            Configuration.GetSection(nameof(BookstoreDatabaseSettings)));
    
        services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
            sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);
    
        services.AddSingleton<BookService>();
    
        services.AddControllers()
            .AddNewtonsoftJson(options => options.UseMemberCasing());
    }
    

    À la suite du changement effectué, les noms de propriétés de la réponse JSON sérialisée de l’API web correspondent aux noms de propriétés équivalents du type d’objet CLR. Par exemple, la propriété Author de la classe Book est sérialisée en tant que Author.

  3. Dans Models/Book.cs, annotez la propriété BookName avec l’attribut [JsonProperty] suivant :

    [BsonElement("Name")]
    [JsonProperty("Name")]
    public string BookName { get; set; }
    

    La valeur de l’attribut [JsonProperty] de Name représente le nom de propriété dans la réponse JSON sérialisée de l’API web.

  4. Ajoutez le code suivant en haut de Models/Book.cs pour résoudre la référence d’attribut [JsonProperty] :

    using Newtonsoft.Json;
    
  5. Répétez les étapes définies dans la section Tester l’API web. Notez la différence des noms de propriétés JSON.

Ajouter la prise en charge de l’authentification à une API web

ASP.NET Core Identity ajoute la fonctionnalité de connexion de l’interface utilisateur aux applications web ASP.NET Core. Pour sécuriser les API web et SPA, utilisez l’une des options suivantes :

Duende IdentityServer est un framework OpenID Connect et OAuth 2.0 pour ASP.NET Core. Duende IdentityServer active les fonctionnalités de sécurité suivantes :

  • Authentification en tant que service (AaaS)
  • Authentification/déconnexion unique (SSO) sur plusieurs types d’applications
  • Contrôle d’accès pour les API
  • Federation Gateway

Pour plus d’informations, consultez la section Vue d’ensemble de Duende IdentityServer.

Pour plus d’informations sur les autres fournisseurs d’authentification, consultez Options d’authentification de la communauté Open Source pour ASP.NET Core

Étapes suivantes

Pour plus d’informations sur la création d’API web ASP.NET Core, consultez les ressources suivantes :