Dela via


Självstudie: Skapa ett webb-API med ASP.NET Core

Not

Det här är inte den senaste versionen av den här artikeln. För den nuvarande utgåvan, se den .NET 9-versionen av den här artikeln.

Varning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. Den aktuella versionen finns i den .NET 9-versionen av den här artikeln.

Viktig

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

För den aktuella versionen, se .NET 9-versionen av den här artikeln .

Av Rick Anderson och Kirk Larkin

I den här självstudien lär du dig grunderna i att skapa ett kontrollantbaserat webb-API som använder en databas. En annan metod för att skapa API:er i ASP.NET Core är att skapa minimala API:er. Hjälp med att välja mellan minimala API:er och kontrollantbaserade API:er finns i översikten över API:er. En självstudiekurs om hur du skapar ett minimalt API finns i Självstudie: Skapa ett minimalt API med ASP.NET Core.

Överblick

I den här handledningen skapas följande API:

API Beskrivning Begärandetext Svarskropp
GET /api/todoitems Hämta alla to-do objekt Ingen Matris med to-do objekt
GET /api/todoitems/{id} Hämta ett objekt efter ID Ingen Att göra-objekt
POST /api/todoitems Lägga till ett nytt objekt Att göra-objekt Att göra-objekt
PUT /api/todoitems/{id} Uppdatera ett befintligt objekt Att göra-objekt Ingen
DELETE /api/todoitems/{id}     Ta bort ett objekt Ingen Ingen

Följande diagram visar appens design.

Klienten representeras av en ruta till vänster. Den skickar en begäran och får ett svar från programmet, en ruta som ritats till höger. I programrutan representerar tre rutor kontrollanten, modellen och dataåtkomstskiktet. Begäran kommer till programmets kontrollant och läs-/skrivåtgärder sker mellan kontrollanten och dataåtkomstlagret. Modellen serialiseras och returneras till klienten i svaret.

Förutsättningar

Skapa ett webbprojekt

  • På menyn Arkiv väljer du Nytt>Projekt.
  • Ange Web-API i sökrutan.
  • Välj mallen ASP.NET Core Web API och välj Nästa.
  • I dialogrutan Konfigurera det nya projektetnamnger du projektet TodoApi och väljer Nästa.
  • I dialogrutan Ytterligare information:
    • Bekräfta att Framework är .NET 8.0 (support på lång sikt).
    • Bekräfta kryssrutan för Använd kontrollanter (avmarkera om du vill använda minimala API:er) är markerad.
    • Bekräfta att kryssrutan för Aktivera OpenAPI-stöd är markerad.
    • Välj Skapa.

Lägga till ett NuGet-paket

Ett NuGet-paket måste läggas till för att stödja databasen som används i den här guiden.

  • På menyn Verktyg väljer du NuGet Package Manager > Manage NuGet Packages for Solution.
  • Välj fliken Bläddra.
  • Ange Microsoft.EntityFrameworkCore.InMemory i sökrutan och välj sedan Microsoft.EntityFrameworkCore.InMemory.
  • Markera kryssrutan Project i panelen till höger och välj sedan Install.

Not

Mer information om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paketArbetsflöde för paketförbrukning (NuGet-dokumentation). Bekräfta rätt paketversioner på NuGet.org.

Testa projektet

Projektmallen skapar ett WeatherForecast API med stöd för Swagger.

Tryck på Ctrl+F5 för att köra utan felsökningsprogrammet.

Visual Studio visar följande dialogruta när ett projekt ännu inte har konfigurerats för att använda SSL:

Det här projektet är konfigurerat att använda SSL. För att undvika SSL-varningar i webbläsaren kan du välja att lita på det självsignerade certifikat som IIS Express har genererat. Vill du lita på IIS Express SSL-certifikatet?

Välj Ja om du litar på IIS Express SSL-certifikatet.

Följande dialogruta visas:

säkerhetsvarningsdialog

Välj Ja om du samtycker till att lita på utvecklingscertifikatet.

Information om hur du kan lita på webbläsaren Firefox finns i Firefox SEC_ERROR_INADEQUATE_KEY_USAGE certifikatfel.

Visual Studio startar standardwebbläsaren och navigerar till https://localhost:<port>/swagger/index.html, där <port> är ett slumpmässigt valt portnummer som anges när projektet skapas.

Swagger-sida /swagger/index.html visas. Välj GET>Prova>Kör. Sidan visar:

  • Kommandot Curl för att testa WeatherForecast-API:et.
  • URL:en för att testa WeatherForecast-API:et.
  • Svarskoden, brödtexten och rubrikerna.
  • En listruta med medietyper och exempelvärdet och schemat.

Om Swagger-sidan inte visas kan du läsa detta GitHub-ärende.

Swagger används för att generera användbar dokumentation och hjälpsidor för webb-API:er. I den här handledningen används Swagger för att testa appen. Mer information om Swagger finns i ASP.NET Core web API-dokumentation med Swagger/OpenAPI.

Kopiera och klistra in url:en för begäran i webbläsaren: https://localhost:<port>/weatherforecast

JSON som liknar följande exempel returneras:

[
    {
        "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"
    }
]

Lägga till en modellklass

En modell är en uppsättning klasser som representerar de data som appen hanterar. Modellen för den här appen är klassen TodoItem.

  • Högerklicka på projektet i Solution Explorer. Välj Lägg till>ny mapp. Ge mappen namnet Models.
  • Högerklicka på mappen Models och välj Lägg till>klass. Ge klassen namnet TodoItem och välj Lägg till.
  • Ersätt mallkoden med följande:
namespace TodoApi.Models;

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

Egenskapen Id fungerar som den unika nyckeln i en relationsdatabas.

Modellklasser kan placeras var som helst i projektet, men mappen Models används enligt konvention.

Lägga till en databaskontext

Den databaskontexten är huvudklassen som samordnar Entity Framework-funktioner för en datamodell. Den här klassen skapas genom att härledas från klassen Microsoft.EntityFrameworkCore.DbContext.

  • Högerklicka på mappen Models och välj Lägg till>klass. Ge klassen namnet TodoContext och klicka på Lägg till.
  • Ange följande kod:

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

Registrera databaskontexten

I ASP.NET Core måste tjänster som DB-kontexten registreras i beroendeinjektion (DI)-containern. Containern tillhandahåller tjänsten till kontrollanter.

Uppdatera Program.cs med följande markerade kod:

using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
    opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Föregående kod:

  • Lägger till using direktiv.
  • Lägger till databaskontexten i DI-containern.
  • Anger att databaskontexten ska använda en minnesintern databas.

Generera en styrenhet

  • Högerklicka på mappen Controllers.

  • Välj Lägg till>New Scaffolded Item.

  • Välj API-kontrollant med åtgärder, använd Entity Frameworkoch välj sedan Lägg till.

  • I dialogrutan Lägg till API-kontroller med åtgärder, använd Entity Framework:

    • Välj TodoItem (TodoApi.Models) i klassen Model.
    • Välj TodoContext (TodoApi.Models) i den datakontextklassen .
    • Välj Lägg till.

    Om scaffolding-åtgärden misslyckas väljer du Lägg till för att prova scaffolding igen.

Den genererade koden:

  • Markerar klassen med attributet [ApiController]. Det här attributet anger att kontrollanten svarar på webb-API-begäranden. Information om specifika beteenden som attributet aktiverar finns i Skapa webb-API:er med ASP.NET Core.
  • Använder DI för att mata in databaskontexten (TodoContext) i kontrollanten. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.

ASP.NET Core-mallarna för:

  • Kontrollanter med vyer innehåller [action] i routningsmallen.
  • API-kontrollanter inkluderar inte [action] i routningsmallen.

När [action] token inte finns i routningsmallen inkluderas inte -åtgärden namn (metodnamn) i slutpunkten. Åtgärdens associerade metodnamn används alltså inte i matchande väg.

Uppdatera metoden PostTodoItem create

Uppdatera retursatsen i PostTodoItem för att använda namn på operatorn:

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

Föregående kod är en HTTP POST metod, vilket anges av attributet [HttpPost]. Metoden hämtar värdet för TodoItem från brödtexten i HTTP-begäran.

För mer information, se Attributdirigering med Http[Verb]-attribut.

Metoden CreatedAtAction:

  • Returnerar en HTTP 201-statuskod om den lyckas. HTTP 201 är standardsvaret för en HTTP POST-metod som skapar en ny resurs på servern.
  • Lägger till en Location-rubrik i svaret. Location-huvudet anger URI- för det nyligen skapade to-do objektet. Mer information finns i 10.2.2 201 Skapad.
  • Refererar till åtgärden GetTodoItem för att skapa Location-huvudets URI. Nyckelordet C# nameof används för att undvika hårdkodning av åtgärdsnamnet i CreatedAtAction-anropet.

Test PostTodoItem

  • Kör appen genom att trycka på Ctrl+F5.

  • I swagger-webbläsarfönstret väljer du POST /api/TodoItemsoch väljer sedan Prova.

  • Uppdatera JSON i inmatningsfönstret Begärandetext. Till exempel

    {
      "name": "walk dog",
      "isComplete": true
    }
    
  • Välj Kör

    Swagger POST

Testa platsrubrikens URI

I föregående POST visar Swagger-användargränssnittet platsrubriken under Svarsrubriker. Till exempel location: https://localhost:7260/api/TodoItems/1. Platsrubriken visar URI:n för den skapade resursen.

Så här testar du platsrubriken:

  • I swagger-webbläsarfönstret väljer du GET /api/TodoItems/{id}och väljer sedan Prova.

  • Ange 1 i inmatningsfältet för id och välj sedan Kör.

    Swagger GET

Granska GET-metoderna

Två GET-slutpunkter implementeras:

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

Föregående avsnitt visade ett exempel på vägen /api/todoitems/{id}.

Följ anvisningarna i POST för att lägga till en annan att-göra-post och testa sedan /api/todoitems vägen med hjälp av Swagger.

Den här appen använder en minnesintern databas. Om appen stoppas och startas returnerar inte den föregående GET-begäran några data. Om ingen data returneras, ska POST data till appen.

Routnings- och URL-sökvägar

Attributet [HttpGet] anger en metod som svarar på en HTTP GET begäran. URL-sökvägen för varje metod konstrueras på följande sätt:

  • Börja med mallsträngen i kontrollantens Route-attribut:

    [Route("api/[controller]")]
    [ApiController]
    public class TodoItemsController : ControllerBase
    
  • Ersätt [controller] med namnet på kontrollanten, som enligt konventionen är kontrollantens klassnamn minus suffixet "Controller". I det här exemplet är kontrollantklassnamnet TodoItemsController, så kontrollantnamnet är "TodoItems". ASP.NET Core routning är skiftlägesokänsligt.

  • Om attributet [HttpGet] har en routningsmall (till exempel [HttpGet("products")]) lägger du till den i sökvägen. Det här exemplet använder ingen mall. För mer information, se Attributdirigering med Http[Verb]-attribut.

I följande GetTodoItem-metod är "{id}" en platshållarvariabel för den unika identifieraren för det to-do objektet. När GetTodoItem anropas anges värdet för "{id}" i URL:en till metoden i parametern id.

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

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

    return todoItem;
}

Returnera värden

Returtypen för metoderna GetTodoItems och GetTodoItem är ActionResult<T> typ. ASP.NET Core serialiserar automatiskt objektet till JSON- och skriver JSON i brödtexten i svarsmeddelandet. Svarskoden för den här returtypen är 200 OK, förutsatt att det inte finns några ohanterade undantag. Ohanterade undantag översätts till 5xx-fel.

ActionResult returtyper kan representera ett brett utbud av HTTP-statuskoder. Till exempel kan GetTodoItem returnera två olika statusvärden:

  • Om inget objekt matchar det begärda ID:t returnerar metoden en 404-statusNotFound felkod.
  • Annars returnerar metoden 200 med en JSON-svarstext. Om du returnerar item resulterar det i ett HTTP 200 svar.

PutTodoItem-metoden

Granska metoden PutTodoItem:

[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 liknar PostTodoItem, förutom att den använder HTTP PUT. Svaret är 204 (inget innehåll). Enligt HTTP-specifikationen kräver en PUT begäran att klienten skickar hela den uppdaterade entiteten, inte bara ändringarna. Om du vill ha stöd för partiella uppdateringar använder du HTTP PATCH-.

Testa metoden PutTodoItem

Det här exemplet använder en minnesintern databas som måste initieras varje gång appen startas. Det måste finnas ett objekt i databasen innan du gör ett PUT-anrop. Anropa GET för att se till att det finns ett objekt i databasen innan du gör ett PUT-anrop.

Använd knappen PUT med swagger-användargränssnittet för att uppdatera TodoItem som har ID = 1 och ange dess namn till "feed fish". Observera att svaret är HTTP 204 No Content.

Metoden DeleteTodoItem

Granska metoden DeleteTodoItem:

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

Testa metoden DeleteTodoItem

Använd Swagger-användargränssnittet för att ta bort TodoItem som har ID = 1. Observera att svaret är HTTP 204 No Content.

Testa med andra verktyg

Det finns många andra verktyg som kan användas för att testa webb-API:er, till exempel:

Mer information finns i:

Förhindra överpublicering

För närvarande exponerar exempelappen hela TodoItem objektet. Produktionsappar begränsar vanligtvis de data som matas in och returneras med hjälp av en delmängd av modellen. Det finns flera orsaker till detta, och säkerheten är viktig. Delmängden av en modell kallas vanligtvis för ett dataöverföringsobjekt (DTO), indatamodell eller vymodell. DTO- används i den här handledningen.

En DTO kan användas för att:

  • Förhindra överpublicering.
  • Dölj egenskaper som klienter inte ska visa.
  • Utelämna vissa egenskaper för att minska nyttolaststorleken.
  • Platta ut objektdiagram som innehåller kapslade objekt. Utplattade objektdiagram kan vara enklare för klienter.

Om du vill demonstrera DTO-metoden uppdaterar du klassen TodoItem så att den innehåller ett hemligt fält:

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

Det hemliga fältet måste vara dolt från den här appen, men en administrativ app kan välja att exponera det.

Kontrollera att du kan publicera och hämta det hemliga fältet.

Skapa en DTO-modell:

namespace TodoApi.Models;

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

Uppdatera TodoItemsController för att använda TodoItemDTO:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

namespace TodoApi.Controllers;

[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
    private readonly TodoContext _context;

    public TodoItemsController(TodoContext context)
    {
        _context = context;
    }

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

    // GET: api/TodoItems/5
    // <snippet_GetByID>
    [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);
    }
    // </snippet_GetByID>

    // PUT: api/TodoItems/5
    // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
    // <snippet_Update>
    [HttpPut("{id}")]
    public async Task<IActionResult> PutTodoItem(long id, TodoItemDTO todoDTO)
    {
        if (id != todoDTO.Id)
        {
            return BadRequest();
        }

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

        todoItem.Name = todoDTO.Name;
        todoItem.IsComplete = todoDTO.IsComplete;

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

        return NoContent();
    }
    // </snippet_Update>

    // POST: api/TodoItems
    // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
    // <snippet_Create>
    [HttpPost]
    public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO todoDTO)
    {
        var todoItem = new TodoItem
        {
            IsComplete = todoDTO.IsComplete,
            Name = todoDTO.Name
        };

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

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

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

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

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

Kontrollera att du inte kan publicera eller hämta det hemliga fältet.

Anropa webb-API:et med JavaScript

Se Självstudie: Anropa ett ASP.NET Core-webb-API med JavaScript.

Videoserie för webb-API

Se Video om: Ny serie för nybörjare om web API:er.

Mönster för företagswebbappar

Vägledning om hur du skapar en tillförlitlig, säker, högpresterande, testbar och skalbar ASP.NET Core-app finns i Enterprise-webbappmönster. En komplett exempelwebbapp av produktionskvalitet som implementerar mönstren är tillgänglig.

Lägga till autentiseringsstöd i ett webb-API

ASP.NET Core Identity lägger till inloggningsfunktioner för användargränssnitt (UI) i ASP.NET Core-webbappar. Om du vill skydda webb-API:er och SPA:er använder du något av följande:

Duende Identity Server är ett OpenID Connect- och OAuth 2.0-ramverk för ASP.NET Core. Duende Identity Server aktiverar följande säkerhetsfunktioner:

  • Autentisering som en tjänst (AaaS)
  • Enkel inloggning/av(SSO) över flera programtyper
  • Åtkomstkontroll för API:er
  • Federation Gateway

Viktig

Duende Software kan kräva att du betalar en licensavgift för produktionsanvändning av Duende Identity Server. Mer information finns i Migrera från ASP.NET Core 5.0 till 6.0.

Mer information finns i Duende Identity Server-dokumentationen (Duende Software-webbplatsen).

Publicera till Azure

Information om hur du distribuerar till Azure finns i Snabbstart: Distribuera en ASP.NET webbapp.

Ytterligare resurser

Visa eller ladda ner exempelkod för den här handledningen. Se hur du laddar ned.

Mer information finns i följande resurser:

I den här självstudien lär du dig grunderna i att skapa ett kontrollantbaserat webb-API som använder en databas. En annan metod för att skapa API:er i ASP.NET Core är att skapa minimala API:er. Hjälp med att välja mellan minimala API:er och kontrollantbaserade API:er finns i översikten över API:er. En självstudiekurs om hur du skapar ett minimalt API finns i Självstudie: Skapa ett minimalt API med ASP.NET Core.

Överblick

I den här handledningen skapas följande API:

API Beskrivning Begärandetext Svarstext
GET /api/todoitems Hämta alla to-do objekt Ingen Matris med to-do objekt
GET /api/todoitems/{id} Hämta ett objekt efter ID Ingen Att göra-objekt
POST /api/todoitems Lägga till ett nytt objekt Att göra-objekt Att göra-objekt
PUT /api/todoitems/{id} Uppdatera ett befintligt objekt Att göra-objekt Ingen
DELETE /api/todoitems/{id}     Ta bort ett objekt Ingen Ingen

Följande diagram visar appens design.

Klienten representeras av en ruta till vänster. Den skickar en begäran och får ett svar från programmet, en ruta som ritats till höger. I programrutan representerar tre rutor kontrollanten, modellen och dataåtkomstskiktet. Begäran kommer till programmets kontrollant och läs-/skrivåtgärder sker mellan kontrollanten och dataåtkomstlagret. Modellen serialiseras och returneras till klienten i svaret.

Förutsättningar

Skapa ett webbprojekt

  • På menyn Arkiv väljer du Nytt>Projekt.
  • Ange Web API i sökrutan.
  • Välj mallen ASP.NET Core Web API och välj Nästa.
  • I dialogrutan Konfigurera det nya projektetnamnger du projektet TodoApi och väljer Nästa.
  • I dialogrutan Ytterligare information:
    • Bekräfta att Framework- är .NET 8.0 (långsiktig support).
    • Bekräfta kryssrutan för Använd kontrollanter (avmarkera om du vill använda minimala API:er) är markerad.
    • Bekräfta att kryssrutan för Aktivera OpenAPI-stöd är markerad.
    • Välj Skapa.

Lägga till ett NuGet-paket

Ett NuGet-paket måste läggas till för att möjliggöra användningen av databasen som används i den här handledningen.

  • På menyn Verktyg väljer du NuGet Package Manager > Manage NuGet Packages for Solution.
  • Välj fliken Bläddra.
  • Ange Microsoft.EntityFrameworkCore.InMemory i sökrutan och välj sedan Microsoft.EntityFrameworkCore.InMemory.
  • Markera kryssrutan Project i den högra rutan och sedan välj Installera.

Notis

Mer information om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paketArbetsflöde för paketförbrukning (NuGet-dokumentation). Bekräfta rätt paketversioner på NuGet.org.

Testa projektet

Projektmallen skapar ett WeatherForecast API med stöd för Swagger.

Tryck på Ctrl+F5 för att köra utan felsökningsprogrammet.

Visual Studio visar följande dialogruta när ett projekt ännu inte har konfigurerats för att använda SSL:

Det här projektet är konfigurerat att använda SSL. För att undvika SSL-varningar i webbläsaren kan du välja att lita på det självsignerade certifikat som IIS Express har genererat. Vill du lita på IIS Express SSL-certifikatet?

Välj Ja om du litar på IIS Express SSL-certifikatet.

Följande dialogruta visas:

dialogrutan säkerhetsvarning

Välj Ja om du samtycker till att lita på utvecklingscertifikatet.

Information om hur du litar på Webbläsaren Firefox finns i Firefox SEC_ERROR_INADEQUATE_KEY_USAGE certifikatfel.

Visual Studio startar standardwebbläsaren och navigerar till https://localhost:<port>/swagger/index.html, där <port> är ett slumpmässigt valt portnummer som anges när projektet skapas.

Swagger-sidan /swagger/index.html visas. Välj GET>Prova>Kör. Sidan visar:

  • Kommandot Curl för att testa WeatherForecast-API:et.
  • URL:en för att testa WeatherForecast-API:et.
  • Svarskoden, brödtexten och rubrikerna.
  • En listruta med medietyper och exempelvärdet och schemat.

Om Swagger-sidan inte visas kan du läsa GitHub-problemet.

Swagger används för att generera användbar dokumentation och hjälpsidor för webb-API:er. I den här självstudien används Swagger för att testa appen. Mer information om Swagger finns i ASP.NET Core web API-dokumentation med Swagger/OpenAPI.

Kopiera och klistra in url:en för begäran i webbläsaren: https://localhost:<port>/weatherforecast

JSON som liknar följande exempel returneras:

[
    {
        "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"
    }
]

Lägga till en modellklass

En modell är en uppsättning klasser som representerar de data som appen hanterar. Modellen för den här appen är klassen TodoItem.

  • Högerklicka på projektet i Solution Explorer. Välj Lägg till>ny mapp. Ge mappen namnet Models.
  • Högerklicka på mappen Models och välj Lägg till>klass. Ge klassen namnet TodoItem och välj Lägg till.
  • Ersätt mallkoden med följande:
namespace TodoApi.Models;

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

Egenskapen Id fungerar som den unika nyckeln i en relationsdatabas.

Modellklasser kan placeras var som helst i projektet, men mappen Models används enligt konvention.

Lägga till en databaskontext

Den databaskontexten är huvudklassen som samordnar Entity Framework-funktioner för en datamodell. Den här klassen skapas genom att härledas från klassen Microsoft.EntityFrameworkCore.DbContext.

  • Högerklicka på mappen Models och välj Lägg till>klass. Ge klassen namnet TodoContext och klicka på Lägg till.
  • Ange följande kod:

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

Registrera databaskontexten

I ASP.NET Core måste tjänster, såsom en DB-kontext, registreras med en beroendeinjektion (DI) container. Containern tillhandahåller tjänsten till kontrollanter.

Uppdatera Program.cs med följande markerade kod:

using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
    opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Föregående kod:

  • Lägger till ett using-direktiv.
  • Lägger till databaskontexten i DI-containern.
  • Anger att databaskontexten ska använda en minnesintern databas.

Generera en grundstruktur för en styrenhet

  • Högerklicka på mappen Controllers.

  • Välj Lägg till>New Scaffolded Item.

  • Välj API-kontrollant med åtgärder, använd Entity Frameworkoch välj sedan Lägg till.

  • I dialogrutan Lägg till API-styrenhet med åtgärder, använder du Entity Framework-dialogrutan.

    • Välj TodoItem (TodoApi.Models) i klassen Model.
    • Välj TodoContext (TodoApi.Models) i Data context-klass.
    • Välj Lägg till.

    Om scaffolding-åtgärden misslyckas väljer du Lägg till för att prova att skapa en byggnadsställning en andra gång.

Den genererade koden:

  • Markerar klassen med attributet [ApiController]. Det här attributet anger att kontrollanten svarar på webb-API-begäranden. Information om specifika beteenden som attributet aktiverar finns i Skapa webb-API:er med ASP.NET Core.
  • Använder DI för att mata in databaskontexten (TodoContext) i kontrollanten. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.

ASP.NET Core-mallarna för:

  • Kontrollanter med vyer innehåller [action] i routningsmallen.
  • API-kontrollanter inkluderar inte [action] i routningsmallen.

När [action] token inte finns i routningsmallen inkluderas inte -åtgärden namn (metodnamn) i slutpunkten. Åtgärdens associerade metodnamn används alltså inte i matchande väg.

Uppdatera metoden PostTodoItem create

Uppdatera retursatsen i PostTodoItem för att använda namn på operatorn:

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

Föregående kod är en HTTP POST metod, vilket anges av attributet [HttpPost]. Metoden hämtar värdet för TodoItem från brödtexten i HTTP-begäran.

För mer information, se Attributdirigering med Http[Verb]-attribut.

Metoden CreatedAtAction:

  • Returnerar en HTTP 201-statuskod om den lyckas. HTTP 201 är standardsvaret för en HTTP POST-metod som skapar en ny resurs på servern.
  • Lägger till en Location-rubrik i svaret. Location-huvudet anger URI- för det nyligen skapade to-do objektet. Mer information finns i 10.2.2 201 Skapad.
  • Refererar till åtgärden GetTodoItem för att skapa Location-huvudets URI. Nyckelordet C# nameof används för att undvika hårdkodning av åtgärdsnamnet i CreatedAtAction-anropet.

Testa PostTodoItem

  • Kör appen genom att trycka på Ctrl+F5.

  • I swagger-webbläsarfönstret väljer du POST /api/TodoItemsoch väljer sedan Prova.

  • Uppdatera JSON i fönstret förfrågningskropp indatafältet. Till exempel

    {
      "name": "walk dog",
      "isComplete": true
    }
    
  • Välj Kör

    Swagger POST

Testa platsrubrikens URI

I föregående POST visar Swagger-användargränssnittet platsrubriken under Svarsrubriker. Till exempel location: https://localhost:7260/api/TodoItems/1. Platsrubriken visar URI:n för den skapade resursen.

Så här testar du platsrubriken:

  • I swagger-webbläsarfönstret väljer du GET /api/TodoItems/{id}och väljer sedan Prova.

  • Ange 1 i indatarutan id och välj därefter Kör.

    Swagger GET

Granska GET-metoderna

Två GET-slutpunkter implementeras:

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

Föregående avsnitt visade ett exempel på rutten /api/todoitems/{id}.

Följ anvisningarna i POST för att lägga till ett annat att göra-post och testa sedan /api/todoitems rutten med hjälp av Swagger.

Den här appen använder en minnesintern databas. Om appen stoppas och startas returnerar inte den föregående GET-begäran några data. Om inga data returneras, POST data till appen.

Routnings- och URL-sökvägar

Attributet [HttpGet] anger en metod som svarar på en HTTP GET begäran. URL-sökvägen för varje metod konstrueras på följande sätt:

  • Börja med mallsträngen i kontrollantens Route-attribut:

    [Route("api/[controller]")]
    [ApiController]
    public class TodoItemsController : ControllerBase
    
  • Ersätt [controller] med namnet på kontrollanten, som enligt konventionen är kontrollantens klassnamn minus suffixet "Controller". I det här exemplet är kontrollantklassnamnet TodoItemsController, så kontrollantnamnet är "TodoItems". ASP.NET Core routning är skiftlägesokänsligt.

  • Om attributet [HttpGet] har en routningsmall (till exempel [HttpGet("products")]) lägger du till den i sökvägen. Det här exemplet använder ingen mall. För mer information, se Attributdirigering med Http[Verb]-attribut.

I följande GetTodoItem-metod är "{id}" en platshållarvariabel för den unika identifieraren för det to-do objektet. När GetTodoItem anropas anges värdet för "{id}" i URL:en till metoden i parametern id.

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

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

    return todoItem;
}

