Tutoriel : Création d’une API web avec ASP.NET Core

Par Rick Anderson, Kirk Larkinet Mike Wasson

Ce tutoriel décrit les principes fondamentaux liés à la génération d’une API web avec ASP.NET Core.

Dans ce tutoriel, vous allez apprendre à :

  • Créer un projet d’API web.
  • Ajouter une classe de modèle et un contexte de base de données.
  • Générer automatiquement des modèles pour un contrôleur avec des méthodes CRUD.
  • Configurer le routage, les chemins d’URL et les valeurs de retour.
  • Appeler l’API web avec Postman

À la fin, vous disposez d’une API web qui peut gérer des tâches stockées dans une base de données.

Vue d’ensemble

Ce didacticiel crée l’API suivante :

API Description Corps de la demande Response body
GET /api/todoitems Obtenir toutes les tâches None Tableau de tâches
GET /api/todoitems/{id} Obtenir un élément par ID None Tâche
POST /api/todoitems Ajouter un nouvel élément Tâche Tâche
PUT /api/todoitems/{id} Mettre à jour un élément existant   Tâche None
DELETE /api/todoitems/{id}     Supprimer un élément    None None

Le diagramme suivant illustre la conception de l’application.

Le client est représenté par une zone située à gauche. Il envoie une demande et reçoit une réponse de l’application, représentée par une zone dessinée à droite. Dans la zone de l’application, trois zones représentent le contrôleur, le modèle et la couche d’accès aux données. La requête provient du contrôleur de l’application, et les opérations de lecture/écriture se produisent entre le contrôleur et la couche d’accès aux données. Le modèle est sérialisé et retourné au client dans la réponse.

Prérequis

Créer un projet web

  • dans le menu fichier , sélectionnez nouveau > Project.
  • sélectionnez le modèle API Web ASP.NET Core , puis cliquez sur suivant.
  • Nommez le projet TodoApi et cliquez sur Créer.
  • dans la boîte de dialogue créer une Application Web ASP.NET Core , vérifiez que .net Core et ASP.NET Core 5,0 sont sélectionnés. Sélectionnez le modèle API et cliquez sur Créer.

Boîte de dialogue de nouveau projet dans VS

Tester le projet

Le modèle de projet crée une WeatherForecast API avec prise en charge de Swagger.

Appuyez sur Ctrl+F5 pour exécuter sans le débogueur.

Visual Studio affiche la boîte de dialogue suivante lorsqu’un projet n’est pas encore configuré pour utiliser SSL :

Ce projet est configuré pour utiliser SSL. Pour éviter les avertissements SSL dans le navigateur, vous pouvez choisir d’approuver le certificat auto-signé généré par IIS Express. Voulez-vous approuver le certificat SSL d’IIS Express ?

Sélectionnez Oui si vous faites confiance au certificat SSL d’IIS Express.

La boîte de dialogue suivante s’affiche :

Boîte de dialogue Avertissement de sécurité

Sélectionnez Oui si vous acceptez d’approuver le certificat de développement.

Pour plus d’informations sur l’approbation du navigateur Firefox, voir firefox SEC_ERROR_INADEQUATE_KEY_USAGE erreur de certificat.

Visual Studio lance :

  • serveur web IIS Express.
  • Le navigateur par défaut et navigue vers https://localhost:<port>/swagger/index.html , où <port> est un numéro de port choisi de façon aléatoire.

La page Swagger /swagger/index.html s’affiche. Sélectionnez faire > essayer l' > exécution. La page affiche :

  • Commande de boucle pour tester l’API WeatherForecast.
  • URL pour tester l’API WeatherForecast.
  • Code, corps et en-têtes de la réponse.
  • Zone de liste déroulante avec les types de média et l’exemple de valeur et de schéma.

si la page Swagger ne s’affiche pas, consultez ce GitHub problème.

Swagger est utilisé pour générer une documentation utile et des pages d’aide pour les API Web. Ce didacticiel se concentre sur la création d’une API Web. Pour plus d’informations sur Swagger, consultez ASP.NET Core la documentation de l’API web avec Swagger/OpenAPI .

Copiez et collez l’URL de la requête dans le navigateur : https://localhost:<port>/WeatherForecast

Un code JSON similaire au suivant est retourné :

[
    {
        "date": "2019-07-16T19:04:05.7257911-06:00",
        "temperatureC": 52,
        "temperatureF": 125,
        "summary": "Mild"
    },
    {
        "date": "2019-07-17T19:04:05.7258461-06:00",
        "temperatureC": 36,
        "temperatureF": 96,
        "summary": "Warm"
    },
    {
        "date": "2019-07-18T19:04:05.7258467-06:00",
        "temperatureC": 39,
        "temperatureF": 102,
        "summary": "Cool"
    },
    {
        "date": "2019-07-19T19:04:05.7258471-06:00",
        "temperatureC": 10,
        "temperatureF": 49,
        "summary": "Bracing"
    },
    {
        "date": "2019-07-20T19:04:05.7258474-06:00",
        "temperatureC": -1,
        "temperatureF": 31,
        "summary": "Chilly"
    }
]

Mettre à jour launchUrl

Dans Properties\launchSettings.js, mettez à jour launchUrl de "swagger" vers "api/todoitems" :

"launchUrl": "api/todoitems",

Comme Swagger sera supprimé, le balisage précédent modifie l’URL qui est lancée vers la méthode d’extraction du contrôleur ajoutée dans les sections suivantes.

Ajouter une classe de modèle

Un modèle est un ensemble de classes qui représentent les données gérées par l’application. Le modèle pour cette application est une classe TodoItem unique.

  • Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet. Sélectionnez Ajouter > un nouveau dossier. Nommez le dossier Models .

  • Cliquez avec le bouton droit sur le Models dossier et sélectionnez Ajouter une > classe. Nommez la classe TodoItem et sélectionnez sur Ajouter.

  • Remplacez le code du modèle par ce qui suit :

namespace TodoApi.Models
{
    public class TodoItem
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

La propriété Id fonctionne comme la clé unique dans une base de données relationnelle.

Les classes de modèle peuvent se trouver n’importe où dans le projet, mais le Models dossier est utilisé par Convention.

Ajouter un contexte de base de données

Le contexte de base de données est la classe principale qui coordonne les fonctionnalités d’Entity Framework pour un modèle de données. Cette classe est créée en dérivant de la classe Microsoft.EntityFrameworkCore.DbContext.

Ajouter des packages NuGet

  • Dans le menu Outils, sélectionnez Gestionnaire de package NuGet > Gérer les packages NuGet pour la solution.
  • Sélectionnez l’onglet Parcourir , puis entrez Microsoft.EntityFrameworkCore.InMemory dans la zone de recherche.
  • Sélectionnez Microsoft.EntityFrameworkCore.InMemory dans le volet gauche.
  • activez la case à cocher Project dans le volet droit, puis sélectionnez installer.

Gestionnaire de package NuGet

Ajouter le contexte de base de données TodoContext

  • Cliquez avec le bouton droit sur le Models dossier et sélectionnez Ajouter une > classe. Nommez la classe TodoContext et cliquez sur Ajouter.
  • Entrez le code suivant :

    using Microsoft.EntityFrameworkCore;
    
    namespace TodoApi.Models
    {
        public class TodoContext : DbContext
        {
            public TodoContext(DbContextOptions<TodoContext> options)
                : base(options)
            {
            }
    
            public DbSet<TodoItem> TodoItems { get; set; }
        }
    }
    

Inscrire le contexte de base de données

Dans ASP.NET Core, les services tels que le contexte de base de données doivent être inscrits auprès du conteneur d’injection de dépendances. Le conteneur fournit le service aux contrôleurs.

Mettez à jour Startup. cs avec le code suivant :

// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

namespace TodoApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddDbContext<TodoContext>(opt =>
                                               opt.UseInMemoryDatabase("TodoList"));
            //services.AddSwaggerGen(c =>
            //{
            //    c.SwaggerDoc("v1", new OpenApiInfo { Title = "TodoApi", Version = "v1" });
            //});
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                //app.UseSwagger();
                //app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TodoApi v1"));
            }

            app.UseHttpsRedirection();
            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

Le code précédent :

  • Supprime les appels Swagger.
  • Supprime les déclarations using inutilisées.
  • Ajoute le contexte de base de données au conteneur d’injection de dépendances.
  • Spécifie que le contexte de base de données utilise une base de données en mémoire.

Générer automatiquement des modèles pour un contrôleur

  • Cliquez avec le bouton droit sur le dossier Contrôleurs.

  • Sélectionnez Ajouter > un nouvel élément de génération de modèles automatique.

  • Sélectionnez Contrôleur d’API avec actions, utilisant Entity Framework, puis Ajouter.

  • Dans la boîte de dialogue Contrôleur d’API avec actions, utilisant Entity Framework :

    • Sélectionnez TodoItem (TodoApi. Models ) dans la classe de modèle.
    • Sélectionnez TodoContext (TodoApi. Models ) dans la classe de contexte de données.
    • Sélectionnez Ajouter.

Le code généré :

  • Marque la classe avec l' [ApiController] attribut. Cet attribut indique que le contrôleur répond aux requêtes de l’API web. Pour plus d’informations sur les comportements spécifiques que permet l’attribut, consultez Créer des API web avec ASP.NET Core.
  • Utilise l’injection de dépendances pour injecter le contexte de base de données (TodoContext) dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.

les modèles de ASP.NET Core pour :

  • Les contrôleurs avec des vues sont inclus [action] dans le modèle de routage.
  • Les contrôleurs d’API n’incluent pas [action] dans le modèle de routage.

Lorsque le [action] jeton n’est pas dans le modèle de routage, le nom de l' action est exclu de l’itinéraire. Autrement dit, le nom de la méthode associée à l’action n’est pas utilisé dans l’itinéraire correspondant.

Mettre à jour la méthode de création de PostTodoItem

Mettez à jour l’instruction return dans la PostTodoItem pour utiliser l’opérateur nameof :

// POST: api/TodoItems
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
    _context.TodoItems.Add(todoItem);
    await _context.SaveChangesAsync();

    //return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
    return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}

Le code précédent est une méthode HTTP Après, comme indiqué par l' [HttpPost] attribut. La méthode obtient la valeur de la tâche dans le corps de la requête HTTP.

Pour plus d’informations, consultez Routage par attributs avec des attributs Http[Verbe].

La méthode CreatedAtAction :

  • Retourne un code d’état HTTP 201 en cas de réussite. HTTP 201 est la réponse standard d’une méthode HTTP POST qui crée une ressource sur le serveur.
  • Ajoute un en-tête Location à la réponse. L’en-tête Location spécifie l’URI de l’élément d’action qui vient d’être créé. Pour plus d’informations, consultez la section 10.2.2 201 Created.
  • Fait référence à l’action GetTodoItem pour créer l’URI Location de l’en-tête. Le mot clé nameof C# est utilisé pour éviter de coder en dur le nom de l’action dans l’appel CreatedAtAction.

Installer Postman

Ce tutoriel utilise Postman pour tester l’API web.

  • Installer le poste
  • Démarrez l’application web.
  • Démarrez Postman.
  • Désactivez la vérification du certificat SSL.
    • à partir de Paramètres de fichier > (onglet général ), désactivez la vérification de certificat SSL.

      Avertissement

      Réactivez la vérification du certificat SSL après avoir testé le contrôleur.

Tester PostTodoItem avec Postman

  • Créez une requête.

  • Affectez POST à la méthode HTTP.

  • Définissez l’URI sur https://localhost:<port>/api/todoitems . Par exemple : https://localhost:5001/api/todoitems.

  • Sélectionnez l’onglet Corps .

  • Sélectionnez la case d’option raw (données brutes).

  • Définissez le type sur JSON (application/json).

  • Dans le corps de la demande, entrez la syntaxe JSON d’une tâche :

    {
      "name":"walk dog",
      "isComplete":true
    }
    
  • Sélectionnez Envoyer.

    Postman avec requête de création

Tester l’URI de l’en-tête d’emplacement

L’URI d’en-tête d’emplacement peut être testé dans le navigateur. Copiez et collez l’URI d’en-tête d’emplacement dans le navigateur.

Pour effectuer un test dans le poster :

  • Sélectionnez l’onglet Headers (En-têtes) dans le volet Response (Réponse).

  • Copiez la valeur d’en-tête Location (Emplacement) :

    Onglet Headers de la console Postman

  • Affectez GET à la méthode HTTP.

  • Définissez l’URI sur https://localhost:<port>/api/todoitems/1 . Par exemple : https://localhost:5001/api/todoitems/1.

  • Sélectionnez Envoyer.

Examiner les méthodes GET

Deux points de terminaison d’extraction sont implémentés :

  • GET /api/todoitems
  • GET /api/todoitems/{id}

Testez l’application en appelant les deux points de terminaison à partir d’un navigateur ou de Postman. Par exemple :

  • https://localhost:5001/api/todoitems
  • https://localhost:5001/api/todoitems/1

Une réponse semblable à la suivante est produite par l’appel à GetTodoItems :

[
  {
    "id": 1,
    "name": "Item1",
    "isComplete": false
  }
]

Tester Get avec Postman

  • Créez une requête.
  • Définissez la méthode HTTP sur GET.
  • Définissez l’URI de la demande sur https://localhost:<port>/api/todoitems . Par exemple : https://localhost:5001/api/todoitems.
  • Définissez l’affichage à deux volets dans Postman.
  • Sélectionnez Envoyer.

Cette application utilise une base de données en mémoire. Si l’application est arrêtée et démarrée, la requête GET précédente ne retourne aucune donnée. Si aucune donnée n’est retournée, publiez (POST) les données dans l’application.

Routage et chemins d’URL

L' [HttpGet] attribut désigne une méthode qui répond à une requête http. Le chemin d’URL pour chaque méthode est construit comme suit :

  • Partez de la chaîne de modèle dans l’attribut Route du contrôleur :

    [Route("api/[controller]")]
    [ApiController]
    public class TodoItemsController : ControllerBase
    {
        private readonly TodoContext _context;
    
        public TodoItemsController(TodoContext context)
        {
            _context = context;
        }
    
  • Remplacez [controller] par le nom du contrôleur qui, par convention, est le nom de la classe du contrôleur sans le suffixe « Controller ». Pour cet exemple, le nom de la classe du contrôleur étant TodoItems Controller, le nom du contrôleur est « TodoItems ». Le routage d’ASP.NET Core ne respecte pas la casse.

  • Si l’attribut [HttpGet] a un modèle de route (par exemple, [HttpGet("products")]), ajoutez-le au chemin. Cet exemple n’utilise pas de modèle. Pour plus d’informations, consultez Routage par attributs avec des attributs Http[Verbe].

Dans la méthode GetTodoItem suivante, "{id}" est une variable d’espace réservé pour l’identificateur unique de la tâche. Lorsque GetTodoItem est appelé, la valeur de "{id}" dans l’URL est fournie à la méthode dans son id paramètre.

// GET: api/TodoItems/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

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

    return todoItem;
}

Valeurs retournées

Le type de retour des GetTodoItems GetTodoItem méthodes et est ActionResult <T> type. ASP.NET Core sérialise automatiquement l’objet en JSON et écrit le JSON dans le corps du message de réponse. Le code de réponse pour ce type de retour est 200 OK, en supposant qu’il n’existe aucune exception non gérée. Les exceptions non gérées sont converties en erreurs 5xx.

Les types de retour ActionResult peuvent représenter une large plage de codes d’état HTTP. Par exemple, GetTodoItem peut retourner deux valeurs d’état différentes :

  • Si aucun élément ne correspond à l’ID demandé, la méthode retourne un code d’erreur d' état 404 NotFound .
  • Sinon, la méthode retourne 200 avec un corps de réponse JSON. Le retour de item entraîne une réponse HTTP 200.

Méthode PutTodoItem

Examinez la méthode PutTodoItem :

// PUT: api/TodoItems/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
    if (id != todoItem.Id)
    {
        return BadRequest();
    }

    _context.Entry(todoItem).State = EntityState.Modified;

    try
    {
        await _context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!TodoItemExists(id))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }

    return NoContent();
}

PutTodoItem est similaire à PostTodoItem, à la différence près qu’il utilise HTTP PUT. La réponse est 204 (aucun contenu). D’après la spécification HTTP, une requête PUT nécessite que le client envoie toute l’entité mise à jour, et pas seulement les changements. Pour prendre en charge les mises à jour partielles, utilisez HTTP PATCH.

Si vous obtenez une erreur en appelant PutTodoItem, appelez GET pour vérifier que la base de données contient un élément.

Tester la méthode PutTodoItem

Cet exemple utilise une base de données en mémoire qui doit être initialisée chaque fois que l’application est démarrée. La base de données doit contenir un élément avant que vous ne passiez un appel PUT. Appelez obtenir pour vous assurer qu’il y a un élément dans la base de données avant d’effectuer un appel PUT.

Mettez à jour l’élément de tâche dont l’ID est égal à 1 et affectez-lui comme nom "feed fish" :

  {
    "Id":1,
    "name":"feed fish",
    "isComplete":true
  }

L’image suivante montre la mise à jour Postman :

Console Postman montrant la réponse 204 (Pas de contenu)

Méthode DeleteTodoItem

Examinez la méthode DeleteTodoItem :

// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);
    if (todoItem == null)
    {
        return NotFound();
    }

    _context.TodoItems.Remove(todoItem);
    await _context.SaveChangesAsync();

    return NoContent();
}

Tester la méthode DeleteTodoItem

Utilisez Postman pour supprimer une tâche :

  • Définissez la méthode sur DELETE.
  • Définissez l’URI de l’objet à supprimer (par exemple https://localhost:5001/api/todoitems/1 ).
  • Sélectionnez Envoyer.

Empêcher la post-validation

Actuellement, l’exemple d’application expose l' TodoItem objet entier. En général, les applications de production limitent les données entrées et retournées à l’aide d’un sous-ensemble du modèle. Il existe plusieurs raisons à cela, et la sécurité est essentielle. Le sous-ensemble d’un modèle est généralement appelé un objet Transfert de données (DTO), un modèle d’entrée ou un modèle de vue. Le DTO est utilisé dans cet article.

Un DTO peut être utilisé pour :

  • Empêcher la survalidation.
  • Masquer les propriétés que les clients ne sont pas censés afficher.
  • Omettez certaines propriétés afin de réduire la taille de la charge utile.
  • Aplatir les graphiques d’objets qui contiennent des objets imbriqués. Les graphiques d’objets aplatis peuvent être plus pratiques pour les clients.

Pour illustrer l’approche DTO, mettez à jour la TodoItem classe pour inclure un champ secret :

namespace TodoApi.Models
{
    public class TodoItem
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
        public string Secret { get; set; }
    }
}

Le champ secret doit être masqué à partir de cette application, mais une application administrative peut choisir de l’exposer.

Vérifiez que vous pouvez poster et recevoir le champ secret.

Créer un modèle DTO :

public class TodoItemDTO
{
    public long Id { get; set; }
    public string Name { get; set; }
    public bool IsComplete { get; set; }
}

Mettez à jour le TodoItemsController pour utiliser TodoItemDTO :

// GET: api/TodoItems
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
{
    return await _context.TodoItems
        .Select(x => ItemToDTO(x))
        .ToListAsync();
}

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

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

    return ItemToDTO(todoItem);
}

[HttpPut("{id}")]
public async Task<IActionResult> UpdateTodoItem(long id, TodoItemDTO todoItemDTO)
{
    if (id != todoItemDTO.Id)
    {
        return BadRequest();
    }

    var todoItem = await _context.TodoItems.FindAsync(id);
    if (todoItem == null)
    {
        return NotFound();
    }

    todoItem.Name = todoItemDTO.Name;
    todoItem.IsComplete = todoItemDTO.IsComplete;

    try
    {
        await _context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
    {
        return NotFound();
    }

    return NoContent();
}

[HttpPost]
public async Task<ActionResult<TodoItemDTO>> CreateTodoItem(TodoItemDTO todoItemDTO)
{
    var todoItem = new TodoItem
    {
        IsComplete = todoItemDTO.IsComplete,
        Name = todoItemDTO.Name
    };

    _context.TodoItems.Add(todoItem);
    await _context.SaveChangesAsync();

    return CreatedAtAction(
        nameof(GetTodoItem),
        new { id = todoItem.Id },
        ItemToDTO(todoItem));
}

[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

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

    _context.TodoItems.Remove(todoItem);
    await _context.SaveChangesAsync();

    return NoContent();
}

private bool TodoItemExists(long id) =>
     _context.TodoItems.Any(e => e.Id == id);

private static TodoItemDTO ItemToDTO(TodoItem todoItem) =>
    new TodoItemDTO
    {
        Id = todoItem.Id,
        Name = todoItem.Name,
        IsComplete = todoItem.IsComplete
    };

Vérifiez que vous ne pouvez pas poster ou recevoir le champ secret.

Appelez l’API web avec JavaScript

consultez didacticiel : appeler une API web ASP.NET Core avec JavaScript.

Dans ce tutoriel, vous allez apprendre à :

  • Créer un projet d’API web.
  • Ajouter une classe de modèle et un contexte de base de données.
  • Générer automatiquement des modèles pour un contrôleur avec des méthodes CRUD.
  • Configurer le routage, les chemins d’URL et les valeurs de retour.
  • Appeler l’API web avec Postman

À la fin, vous disposez d’une API web qui peut gérer des tâches stockées dans une base de données.

Vue d’ensemble

Ce didacticiel crée l’API suivante :

API Description Corps de la demande Response body
GET /api/todoitems Obtenir toutes les tâches None Tableau de tâches
GET /api/todoitems/{id} Obtenir un élément par ID None Tâche
POST /api/todoitems Ajouter un nouvel élément Tâche Tâche
PUT /api/todoitems/{id} Mettre à jour un élément existant   Tâche None
DELETE /api/todoitems/{id}     Supprimer un élément    None None

Le diagramme suivant illustre la conception de l’application.

Le client est représenté par une zone située à gauche. Il envoie une demande et reçoit une réponse de l’application, représentée par une zone dessinée à droite. Dans la zone de l’application, trois zones représentent le contrôleur, le modèle et la couche d’accès aux données. La requête provient du contrôleur de l’application, et les opérations de lecture/écriture se produisent entre le contrôleur et la couche d’accès aux données. Le modèle est sérialisé et retourné au client dans la réponse.

Prérequis

Créer un projet web

  • dans le menu fichier , sélectionnez nouveau > Project.
  • Sélectionnez le modèle Application web ASP.NET Core et cliquez sur Suivant.
  • Nommez le projet TodoApi et cliquez sur Créer.
  • dans la boîte de dialogue créer une Application Web ASP.NET Core , vérifiez que .net Core et ASP.NET Core 3,1 sont sélectionnés. Sélectionnez le modèle API et cliquez sur Créer.

Boîte de dialogue de nouveau projet dans VS

Tester l’API

Le modèle de projet crée une API WeatherForecast. Appelez la méthode Get à partir d’un navigateur pour tester l’application.

Appuyez sur Ctrl+F5 pour exécuter l’application. Visual Studio lance un navigateur et accède à https://localhost:<port>/WeatherForecast, où <port> est un numéro de port choisi de manière aléatoire.

Si une boîte de dialogue apparaît vous demandant si vous devez approuver le certificat IIS Express, sélectionnez Oui. Dans la boîte de dialogue Avertissement de sécurité qui s’affiche ensuite, sélectionnez Oui.

Un code JSON similaire au suivant est retourné :

[
    {
        "date": "2019-07-16T19:04:05.7257911-06:00",
        "temperatureC": 52,
        "temperatureF": 125,
        "summary": "Mild"
    },
    {
        "date": "2019-07-17T19:04:05.7258461-06:00",
        "temperatureC": 36,
        "temperatureF": 96,
        "summary": "Warm"
    },
    {
        "date": "2019-07-18T19:04:05.7258467-06:00",
        "temperatureC": 39,
        "temperatureF": 102,
        "summary": "Cool"
    },
    {
        "date": "2019-07-19T19:04:05.7258471-06:00",
        "temperatureC": 10,
        "temperatureF": 49,
        "summary": "Bracing"
    },
    {
        "date": "2019-07-20T19:04:05.7258474-06:00",
        "temperatureC": -1,
        "temperatureF": 31,
        "summary": "Chilly"
    }
]

Ajouter une classe de modèle

Un modèle est un ensemble de classes qui représentent les données gérées par l’application. Le modèle pour cette application est une classe TodoItem unique.

  • Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet. Sélectionnez Ajouter > un nouveau dossier. Nommez le dossier Models .

  • Cliquez avec le bouton droit sur le Models dossier et sélectionnez Ajouter une > classe. Nommez la classe TodoItem et sélectionnez sur Ajouter.

  • Remplacez le code du modèle par le code suivant :

public class TodoItem
{
    public long Id { get; set; }
    public string Name { get; set; }
    public bool IsComplete { get; set; }
}

La propriété Id fonctionne comme la clé unique dans une base de données relationnelle.

Les classes de modèle peuvent se trouver n’importe où dans le projet, mais le Models dossier est utilisé par Convention.

Ajouter un contexte de base de données

Le contexte de base de données est la classe principale qui coordonne les fonctionnalités d’Entity Framework pour un modèle de données. Cette classe est créée en dérivant de la classe Microsoft.EntityFrameworkCore.DbContext.

Ajouter des packages NuGet

  • Dans le menu Outils, sélectionnez Gestionnaire de package NuGet > Gérer les packages NuGet pour la solution.
  • Sélectionnez l’onglet Parcourir , puis entrez Microsoft. EntityFrameworkCore. InMemory dans la zone de recherche.
  • Dans le volet gauche, sélectionnez Microsoft. EntityFrameworkCore. InMemory .
  • activez la case à cocher Project dans le volet droit, puis sélectionnez installer.

Gestionnaire de package NuGet

Ajouter le contexte de base de données TodoContext

  • Cliquez avec le bouton droit sur le Models dossier et sélectionnez Ajouter une > classe. Nommez la classe TodoContext et cliquez sur Ajouter.
  • Entrez le code suivant :

    using Microsoft.EntityFrameworkCore;
    
    namespace TodoApi.Models
    {
        public class TodoContext : DbContext
        {
            public TodoContext(DbContextOptions<TodoContext> options)
                : base(options)
            {
            }
    
            public DbSet<TodoItem> TodoItems { get; set; }
        }
    }
    

Inscrire le contexte de base de données

Dans ASP.NET Core, les services tels que le contexte de base de données doivent être inscrits auprès du conteneur d’injection de dépendances. Le conteneur fournit le service aux contrôleurs.

Mettez à jour Startup.cs avec le code en surbrillance suivant :

// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

namespace TodoApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TodoContext>(opt =>
               opt.UseInMemoryDatabase("TodoList"));
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

Le code précédent :

  • Supprime les déclarations using inutilisées.
  • Ajoute le contexte de base de données au conteneur d’injection de dépendances.
  • Spécifie que le contexte de base de données utilise une base de données en mémoire.

Générer automatiquement des modèles pour un contrôleur

  • Cliquez avec le bouton droit sur le dossier Contrôleurs.

  • Sélectionnez Ajouter > un nouvel élément de génération de modèles automatique.

  • Sélectionnez Contrôleur d’API avec actions, utilisant Entity Framework, puis Ajouter.

  • Dans la boîte de dialogue Contrôleur d’API avec actions, utilisant Entity Framework :

    • Sélectionnez TodoItem (TodoApi. Models ) dans la classe de modèle.
    • Sélectionnez TodoContext (TodoApi. Models ) dans la classe de contexte de données.
    • Sélectionnez Ajouter.

Le code généré :

  • Marque la classe avec l' [ApiController] attribut. Cet attribut indique que le contrôleur répond aux requêtes de l’API web. Pour plus d’informations sur les comportements spécifiques que permet l’attribut, consultez Créer des API web avec ASP.NET Core.
  • Utilise l’injection de dépendances pour injecter le contexte de base de données (TodoContext) dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.

les modèles de ASP.NET Core pour :

  • Les contrôleurs avec des vues sont inclus [action] dans le modèle de routage.
  • Les contrôleurs d’API n’incluent pas [action] dans le modèle de routage.

Lorsque le [action] jeton n’est pas dans le modèle de routage, le nom de l' action est exclu de l’itinéraire. Autrement dit, le nom de la méthode associée à l’action n’est pas utilisé dans l’itinéraire correspondant.

Examiner la méthode de création de PostTodoItem

Remplacez l’instruction return dans PostTodoItem pour utiliser l’opérateur nameof :

// POST: api/TodoItems
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
    _context.TodoItems.Add(todoItem);
    await _context.SaveChangesAsync();

    //return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
    return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}

Le code précédent est une méthode HTTP Après, comme indiqué par l' [HttpPost] attribut. La méthode obtient la valeur de la tâche dans le corps de la requête HTTP.

Pour plus d’informations, consultez Routage par attributs avec des attributs Http[Verbe].

La méthode CreatedAtAction :

  • Retourne un code d’état HTTP 201 en cas de réussite. HTTP 201 est la réponse standard d’une méthode HTTP POST qui crée une ressource sur le serveur.
  • Ajoute un en-tête Location à la réponse. L’en-tête Location spécifie l’URI de l’élément d’action qui vient d’être créé. Pour plus d’informations, consultez la section 10.2.2 201 Created.
  • Fait référence à l’action GetTodoItem pour créer l’URI Location de l’en-tête. Le mot clé nameof C# est utilisé pour éviter de coder en dur le nom de l’action dans l’appel CreatedAtAction.

Installer Postman

Ce tutoriel utilise Postman pour tester l’API web.

  • Installer le poste
  • Démarrez l’application web.
  • Démarrez Postman.
  • Désactivez la vérification du certificat SSL.
    • à partir de Paramètres de fichier > (onglet général ), désactivez la vérification de certificat SSL.

      Avertissement

      Réactivez la vérification du certificat SSL après avoir testé le contrôleur.

Tester PostTodoItem avec Postman

  • Créez une requête.

  • Affectez POST à la méthode HTTP.

  • Définissez l’URI sur https://localhost:<port>/api/todoitems . Par exemple : https://localhost:5001/api/todoitems.

  • Sélectionnez l’onglet Corps .

  • Sélectionnez la case d’option raw (données brutes).

  • Définissez le type sur JSON (application/json).

  • Dans le corps de la demande, entrez la syntaxe JSON d’une tâche :

    {
      "name":"walk dog",
      "isComplete":true
    }
    
  • Sélectionnez Envoyer.

    Postman avec requête de création

Tester l’URI d’en-tête d’emplacement avec le poster

  • Sélectionnez l’onglet Headers (En-têtes) dans le volet Response (Réponse).

  • Copiez la valeur d’en-tête Location (Emplacement) :

    Onglet Headers de la console Postman

  • Affectez GET à la méthode HTTP.

  • Définissez l’URI sur https://localhost:<port>/api/todoitems/1 . Par exemple : https://localhost:5001/api/todoitems/1.

  • Sélectionnez Envoyer.

Examiner les méthodes GET

Ces méthodes implémentent deux points de terminaison GET :

  • GET /api/todoitems
  • GET /api/todoitems/{id}

Testez l’application en appelant les deux points de terminaison à partir d’un navigateur ou de Postman. Par exemple :

  • https://localhost:5001/api/todoitems
  • https://localhost:5001/api/todoitems/1

Une réponse semblable à la suivante est produite par l’appel à GetTodoItems :

[
  {
    "id": 1,
    "name": "Item1",
    "isComplete": false
  }
]

Tester Get avec Postman

  • Créez une requête.
  • Définissez la méthode HTTP sur GET.
  • Définissez l’URI de la demande sur https://localhost:<port>/api/todoitems . Par exemple : https://localhost:5001/api/todoitems.
  • Définissez l’affichage à deux volets dans Postman.
  • Sélectionnez Envoyer.

Cette application utilise une base de données en mémoire. Si l’application est arrêtée et démarrée, la requête GET précédente ne retourne aucune donnée. Si aucune donnée n’est retournée, publiez (POST) les données dans l’application.

Routage et chemins d’URL

L' [HttpGet] attribut désigne une méthode qui répond à une requête http. Le chemin d’URL pour chaque méthode est construit comme suit :

  • Partez de la chaîne de modèle dans l’attribut Route du contrôleur :

    [Route("api/[controller]")]
    [ApiController]
    public class TodoItemsController : ControllerBase
    {
        private readonly TodoContext _context;
    
        public TodoItemsController(TodoContext context)
        {
            _context = context;
        }
    
  • Remplacez [controller] par le nom du contrôleur qui, par convention, est le nom de la classe du contrôleur sans le suffixe « Controller ». Pour cet exemple, le nom de la classe du contrôleur étant TodoItems Controller, le nom du contrôleur est « TodoItems ». Le routage d’ASP.NET Core ne respecte pas la casse.

  • Si l’attribut [HttpGet] a un modèle de route (par exemple, [HttpGet("products")]), ajoutez-le au chemin. Cet exemple n’utilise pas de modèle. Pour plus d’informations, consultez Routage par attributs avec des attributs Http[Verbe].

Dans la méthode GetTodoItem suivante, "{id}" est une variable d’espace réservé pour l’identificateur unique de la tâche. Lorsque GetTodoItem est appelé, la valeur de "{id}" dans l’URL est fournie à la méthode dans son id paramètre.

// GET: api/TodoItems/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

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

    return todoItem;
}

Valeurs retournées

Le type de retour des GetTodoItems GetTodoItem méthodes et est ActionResult <T> type. ASP.NET Core sérialise automatiquement l’objet en JSON et écrit le JSON dans le corps du message de réponse. Le code de réponse pour ce type de retour est 200, en supposant qu’il n’existe pas d’exception non gérée. Les exceptions non gérées sont converties en erreurs 5xx.

Les types de retour ActionResult peuvent représenter une large plage de codes d’état HTTP. Par exemple, GetTodoItem peut retourner deux valeurs d’état différentes :

  • Si aucun élément ne correspond à l’ID demandé, la méthode retourne un NotFound code d’erreur 404.
  • Sinon, la méthode retourne 200 avec un corps de réponse JSON. Le retour de item entraîne une réponse HTTP 200.

Méthode PutTodoItem

Examinez la méthode PutTodoItem :

// PUT: api/TodoItems/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
    if (id != todoItem.Id)
    {
        return BadRequest();
    }

    _context.Entry(todoItem).State = EntityState.Modified;

    try
    {
        await _context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!TodoItemExists(id))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }

    return NoContent();
}

PutTodoItem est similaire à PostTodoItem, à la différence près qu’il utilise HTTP PUT. La réponse est 204 (aucun contenu). D’après la spécification HTTP, une requête PUT nécessite que le client envoie toute l’entité mise à jour, et pas seulement les changements. Pour prendre en charge les mises à jour partielles, utilisez HTTP PATCH.

Si vous obtenez une erreur en appelant PutTodoItem, appelez GET pour vérifier que la base de données contient un élément.

Tester la méthode PutTodoItem

Cet exemple utilise une base de données en mémoire qui doit être initialisée chaque fois que l’application est démarrée. La base de données doit contenir un élément avant que vous ne passiez un appel PUT. Appelez obtenir pour vous assurer qu’il y a un élément dans la base de données avant d’effectuer un appel PUT.

Mettez à jour l’élément de tâche dont l’ID est égal à 1 et affectez-lui le nom « flux de poisson » :

  {
    "id":1,
    "name":"feed fish",
    "isComplete":true
  }

L’image suivante montre la mise à jour Postman :

Console Postman montrant la réponse 204 (Pas de contenu)

Méthode DeleteTodoItem

Examinez la méthode DeleteTodoItem :

// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<ActionResult<TodoItem>> DeleteTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);
    if (todoItem == null)
    {
        return NotFound();
    }

    _context.TodoItems.Remove(todoItem);
    await _context.SaveChangesAsync();

    return todoItem;
}

Tester la méthode DeleteTodoItem

Utilisez Postman pour supprimer une tâche :

  • Définissez la méthode sur DELETE.
  • Définissez l’URI de l’objet à supprimer (par exemple https://localhost:5001/api/todoitems/1 ).
  • Sélectionnez Envoyer.

Empêcher la post-validation

Actuellement, l’exemple d’application expose l' TodoItem objet entier. En général, les applications de production limitent les données entrées et retournées à l’aide d’un sous-ensemble du modèle. Il existe plusieurs raisons à cela, et la sécurité est essentielle. Le sous-ensemble d’un modèle est généralement appelé un objet Transfert de données (DTO), un modèle d’entrée ou un modèle de vue. Le DTO est utilisé dans cet article.

Un DTO peut être utilisé pour :

  • Empêcher la survalidation.
  • Masquer les propriétés que les clients ne sont pas censés afficher.
  • Omettez certaines propriétés afin de réduire la taille de la charge utile.
  • Aplatir les graphiques d’objets qui contiennent des objets imbriqués. Les graphiques d’objets aplatis peuvent être plus pratiques pour les clients.

Pour illustrer l’approche DTO, mettez à jour la TodoItem classe pour inclure un champ secret :

public class TodoItem
{
    public long Id { get; set; }
    public string Name { get; set; }
    public bool IsComplete { get; set; }
    public string Secret { get; set; }
}

Le champ secret doit être masqué à partir de cette application, mais une application administrative peut choisir de l’exposer.

Vérifiez que vous pouvez poster et recevoir le champ secret.

Créer un modèle DTO :

public class TodoItemDTO
{
    public long Id { get; set; }
    public string Name { get; set; }
    public bool IsComplete { get; set; }
}

Mettez à jour le TodoItemsController pour utiliser TodoItemDTO :

    [HttpGet]
    public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
    {
        return await _context.TodoItems
            .Select(x => ItemToDTO(x))
            .ToListAsync();
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
    {
        var todoItem = await _context.TodoItems.FindAsync(id);

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

        return ItemToDTO(todoItem);
    }

    [HttpPut("{id}")]
    public async Task<IActionResult> UpdateTodoItem(long id, TodoItemDTO todoItemDTO)
    {
        if (id != todoItemDTO.Id)
        {
            return BadRequest();
        }

        var todoItem = await _context.TodoItems.FindAsync(id);
        if (todoItem == null)
        {
            return NotFound();
        }

        todoItem.Name = todoItemDTO.Name;
        todoItem.IsComplete = todoItemDTO.IsComplete;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
        {
            return NotFound();
        }

        return NoContent();
    }

    [HttpPost]
    public async Task<ActionResult<TodoItemDTO>> CreateTodoItem(TodoItemDTO todoItemDTO)
    {
        var todoItem = new TodoItem
        {
            IsComplete = todoItemDTO.IsComplete,
            Name = todoItemDTO.Name
        };

        _context.TodoItems.Add(todoItem);
        await _context.SaveChangesAsync();

        return CreatedAtAction(
            nameof(GetTodoItem),
            new { id = todoItem.Id },
            ItemToDTO(todoItem));
    }

    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteTodoItem(long id)
    {
        var todoItem = await _context.TodoItems.FindAsync(id);

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

        _context.TodoItems.Remove(todoItem);
        await _context.SaveChangesAsync();

        return NoContent();
    }

    private bool TodoItemExists(long id) =>
         _context.TodoItems.Any(e => e.Id == id);

    private static TodoItemDTO ItemToDTO(TodoItem todoItem) =>
        new TodoItemDTO
        {
            Id = todoItem.Id,
            Name = todoItem.Name,
            IsComplete = todoItem.IsComplete
        };       
}

Vérifiez que vous ne pouvez pas poster ou recevoir le champ secret.

Appelez l’API web avec JavaScript

consultez didacticiel : appeler une API web ASP.NET Core avec JavaScript.

Dans ce tutoriel, vous allez apprendre à :

  • Créer un projet d’API web.
  • Ajouter une classe de modèle et un contexte de base de données.
  • Ajouter un contrôleur
  • Ajouter les méthodes CRUD
  • Configurer le routage et les chemins d’URL
  • Spécifier des valeurs de retour
  • Appeler l’API web avec Postman
  • Appeler l’API web avec JavaScript.

À la fin, vous disposez d’une API web qui peut gérer des tâches stockées dans une base de données relationnelle.

Vue d’ensemble 2,1

Ce didacticiel crée l’API suivante :

API Description Corps de la demande Response body
Obtient/API/todoitems Obtenir toutes les tâches None Tableau de tâches
Obtient/API/todoitems/{ID} Obtenir un élément par ID None Tâche
POSTER/API/todoitems Ajouter un nouvel élément Tâche Tâche
PUT/API/todoitems/{ID} Mettre à jour un élément existant   Tâche None
SUPPRIMER/API/todoitems/{ID}    Supprimer un élément    None None

Le diagramme suivant illustre la conception de l’application.

Le client est représenté par une zone située à gauche. Il envoie une demande et reçoit une réponse de l’application, représentée par une zone dessinée à droite. Dans la zone de l’application, trois zones représentent le contrôleur, le modèle et la couche d’accès aux données. La requête provient du contrôleur de l’application, et les opérations de lecture/écriture se produisent entre le contrôleur et la couche d’accès aux données. Le modèle est sérialisé et retourné au client dans la réponse.

Conditions préalables 2,1

Avertissement

Si vous utilisez Visual Studio 2017, consultez le problème no 3124 dotnet/sdk pour plus d’informations sur les versions du Kit SDK .NET Core qui ne fonctionnent pas avec Visual Studio.

Créer un projet Web 2,1

  • dans le menu fichier , sélectionnez nouveau > Project.
  • Sélectionnez le modèle Application web ASP.NET Core et cliquez sur Suivant.
  • Nommez le projet TodoApi et cliquez sur Créer.
  • Dans la boîte de dialogue Créer une application web ASP.NET Core, vérifiez que .NET Core et ASP.NET Core 2.2 sont sélectionnés. Sélectionnez le modèle API et cliquez sur Créer. Ne sélectionnez pas****Activer la prise en charge de Docker.

Boîte de dialogue de nouveau projet dans VS

Tester l’API 2,1

Le modèle de projet crée une API values. Appelez la méthode Get à partir d’un navigateur pour tester l’application.

Appuyez sur Ctrl+F5 pour exécuter l’application. Visual Studio lance un navigateur et accède à https://localhost:<port>/api/values, où <port> est un numéro de port choisi de manière aléatoire.

Si une boîte de dialogue apparaît vous demandant si vous devez approuver le certificat IIS Express, sélectionnez Oui. Dans la boîte de dialogue Avertissement de sécurité qui s’affiche ensuite, sélectionnez Oui.

Le code JSON suivant est retourné :

["value1","value2"]

Ajouter une classe de modèle 2,1

Un modèle est un ensemble de classes qui représentent les données gérées par l’application. Le modèle pour cette application est une classe TodoItem unique.

  • Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet. Sélectionnez Ajouter > un nouveau dossier. Nommez le dossier Models .

  • Cliquez avec le bouton droit sur le Models dossier et sélectionnez Ajouter une > classe. Nommez la classe TodoItem et sélectionnez sur Ajouter.

  • Remplacez le code du modèle par le code suivant :

namespace TodoApi.Models
{
    public class TodoItem
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

La propriété Id fonctionne comme la clé unique dans une base de données relationnelle.

Les classes de modèle peuvent se trouver n’importe où dans le projet, mais le Models dossier est utilisé par Convention.

Ajouter un contexte de base de données 2,1

Le contexte de base de données est la classe principale qui coordonne les fonctionnalités d’Entity Framework pour un modèle de données. Cette classe est créée en dérivant de la classe Microsoft.EntityFrameworkCore.DbContext.

  • Cliquez avec le bouton droit sur le Models dossier et sélectionnez Ajouter une > classe. Nommez la classe TodoContext et cliquez sur Ajouter.
  • Remplacez le code du modèle par le code suivant :

    using Microsoft.EntityFrameworkCore;
    
    namespace TodoApi.Models
    {
        public class TodoContext : DbContext
        {
            public TodoContext(DbContextOptions<TodoContext> options)
                : base(options)
            {
            }
    
            public DbSet<TodoItem> TodoItems { get; set; }
        }
    }
    

Inscrire le contexte de base de données 2,1

Dans ASP.NET Core, les services tels que le contexte de base de données doivent être inscrits auprès du conteneur d’injection de dépendances. Le conteneur fournit le service aux contrôleurs.

Mettez à jour Startup.cs avec le code en surbrillance suivant :

// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using TodoApi.Models;

namespace TodoApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the 
        //container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TodoContext>(opt =>
                opt.UseInMemoryDatabase("TodoList"));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP 
        //request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for 
                // production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }
}

Le code précédent :

  • Supprime les déclarations using inutilisées.
  • Ajoute le contexte de base de données au conteneur d’injection de dépendances.
  • Spécifie que le contexte de base de données utilise une base de données en mémoire.

Ajouter un contrôleur 2,1

  • Cliquez avec le bouton droit sur le dossier Contrôleurs.

  • Sélectionnez Ajouter > un nouvel élément.

  • Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez le modèle Classe de contrôleur d’API.

  • Nommez la classe TodoController et sélectionnez Ajouter.

    Boîte de dialogue Ajouter un nouvel élément avec contrôleur dans la zone de recherche et le contrôleur des API web sélectionné

  • Remplacez le code du modèle par le code suivant :

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using TodoApi.Models;
    
    namespace TodoApi.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class TodoController : ControllerBase
        {
            private readonly TodoContext _context;
    
            public TodoController(TodoContext context)
            {
                _context = context;
    
                if (_context.TodoItems.Count() == 0)
                {
                    // Create a new TodoItem if collection is empty,
                    // which means you can't delete all TodoItems.
                    _context.TodoItems.Add(new TodoItem { Name = "Item1" });
                    _context.SaveChanges();
                }
            }
        }
    }
    

Le code précédent :

  • Définit une classe de contrôleur d’API sans méthodes.
  • Marque la classe avec l' [ApiController] attribut. Cet attribut indique que le contrôleur répond aux requêtes de l’API web. Pour plus d’informations sur les comportements spécifiques que permet l’attribut, consultez Créer des API web avec ASP.NET Core.
  • Utilise l’injection de dépendances pour injecter le contexte de base de données (TodoContext) dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
  • Ajoute un élément nommé Item1 à la base de données si celle-ci est vide. Ce code se trouvant dans le constructeur, il s’exécute chaque fois qu’une nouvelle requête HTTP existe. Si vous supprimez tous les éléments, le constructeur recrée Item1 au prochain appel d’une méthode d’API. Ainsi, il peut vous sembler à tort que la suppression n’a pas fonctionné.

Ajouter des méthodes de récupération 2,1

Pour fournir une API qui récupère les tâches, ajoutez les méthodes suivantes à la classe TodoController :

// GET: api/Todo
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
{
    return await _context.TodoItems.ToListAsync();
}

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

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

    return todoItem;
}

Ces méthodes implémentent deux points de terminaison GET :

  • GET /api/todo
  • GET /api/todo/{id}

Arrêtez l’application si elle est toujours en cours d’exécution. Ensuite, réexécutez-la pour inclure les dernières modifications.

Testez l’application en appelant les deux points de terminaison à partir d’un navigateur. Par exemple :

  • https://localhost:<port>/api/todo
  • https://localhost:<port>/api/todo/1

La réponse HTTP suivante est générée par l’appel à GetTodoItems :

[
  {
    "id": 1,
    "name": "Item1",
    "isComplete": false
  }
]

Routage et chemins d’URL 2,1

L' [HttpGet] attribut désigne une méthode qui répond à une requête http. Le chemin d’URL pour chaque méthode est construit comme suit :

  • Partez de la chaîne de modèle dans l’attribut Route du contrôleur :

    namespace TodoApi.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class TodoController : ControllerBase
        {
            private readonly TodoContext _context;
    
  • Remplacez [controller] par le nom du contrôleur qui, par convention, est le nom de la classe du contrôleur sans le suffixe « Controller ». Pour cet exemple, le nom de classe du contrôleur étant Todo Controller, le nom du contrôleur est « todo ». Le routage d’ASP.NET Core ne respecte pas la casse.

  • Si l’attribut [HttpGet] a un modèle de route (par exemple, [HttpGet("products")]), ajoutez-le au chemin. Cet exemple n’utilise pas de modèle. Pour plus d’informations, consultez Routage par attributs avec des attributs Http[Verbe].

Dans la méthode GetTodoItem suivante, "{id}" est une variable d’espace réservé pour l’identificateur unique de la tâche. Quand GetTodoItem est appelée, la valeur de "{id}" dans l’URL est fournie à la méthode dans son paramètre id.

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

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

    return todoItem;
}

Valeurs de retour 2,1

Le type de retour des GetTodoItems GetTodoItem méthodes et est ActionResult <T> type. ASP.NET Core sérialise automatiquement l’objet en JSON et écrit le JSON dans le corps du message de réponse. Le code de réponse pour ce type de retour est 200, en supposant qu’il n’existe pas d’exception non gérée. Les exceptions non gérées sont converties en erreurs 5xx.

Les types de retour ActionResult peuvent représenter une large plage de codes d’état HTTP. Par exemple, GetTodoItem peut retourner deux valeurs d’état différentes :

  • Si aucun élément ne correspond à l’ID demandé, la méthode retourne un NotFound code d’erreur 404.
  • Sinon, la méthode retourne 200 avec un corps de réponse JSON. Le retour de item entraîne une réponse HTTP 200.

Tester la méthode GetTodoItems 2,1

Ce tutoriel utilise Postman pour tester l’API web.

  • Installer Postman
  • Démarrez l’application web.
  • Démarrez Postman.
  • Désactivez la vérification du certificat SSL.
  • à partir de Paramètres de fichier > (onglet général ), désactivez la vérification de certificat SSL.

Avertissement

Réactivez la vérification du certificat SSL après avoir testé le contrôleur.

  • Créez une requête.
    • Définissez la méthode HTTP sur GET.
    • Définissez l’URI de la demande sur https://localhost:<port>/api/todo . Par exemple : https://localhost:5001/api/todo.
  • Définissez l’affichage à deux volets dans Postman.
  • Sélectionnez Envoyer.

Postman avec requête Get

Ajouter une méthode de création 2,1

Ajoutez la méthode PostTodoItem suivante à Controllers/TodoController.cs :

// POST: api/Todo
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem item)
{
    _context.TodoItems.Add(item);
    await _context.SaveChangesAsync();

    return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item);
}

Le code précédent est une méthode HTTP Après, comme indiqué par l' [HttpPost] attribut. La méthode obtient la valeur de la tâche dans le corps de la requête HTTP.

La méthode CreatedAtAction :

  • Retourne un code d’état HTTP 201 en cas de réussite. HTTP 201 est la réponse standard d’une méthode HTTP POST qui crée une ressource sur le serveur.

  • Ajoute un en-tête Location à la réponse. L’en-tête Location spécifie l’URI de l’élément d’action qui vient d’être créé. Pour plus d’informations, consultez la section 10.2.2 201 Created.

  • Fait référence à l’action GetTodoItem pour créer l’URI Location de l’en-tête. Le mot clé nameof C# est utilisé pour éviter de coder en dur le nom de l’action dans l’appel CreatedAtAction.

    // GET: api/Todo/5
    [HttpGet("{id}")]
    public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
    {
        var todoItem = await _context.TodoItems.FindAsync(id);
    
        if (todoItem == null)
        {
            return NotFound();
        }
    
        return todoItem;
    }
    

Tester la méthode PostTodoItem 2,1

  • Créez le projet.

  • Dans Postman, définissez la méthode HTTP sur POST.

  • Définissez l’URI sur https://localhost:<port>/api/Todo . Par exemple : https://localhost:5001/api/Todo.

  • Sélectionnez l’onglet Corps .

  • Sélectionnez la case d’option raw (données brutes).

  • Définissez le type sur JSON (application/json).

  • Dans le corps de la demande, entrez la syntaxe JSON d’une tâche :

    {
      "name":"walk dog",
      "isComplete":true
    }
    
  • Sélectionnez Envoyer.

    Postman avec requête de création

    Si vous obtenez une erreur 405 Méthode non autorisée, il est probable que le projet n’ait pas été compilé après l’ajout de la méthode PostTodoItem.

Tester l’URI d’en-tête d’emplacement 2,1

  • Sélectionnez l’onglet Headers (En-têtes) dans le volet Response (Réponse).

  • Copiez la valeur d’en-tête Location (Emplacement) :

    Onglet Headers de la console Postman

  • Définissez la méthode sur GET.

  • Définissez l’URI sur https://localhost:<port>/api/todoitems/2 . Par exemple : https://localhost:5001/api/todoitems/2.

  • Sélectionnez Envoyer.

Ajouter une méthode PutTodoItem 2,1

Ajoutez la méthode PutTodoItem suivante :

// PUT: api/Todo/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem item)
{
    if (id != item.Id)
    {
        return BadRequest();
    }

    _context.Entry(item).State = EntityState.Modified;
    await _context.SaveChangesAsync();

    return NoContent();
}

PutTodoItem est similaire à PostTodoItem, à la différence près qu’il utilise HTTP PUT. La réponse est 204 (aucun contenu). D’après la spécification HTTP, une requête PUT nécessite que le client envoie toute l’entité mise à jour, et pas seulement les changements. Pour prendre en charge les mises à jour partielles, utilisez HTTP PATCH.

Si vous obtenez une erreur en appelant PutTodoItem, appelez GET pour vérifier que la base de données contient un élément.

Tester la méthode PutTodoItem 2,1

Cet exemple utilise une base de données en mémoire qui doit être initialisée chaque fois que l’application est démarrée. La base de données doit contenir un élément avant que vous ne passiez un appel PUT. Appelez obtenir pour vous assurer qu’il y a un élément dans la base de données avant d’effectuer un appel PUT.

Mettez à jour l’élément de tâche dont l’ID est égal à 1 et affectez-lui le nom « flux de poisson » :

  {
    "id":1,
    "name":"feed fish",
    "isComplete":true
  }

L’image suivante montre la mise à jour Postman :

Console Postman montrant la réponse 204 (Pas de contenu)

Ajouter une méthode DeleteTodoItem 2,1

Ajoutez la méthode DeleteTodoItem suivante :

// DELETE: api/Todo/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

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

    _context.TodoItems.Remove(todoItem);
    await _context.SaveChangesAsync();

    return NoContent();
}

La réponse DeleteTodoItem est 204 (Pas de contenu).

Tester la méthode DeleteTodoItem 2,1

Utilisez Postman pour supprimer une tâche :

  • Définissez la méthode sur DELETE.
  • Définissez l’URI de l’objet à supprimer (par exemple, https://localhost:5001/api/todo/1 ).
  • Sélectionnez Envoyer.

L’exemple d’application vous permet de supprimer tous les éléments. Toutefois, quand le dernier élément est supprimé, un autre est créé par le constructeur de classe de modèle au prochain appel de l’API.

Appeler l’API Web avec JavaScript 2,1

Dans cette section, une page HTML qui utilise JavaScript pour appeler l’API web est ajoutée. jQuery lance la demande. JavaScript met à jour la page avec les détails de la réponse de l’API Web.

Configurez l’application pour traiter les fichiers statiques et activer le mappage de fichier par défaut en mettant à jour Startup.cs avec le code en surbrillance suivant :

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        // The default HSTS value is 30 days. You may want to change this for 
        // production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }

    app.UseDefaultFiles();
    app.UseStaticFiles();
    app.UseHttpsRedirection();
    app.UseMvc();
}

Créez un dossier wwwroot dans le répertoire du projet.