Returnera värden

Returtypen för metoderna GetTodoItems och GetTodoItem är ActionResult<T> typ. ASP.NET Core serialiserar automatiskt objektet till JSON- och skriver JSON i brödtexten i svarsmeddelandet. Svarskoden för den här returtypen är 200 OK, förutsatt att det inte finns några ohanterade undantag. Ohanterade undantag översätts till 5xx-fel.

ActionResult returtyper kan representera ett brett utbud av HTTP-statuskoder. Till exempel kan GetTodoItem returnera två olika statusvärden:

  • Om inget objekt matchar det begärda ID:t returnerar metoden en 404-statusNotFound felkod.
  • Annars returnerar metoden 200 med en JSON-svarstext. Om du returnerar item resulterar det i ett HTTP 200 svar.

PutTodoItem-metoden

Granska metoden PutTodoItem:

[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 liknar PostTodoItem, förutom att den använder HTTP PUT. Svaret är 204 (inget innehåll). Enligt HTTP-specifikationen kräver en PUT begäran att klienten skickar hela den uppdaterade entiteten, inte bara ändringarna. Om du vill ha stöd för partiella uppdateringar använder du HTTP PATCH-.

Testa metoden PutTodoItem

Det här exemplet använder en minnesintern databas som måste initieras varje gång appen startas. Det måste finnas ett objekt i databasen innan du gör ett PUT-anrop. Anropa GET för att se till att det finns ett objekt i databasen innan du gör ett PUT-anrop.

Använd knappen PUT med swagger-användargränssnittet för att uppdatera TodoItem som har ID = 1 och ange dess namn till "feed fish". Observera att svaret är HTTP 204 No Content.

DeleteTodoItem-metoden

Granska metoden DeleteTodoItem:

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

Testa metoden DeleteTodoItem

Använd Swagger-användargränssnittet för att ta bort TodoItem som har ID = 1. Observera att svaret är HTTP 204 No Content.

Testa med andra verktyg

Det finns många andra verktyg som kan användas för att testa webb-API:er, till exempel:

Mer information finns i:

Förhindra överpublicering

För närvarande exponerar exempelappen hela TodoItem objektet. Produktionsappar begränsar vanligtvis de data som matas in och returneras med hjälp av en delmängd av modellen. Det finns flera orsaker till detta, och säkerheten är viktig. Delmängden av en modell kallas vanligtvis för ett dataöverföringsobjekt (DTO), indatamodell eller vymodell. DTO- används i den här handledningen.

En DTO kan användas för att:

  • Förhindra överpublicering.
  • Dölj egenskaper som klienter inte ska visa.
  • Utelämna vissa egenskaper för att minska nyttolaststorleken.
  • Platta ut objektdiagram som innehåller kapslade objekt. Utplattade objektdiagram kan vara enklare för klienter.

Om du vill demonstrera DTO-metoden uppdaterar du klassen TodoItem så att den innehåller ett hemligt fält:

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

Det hemliga fältet måste vara dolt från den här appen, men en administrativ app kan välja att exponera det.

Kontrollera att du kan publicera och hämta det hemliga fältet.

Skapa en DTO-modell:

namespace TodoApi.Models;

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

Uppdatera TodoItemsController för att använda TodoItemDTO:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

namespace TodoApi.Controllers;

[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
    private readonly TodoContext _context;

    public TodoItemsController(TodoContext context)
    {
        _context = context;
    }

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

    // GET: api/TodoItems/5
    // <snippet_GetByID>
    [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);
    }
    // </snippet_GetByID>

    // PUT: api/TodoItems/5
    // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
    // <snippet_Update>
    [HttpPut("{id}")]
    public async Task<IActionResult> PutTodoItem(long id, TodoItemDTO todoDTO)
    {
        if (id != todoDTO.Id)
        {
            return BadRequest();
        }

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

        todoItem.Name = todoDTO.Name;
        todoItem.IsComplete = todoDTO.IsComplete;

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

        return NoContent();
    }
    // </snippet_Update>

    // POST: api/TodoItems
    // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
    // <snippet_Create>
    [HttpPost]
    public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO todoDTO)
    {
        var todoItem = new TodoItem
        {
            IsComplete = todoDTO.IsComplete,
            Name = todoDTO.Name
        };

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

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

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

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

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

Kontrollera att du inte kan publicera eller hämta det hemliga fältet.

Anropa webb-API:et med JavaScript

Se Guide: Anropa ett ASP.NET Core-webb-API med JavaScript.

Videoserie för webb-API

Se Video: Nybörjarserie om Web API:er.

Mönster för företagswebbappar

Vägledning om hur du skapar en tillförlitlig, säker, högpresterande, testbar och skalbar ASP.NET Core-app finns i Enterprise-webbappmönster. En komplett exempelwebbapp av produktionskvalitet som implementerar mönstren är tillgänglig.

Lägga till autentiseringsstöd i ett webb-API

ASP.NET Core Identity lägger till inloggningsfunktioner för användargränssnitt (UI) i ASP.NET Core-webbappar. Om du vill skydda webb-API:er och SPA:er använder du något av följande:

Duende Identity Server är ett OpenID Connect- och OAuth 2.0-ramverk för ASP.NET Core. Duende Identity Server aktiverar följande säkerhetsfunktioner:

  • Autentisering som en tjänst (AaaS)
  • Enkel inloggning/av(SSO) över flera programtyper
  • Åtkomstkontroll för API:er
  • Federationsgateway

Viktig

Duende Software kan kräva att du betalar en licensavgift för produktionsanvändning av Duende Identity Server. Mer information finns i Migrera från ASP.NET Core 5.0 till 6.0.

Mer information finns i Duende Identity Server-dokumentationen (Duende Software-webbplatsen).

Publicera till Azure

Information om hur du distribuerar till Azure finns i Snabbstart: Distribuera en ASP.NET webbapp.

Ytterligare resurser

Visa eller ladda ned kodexempel för den här handledningen. Se här hur du laddar ned.

Mer information finns i följande resurser:

I den här självstudien lär du dig grunderna i att skapa ett kontrollantbaserat webb-API som använder en databas. En annan metod för att skapa API:er i ASP.NET Core är att skapa minimala API:er. Hjälp med att välja mellan minimala API:er och kontrollantbaserade API:er finns i översikten över API:er. En självstudiekurs om hur du skapar ett minimalt API finns i Självstudie: Skapa ett minimalt API med ASP.NET Core.

Överblick

I den här självstudien skapas följande API:

API Beskrivning Begärandetext Svarskropp
GET /api/todoitems Hämta alla to-do objekt Ingen Matris med to-do objekt
GET /api/todoitems/{id} Hämta ett objekt efter ID Ingen Att göra-objekt
POST /api/todoitems Lägga till ett nytt objekt Att göra-objekt Att göra-objekt
PUT /api/todoitems/{id} Uppdatera ett befintligt objekt Att göra-objekt Ingen
DELETE /api/todoitems/{id}     Ta bort ett objekt Ingen Ingen

Följande diagram visar appens design.

Klienten representeras av en ruta till vänster. Den skickar en begäran och får ett svar från programmet, en ruta som ritats till höger. I programrutan representerar tre rutor kontrollanten, modellen och dataåtkomstskiktet. Begäran kommer till programmets kontrollant och läs-/skrivåtgärder sker mellan kontrollanten och dataåtkomstlagret. Modellen serialiseras och returneras till klienten i svaret.

Förutsättningar

Skapa ett webbprojekt

  • På menyn Arkiv väljer du Nytt>Projekt.
  • Ange Webb-API i sökrutan.
  • Välj mallen ASP.NET Core Web API och välj Nästa.
  • I dialogrutan Konfigurera det nya projektetnamnger du projektet TodoApi och väljer Nästa.
  • I dialogrutan Ytterligare information:
    • Bekräfta att Framework- är .NET 8.0 (långsiktig support).
    • Bekräfta kryssrutan för Använd kontrollanter (avmarkera om du vill använda minimala API:er) är markerad.
    • Bekräfta att kryssrutan för Aktivera OpenAPI-stöd är markerad.
    • Välj Skapa.

Lägga till ett NuGet-paket

Ett NuGet-paket måste läggas till för att möjliggöra databasen som används i den här självstudiekursen.

  • På menyn Verktyg väljer du NuGet Package Manager > Manage NuGet Packages for Solution.
  • Välj fliken Bläddra.
  • Ange Microsoft.EntityFrameworkCore.InMemory i sökrutan och välj sedan Microsoft.EntityFrameworkCore.InMemory.
  • Markera kryssrutan Projekt i den högra panelen och välj sedan Installera.

Not

Mer information om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paketArbetsflöde för paketförbrukning (NuGet-dokumentation). Bekräfta rätt paketversioner på NuGet.org.

Testa projektet

Projektmallen skapar ett WeatherForecast API med stöd för Swagger.

Tryck på Ctrl+F5 för att köra utan felsökningsprogrammet.

Visual Studio visar följande dialogruta när ett projekt ännu inte har konfigurerats för att använda SSL:

Det här projektet är konfigurerat att använda SSL. För att undvika SSL-varningar i webbläsaren kan du välja att lita på det självsignerade certifikat som IIS Express har genererat. Vill du lita på IIS Express SSL-certifikatet?

Välj Ja om du litar på IIS Express SSL-certifikatet.

Följande dialogruta visas:

Säkerhetsvarning dialogruta

Välj Ja om du samtycker till att lita på utvecklingscertifikatet.

Information om hur du litar på Webbläsaren Firefox finns i Firefox SEC_ERROR_INADEQUATE_KEY_USAGE certifikatfel.

Visual Studio startar standardwebbläsaren och navigerar till https://localhost:<port>/swagger/index.html, där <port> är ett slumpmässigt valt portnummer som anges när projektet skapas.

Swagger-sidan /swagger/index.html visas. Välj GET>Prova>Kör. Sidan visar:

  • Kommandot Curl för att testa WeatherForecast-API:et.
  • URL:en för att testa WeatherForecast-API:et.
  • Svarskoden, brödtexten och rubrikerna.
  • En listruta med medietyper och exempelvärdet och schemat.

Om Swagger-sidan inte visas, se det här GitHub-problemet.

Swagger används för att generera användbar dokumentation och hjälpsidor för webb-API:er. I den här självstudien används Swagger för att testa appen. Mer information om Swagger finns i ASP.NET Core web API-dokumentation med Swagger/OpenAPI.

Kopiera och klistra in url:en för begäran i webbläsaren: https://localhost:<port>/weatherforecast

JSON som liknar följande exempel returneras:

[
    {
        "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"
    }
]

Lägga till en modellklass

En modell är en uppsättning klasser som representerar de data som appen hanterar. Modellen för den här appen är klassen TodoItem.

  • Högerklicka på projektet i Solution Explorer. Välj Lägg till>ny mapp. Ge mappen namnet Models.
  • Högerklicka på mappen Models och välj Lägg till>klass. Ge klassen namnet TodoItem och välj Lägg till.
  • Ersätt mallkoden med följande:
namespace TodoApi.Models;

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

Egenskapen Id fungerar som den unika nyckeln i en relationsdatabas.

Modellklasser kan placeras var som helst i projektet, men mappen Models används enligt konvention.

Lägga till en databaskontext

Den databaskontexten är huvudklassen som samordnar Entity Framework-funktioner för en datamodell. Den här klassen skapas genom att härledas från klassen Microsoft.EntityFrameworkCore.DbContext.

  • Högerklicka på mappen Models och välj Lägg till>klass. Ge klassen namnet TodoContext och klicka på Lägg till.
  • Ange följande kod:

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

Registrera databaskontexten

I ASP.NET Core måste tjänster som DB-kontexten registreras med beroendeinmatning (DI) container. Containern tillhandahåller tjänsten till kontrollanter.

Uppdatera Program.cs med följande markerade kod:

using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
    opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Föregående kod:

  • Lägger till using direktiv.
  • Lägger till databaskontexten i DI-containern.
  • Anger att databaskontexten ska använda en minnesintern databas.

Generera grundstruktur för en styrenhet

  • Högerklicka på mappen Controllers.

  • Välj Lägg till>New Scaffolded Item.

  • Välj API-kontrollant med åtgärder, använd Entity Frameworkoch välj sedan Lägg till.

  • I dialogrutan Lägg till en API-kontroller med funktioner, med användning av Entity Framework:

    • Välj TodoItem (TodoApi.Models) i klassen Model.
    • Välj TodoContext (TodoApi.Models) i datakontextklassen .
    • Välj Lägg till.

    Om scaffolding-åtgärden misslyckas väljer du Lägg till för att försöka skapa scaffolding en andra gång.

Den genererade koden:

  • Markerar klassen med attributet [ApiController]. Det här attributet anger att kontrollanten svarar på webb-API-begäranden. Information om specifika beteenden som attributet aktiverar finns i Skapa webb-API:er med ASP.NET Core.
  • Använder DI för att mata in databaskontexten (TodoContext) i kontrollanten. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.

ASP.NET Core-mallarna för:

  • Kontrollanter med vyer innehåller [action] i routningsmallen.
  • API-kontrollanter inkluderar inte [action] i routningsmallen.

När [action] token inte finns i routningsmallen inkluderas inte -åtgärden namn (metodnamn) i slutpunkten. Åtgärdens associerade metodnamn används alltså inte i matchande väg.

Uppdatera metoden PostTodoItem create

Uppdatera retursatsen i PostTodoItem för att använda namn på operatorn:

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

Föregående kod är en HTTP POST metod, vilket anges av attributet [HttpPost]. Metoden hämtar värdet för TodoItem från brödtexten i HTTP-begäran.

För mer information, se Attributdirigering med Http[Verb]-attribut.

Metoden CreatedAtAction:

  • Returnerar en HTTP 201-statuskod om den lyckas. HTTP 201 är standardsvaret för en HTTP POST-metod som skapar en ny resurs på servern.
  • Lägger till en Location-rubrik i svaret. Location-huvudet anger URI- för det nyligen skapade to-do objektet. Mer information finns i 10.2.2 201 Skapad.
  • Refererar till åtgärden GetTodoItem för att skapa Location-huvudets URI. Nyckelordet C# nameof används för att undvika hårdkodning av åtgärdsnamnet i CreatedAtAction-anropet.

Test PostTodoItem

  • Kör appen genom att trycka på Ctrl+F5.

  • I swagger-webbläsarfönstret väljer du POST /api/TodoItemsoch väljer sedan Prova.

  • I fönstret för Begärandetext, uppdatera JSON. Till exempel

    {
      "name": "walk dog",
      "isComplete": true
    }
    
  • Välj Kör

    Swagger POST

Testa lokaliseringshuvudets URI

I föregående POST visar Swagger-användargränssnittet platsrubrik under Svarsrubriker. Till exempel location: https://localhost:7260/api/TodoItems/1. Platsrubriken visar URI:n för den skapade resursen.

Så här testar du platsrubriken:

  • I swagger-webbläsarfönstret väljer du GET /api/TodoItems/{id}och väljer sedan Prova.

  • Ange 1 i indatarutan id och välj sedan Kör.

    Swagger GET

Granska GET-metoderna

Två GET-slutpunkter implementeras:

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

Föregående avsnitt visade ett exempel på vägen /api/todoitems/{id}.

Följ anvisningarna i POST för att lägga till en ny uppgift och testa sedan /api/todoitems route med hjälp av Swagger.

Den här appen använder en minnesintern databas. Om appen stoppas och startas returnerar inte den föregående GET-begäran några data. Om ingen data returneras, POST data till appen.

Routnings- och URL-sökvägar

Attributet [HttpGet] anger en metod som svarar på en HTTP GET begäran. URL-sökvägen för varje metod konstrueras på följande sätt:

  • Börja med mallsträngen i kontrollantens Route-attribut:

    [Route("api/[controller]")]
    [ApiController]
    public class TodoItemsController : ControllerBase
    
  • Ersätt [controller] med namnet på kontrollanten, som enligt konventionen är kontrollantens klassnamn minus suffixet "Controller". I det här exemplet är kontrollantklassnamnet TodoItemsController, så kontrollantnamnet är "TodoItems". ASP.NET Core -routning är inte skiftlägeskänsligt.

  • Om attributet [HttpGet] har en routningsmall (till exempel [HttpGet("products")]) lägger du till den i sökvägen. Det här exemplet använder ingen mall. För mer information, se Attributdirigering med Http[Verb]-attribut.

I följande GetTodoItem-metod är "{id}" en platshållarvariabel för den unika identifieraren för det to-do objektet. När GetTodoItem anropas anges värdet för "{id}" i URL:en till metoden i parametern id.

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

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

    return todoItem;
}