Ajoutez un fichier HTML nommé index.html au répertoire wwwroot. Remplacez son contenu par le balisage suivant :

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>To-do CRUD</title>
    <style>
        input[type='submit'], button, [aria-label] {
            cursor: pointer;
        }

        #spoiler {
            display: none;
        }

        table {
            font-family: Arial, sans-serif;
            border: 1px solid;
            border-collapse: collapse;
        }

        th {
            background-color: #0066CC;
            color: white;
        }

        td {
            border: 1px solid;
            padding: 5px;
        }
    </style>
</head>
<body>
    <h1>To-do CRUD</h1>
    <h3>Add</h3>
    <form action="javascript:void(0);" method="POST" onsubmit="addItem()">
        <input type="text" id="add-name" placeholder="New to-do">
        <input type="submit" value="Add">
    </form>

    <div id="spoiler">
        <h3>Edit</h3>
        <form class="my-form">
            <input type="hidden" id="edit-id">
            <input type="checkbox" id="edit-isComplete">
            <input type="text" id="edit-name">
            <input type="submit" value="Save">
            <a onclick="closeInput()" aria-label="Close">&#10006;</a>
        </form>
    </div>

    <p id="counter"></p>

    <table>
        <tr>
            <th>Is Complete</th>
            <th>Name</th>
            <th></th>
            <th></th>
        </tr>
        <tbody id="todos"></tbody>
    </table>

    <script src="https://code.jquery.com/jquery-3.3.1.min.js"
            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
            crossorigin="anonymous"></script>
    <script src="site.js"></script>
</body>
</html>

Ajoutez un fichier JavaScript nommé site.js au répertoire wwwroot. Remplacez le contenu par le code suivant :

const uri = "api/todo";
let todos = null;
function getCount(data) {
  const el = $("#counter");
  let name = "to-do";
  if (data) {
    if (data > 1) {
      name = "to-dos";
    }
    el.text(data + " " + name);
  } else {
    el.text("No " + name);
  }
}

$(document).ready(function() {
  getData();
});

function getData() {
  $.ajax({
    type: "GET",
    url: uri,
    cache: false,
    success: function(data) {
      const tBody = $("#todos");

      $(tBody).empty();

      getCount(data.length);

      $.each(data, function(key, item) {
        const tr = $("<tr></tr>")
          .append(
            $("<td></td>").append(
              $("<input/>", {
                type: "checkbox",
                disabled: true,
                checked: item.isComplete
              })
            )
          )
          .append($("<td></td>").text(item.name))
          .append(
            $("<td></td>").append(
              $("<button>Edit</button>").on("click", function() {
                editItem(item.id);
              })
            )
          )
          .append(
            $("<td></td>").append(
              $("<button>Delete</button>").on("click", function() {
                deleteItem(item.id);
              })
            )
          );

        tr.appendTo(tBody);
      });

      todos = data;
    }
  });
}

function addItem() {
  const item = {
    name: $("#add-name").val(),
    isComplete: false
  };

  $.ajax({
    type: "POST",
    accepts: "application/json",
    url: uri,
    contentType: "application/json",
    data: JSON.stringify(item),
    error: function(jqXHR, textStatus, errorThrown) {
      alert("Something went wrong!");
    },
    success: function(result) {
      getData();
      $("#add-name").val("");
    }
  });
}

function deleteItem(id) {
  $.ajax({
    url: uri + "/" + id,
    type: "DELETE",
    success: function(result) {
      getData();
    }
  });
}

function editItem(id) {
  $.each(todos, function(key, item) {
    if (item.id === id) {
      $("#edit-name").val(item.name);
      $("#edit-id").val(item.id);
      $("#edit-isComplete")[0].checked = item.isComplete;
    }
  });
  $("#spoiler").css({ display: "block" });
}

$(".my-form").on("submit", function() {
  const item = {
    name: $("#edit-name").val(),
    isComplete: $("#edit-isComplete").is(":checked"),
    id: $("#edit-id").val()
  };

  $.ajax({
    url: uri + "/" + $("#edit-id").val(),
    type: "PUT",
    accepts: "application/json",
    contentType: "application/json",
    data: JSON.stringify(item),
    success: function(result) {
      getData();
    }
  });

  closeInput();
  return false;
});

function closeInput() {
  $("#spoiler").css({ display: "none" });
}

Vous devrez peut-être changer les paramètres de lancement du projet ASP.NET Core pour tester la page HTML localement :

  • Ouvrez Properties\launchSettings.json.
  • Supprimez la launchUrl propriété pour forcer l’ouverture de l’application à index.html — fichier par défaut du projet.

Cet exemple appelle toutes les méthodes CRUD de l’API web. Les explications suivantes traitent des appels à l’API.

Obtenir la liste des éléments de tâche 2,1

jQuery envoie une requête HTTP obtenir à l’API Web, qui retourne JSON représentant un tableau d’éléments de tâche. La fonction de rappel success est appelée si la requête réussit. Dans le rappel, le DOM est mis à jour avec les informations des tâches.

$(document).ready(function() {
  getData();
});

function getData() {
  $.ajax({
    type: "GET",
    url: uri,
    cache: false,
    success: function(data) {
      const tBody = $("#todos");

      $(tBody).empty();

      getCount(data.length);

      $.each(data, function(key, item) {
        const tr = $("<tr></tr>")
          .append(
            $("<td></td>").append(
              $("<input/>", {
                type: "checkbox",
                disabled: true,
                checked: item.isComplete
              })
            )
          )
          .append($("<td></td>").text(item.name))
          .append(
            $("<td></td>").append(
              $("<button>Edit</button>").on("click", function() {
                editItem(item.id);
              })
            )
          )
          .append(
            $("<td></td>").append(
              $("<button>Delete</button>").on("click", function() {
                deleteItem(item.id);
              })
            )
          );

        tr.appendTo(tBody);
      });

      todos = data;
    }
  });
}

Ajouter un élément de tâche 2,1

jQuery envoie une requête HTTP POSTÉRIEURe avec l’élément de tâche dans le corps de la demande. Les options accepts et contentType sont définies avec la valeur application/json pour spécifier le type de média qui est reçu et envoyé. La tâche est convertie au format JSON à l’aide de JSON.stringify. Quand l’API retourne un code d’état de réussite, la fonction getData est appelée pour mettre à jour la table HTML.

function addItem() {
  const item = {
    name: $("#add-name").val(),
    isComplete: false
  };

  $.ajax({
    type: "POST",
    accepts: "application/json",
    url: uri,
    contentType: "application/json",
    data: JSON.stringify(item),
    error: function(jqXHR, textStatus, errorThrown) {
      alert("Something went wrong!");
    },
    success: function(result) {
      getData();
      $("#add-name").val("");
    }
  });
}

Mettre à jour un élément de tâche 2,1

La mise à jour d’une tâche est similaire à l’ajout d’une tâche. L’identificateur unique de la tâche est ajouté à l’url et le type est PUT.

$.ajax({
  url: uri + "/" + $("#edit-id").val(),
  type: "PUT",
  accepts: "application/json",
  contentType: "application/json",
  data: JSON.stringify(item),
  success: function(result) {
    getData();
  }
});

Supprimer un élément de tâche 2,1

Pour supprimer une tâche, vous devez définir le type sur l’appel AJAX avec la valeur DELETE et spécifier l’identificateur unique de l’élément dans l’URL.

$.ajax({
  url: uri + "/" + id,
  type: "DELETE",
  success: function(result) {
    getData();
  }
});

Ajouter la prise en charge de l’authentification à une API Web 2,1

ASP.NET Core Identity Ajoute la fonctionnalité de connexion de l’interface utilisateur à ASP.NET Core applications Web. Pour sécuriser les API Web et la commande SPAs, utilisez l’une des méthodes suivantes :

Identity4 est un Framework OpenID Connect et OAuth 2,0 pour ASP.NET Core. Identity4 active les fonctionnalités de sécurité suivantes :

  • Authentification en tant que service (AaaS)
  • Authentification unique (SSO) sur plusieurs types d’applications
  • Contrôle d’accès pour les API
  • Passerelle de Fédération

Pour plus d’informations, consultez Bienvenue dans Identity 4.

Ressources supplémentaires 2,1

Affichez ou téléchargez l’exemple de code de ce tutoriel. Consultez Guide pratique pour télécharger.

Pour plus d’informations, consultez les ressources suivantes :