Returnera värden

Returtypen för metoderna GetTodoItems och GetTodoItem är ActionResult<T> typ. ASP.NET Core serialiserar automatiskt objektet till JSON- och skriver JSON i brödtexten i svarsmeddelandet. Svarskoden för den här returtypen är 200 OK, förutsatt att det inte finns några ohanterade undantag. Ohanterade undantag översätts till 5xx-fel.

ActionResult returtyper kan representera ett brett utbud av HTTP-statuskoder. Till exempel kan GetTodoItem returnera två olika statusvärden:

  • Om inget objekt matchar det begärda ID:t returnerar metoden en 404-statusNotFound felkod.
  • Annars returnerar metoden 200 med en JSON-svarstext. Om du returnerar item resulterar det i ett HTTP 200 svar.

PutTodoItem-metoden

Granska metoden PutTodoItem:

[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 liknar PostTodoItem, förutom att den använder HTTP PUT. Svaret är 204 (inget innehåll). Enligt HTTP-specifikationen kräver en PUT begäran att klienten skickar hela den uppdaterade entiteten, inte bara ändringarna. Om du vill ha stöd för partiella uppdateringar använder du HTTP PATCH-.

Testa metoden PutTodoItem

Det här exemplet använder en minnesintern databas som måste initieras varje gång appen startas. Det måste finnas ett objekt i databasen innan du gör ett PUT-anrop. Anropa GET för att se till att det finns ett objekt i databasen innan du gör ett PUT-anrop.

Använd knappen PUT med swagger-användargränssnittet för att uppdatera TodoItem som har ID = 1 och ange dess namn till "feed fish". Observera att svaret är HTTP 204 No Content.

Metoden DeleteTodoItem

Granska metoden DeleteTodoItem:

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

Testa metoden DeleteTodoItem

Använd Swagger-användargränssnittet för att ta bort TodoItem som har ID = 1. Observera att svaret är HTTP 204 No Content.

Testa med andra verktyg

Det finns många andra verktyg som kan användas för att testa webb-API:er, till exempel:

Mer information finns i:

Förhindra överpublicering

För närvarande exponerar exempelappen hela TodoItem objektet. Produktionsappar begränsar vanligtvis de data som matas in och returneras med hjälp av en delmängd av modellen. Det finns flera orsaker till detta, och säkerheten är viktig. Delmängden av en modell kallas vanligtvis för ett dataöverföringsobjekt (DTO), indatamodell eller vymodell. DTO- används i denna handledning.

En DTO kan användas för att:

  • Förhindra överpublicering.
  • Dölj egenskaper som klienter inte ska visa.
  • Utelämna vissa egenskaper för att minska nyttolaststorleken.
  • Platta ut objektdiagram som innehåller kapslade objekt. Utplattade objektdiagram kan vara enklare för klienter.

Om du vill demonstrera DTO-metoden uppdaterar du klassen TodoItem så att den innehåller ett hemligt fält:

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

Det hemliga fältet måste vara dolt från den här appen, men en administrativ app kan välja att exponera det.

Kontrollera att du kan skicka och hämta det hemliga fältet.

Skapa en DTO-modell:

namespace TodoApi.Models;

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

Uppdatera TodoItemsController för att använda TodoItemDTO:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

namespace TodoApi.Controllers;

[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
    private readonly TodoContext _context;

    public TodoItemsController(TodoContext context)
    {
        _context = context;
    }

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

    // GET: api/TodoItems/5
    // <snippet_GetByID>
    [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);
    }
    // </snippet_GetByID>

    // PUT: api/TodoItems/5
    // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
    // <snippet_Update>
    [HttpPut("{id}")]
    public async Task<IActionResult> PutTodoItem(long id, TodoItemDTO todoDTO)
    {
        if (id != todoDTO.Id)
        {
            return BadRequest();
        }

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

        todoItem.Name = todoDTO.Name;
        todoItem.IsComplete = todoDTO.IsComplete;

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

        return NoContent();
    }
    // </snippet_Update>

    // POST: api/TodoItems
    // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
    // <snippet_Create>
    [HttpPost]
    public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO todoDTO)
    {
        var todoItem = new TodoItem
        {
            IsComplete = todoDTO.IsComplete,
            Name = todoDTO.Name
        };

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

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

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

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

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

Kontrollera att du inte kan publicera eller hämta det hemliga fältet.

Anropa webb-API:et med JavaScript

Se Självstudie: Anropa ett ASP.NET Core-webb-API med JavaScript.

Videoserie för webb-API

Se Video: Nybörjarserie om: Webbapi:er.

Mönster för företagswebbappar

Vägledning om hur du skapar en tillförlitlig, säker, högpresterande, testbar och skalbar ASP.NET Core-app finns i Enterprise-webbappmönster. En komplett exempelwebbapp av produktionskvalitet som implementerar mönstren är tillgänglig.

Lägga till autentiseringsstöd i ett webb-API

ASP.NET Core Identity lägger till inloggningsfunktioner för användargränssnitt (UI) i ASP.NET Core-webbappar. Om du vill skydda webb-API:er och SPA:er använder du något av följande:

Duende Identity Server är ett OpenID Connect- och OAuth 2.0-ramverk för ASP.NET Core. Duende Identity Server aktiverar följande säkerhetsfunktioner:

  • Autentisering som en tjänst (AaaS)
  • Enkel inloggning/av(SSO) över flera programtyper
  • Åtkomstkontroll för API:er
  • Federationsgateway

Viktig

Duende Software kan kräva att du betalar en licensavgift för produktionsanvändning av Duende Identity Server. Mer information finns i Migrera från ASP.NET Core 5.0 till 6.0.

Mer information finns i Duende Identity Server-dokumentationen (Duende Software-webbplatsen).

Publicera till Azure

Information om hur du distribuerar till Azure finns i Snabbstart: Distribuera en ASP.NET webbapp.

Ytterligare resurser

Visa eller ladda ner exempelkod för den här självstudiekursen. Se hur du laddar ned.

Mer information finns i följande resurser: