Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Note
Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.
Warning
A ASP.NET Core ezen verziója már nem támogatott. További információ: .NET és .NET Core támogatási szabályzat. Az aktuális kiadást e cikk .NET 9-es verziójában találja.
Készítette: Rick Anderson és Tom Dykstra
A minimális API-k úgy vannak kialakítva, hogy minimális függőségekkel rendelkező HTTP API-kat hozzanak létre. Olyan mikroszolgáltatásokhoz és alkalmazásokhoz ideálisak, amelyek csak a minimális fájlokat, funkciókat és függőségeket szeretnék belefoglalni a ASP.NET Core-ba.
Ez az oktatóanyag a minimális API-k ASP.NET Core használatával történő létrehozásának alapjait mutatja be. Az API-k ASP.NET Core-ban való létrehozásának másik módszere a vezérlők használata. Ha segítségre van szüksége a minimális API-k és a vezérlőalapú API-k közötti választáshoz, tekintse meg API-k áttekintését. A további funkciókat tartalmazó vezérlők alapuló API-projektek létrehozásáról a Webes API-létrehozása című témakörben olvashat.
Overview
Ez az oktatóanyag a következő API-t hozza létre:
| API | Description | A kérés tartalma | Válasz törzse |
|---|---|---|---|
GET /todoitems |
Az összes to-do elem lekérése | None | teendők tömbje |
GET /todoitems/complete |
Kapj kész to-do elemeket | None | teendők tömbje |
GET /todoitems/{id} |
Elem lekérése azonosító alapján | None | Teendő elem |
POST /todoitems |
Új elem hozzáadása | Teendő elem | Teendő elem |
PUT /todoitems/{id} |
Meglévő elem frissítése | Teendő elem | None |
DELETE /todoitems/{id} |
Elem törlése | None | None |
Prerequisites
Visual Studio 2022 az ASP.NET és webfejlesztés munkaállomással.
API-projekt létrehozása
Indítsa el a Visual Studio 2022-t, és válassza Új projekt létrehozásalehetőséget.
Az Új projekt létrehozása párbeszédpanelen:
- Írja be
Emptya Sablonok keresése keresőmezőbe. - Válassza a ASP.NET Core Empty sablont, majd válassza a Következőlehetőséget.
- Írja be
Nevezze el a projektet TodoApi, és válassza a Továbblehetőséget.
A További információk párbeszédpanelen:
- Válassza .NET 9.0
- Törölje a jelölést Ne használjon legfelső szintű utasításokat
- Válassza a lehetőséget, hozza létre a lehetőséget
A kód vizsgálata
A Program.cs fájl a következő kódot tartalmazza:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző kód:
- Létrehoz egy WebApplicationBuilder és egy előre konfigurált alapértelmezett WebApplication.
- Létrehoz egy HTTP GET-végpontot
/, amely visszaadja a függvénytHello World!.
Az alkalmazás futtatása
Nyomja le a Ctrl+F5 billentyűkombinációt a hibakereső nélküli futtatáshoz.
A Visual Studio a következő párbeszédpanelt jeleníti meg:
Válassza Igen lehetőséget, ha megbízik az IIS Express SSL-tanúsítványban.
A következő párbeszédpanel jelenik meg:
Válassza Igen lehetőséget, ha elfogadja, hogy megbízik a fejlesztési tanúsítványban.
A Firefox böngésző megbízhatóságáról további információt a Firefox SEC_ERROR_INADEQUATE_KEY_USAGE tanúsítványhibacímű témakörben talál.
A Visual Studio elindítja a Kestrel webkiszolgáló, és megnyit egy böngészőablakot.
Hello World! megjelenik a böngészőben. A Program.cs fájl minimális, de teljes alkalmazást tartalmaz.
Zárja be a böngészőablakot.
NuGet-csomagok hozzáadása
Az oktatóanyagban használt adatbázis és diagnosztikák támogatásához NuGet-csomagokat kell hozzáadni.
- Az Eszközök menüben válassza a NuGet Package Manager > Megoldáshoz készült NuGet-csomagok kezeléselehetőséget.
- Válassza a Tallózás lapot.
- Válassza a Előzetes verzió belefoglalásalehetőséget.
- Írja be Microsoft.EntityFrameworkCore.InMemory a keresőmezőbe, majd válassza a
Microsoft.EntityFrameworkCore.InMemory. - Jelölje be a Project jelölőnégyzetet a jobb oldali panelen, majd válassza a Telepítéslehetőséget.
- A
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCorecsomag hozzáadásához kövesse az előző utasításokat.
A modell és az adatbázis környezeti osztályai
- A projektmappában hozzon létre egy
Todo.csnevű fájlt a következő kóddal:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Az előző kód létrehozza az alkalmazás modelljét. A modell egy olyan osztály, amely az alkalmazás által kezelt adatokat jelöli.
- Hozzon létre egy
TodoDb.csnevű fájlt a következő kóddal:
using Microsoft.EntityFrameworkCore;
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Az előző kód határozza meg az adatbázis-környezetet, amely az adatmodell Entity Framework funkcióit koordináló fő osztály. Ez az osztály a Microsoft.EntityFrameworkCore.DbContext osztályból származik.
Az API-kód hozzáadása
- Cserélje le a
Program.csfájl tartalmát a következő kódra:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Az alábbi kiemelt kód hozzáadja az adatbázis-környezetet a függőséginjektálási (DI) tárolóhoz, és lehetővé teszi az adatbázissal kapcsolatos kivételek megjelenítését:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
A DI-tároló hozzáférést biztosít az adatbázis-környezethez és más szolgáltatásokhoz.
Ez az oktatóanyag az Endpoints Explorer-t és a .http fájlokat használja az API teszteléséhez.
Közzétételi adatok tesztelése
A Program.cs következő kódja létrehoz egy HTTP POST-végpontot /todoitems, amely adatokat ad hozzá a memóriában lévő adatbázishoz:
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
Futtassa az alkalmazást. A böngésző 404-et jelenít meg, mert már nincs / végpont.
A POST végpont használatával adatokat adhat hozzá az alkalmazáshoz.
Válassza a Nézet>Egyéb ablakok>Endpoints Explorer.
Kattintson a jobb gombbal a POST végpontra, és válassza a Kérés létrehozásalehetőséget.
Egy új fájl jön létre a
TodoApi.httpnevű projektmappában, amely a következő példához hasonló tartalommal rendelkezik:@TodoApi_HostAddress = https://localhost:7031 POST {{TodoApi_HostAddress}}/todoitems ###- Az első sor létrehoz egy változót, amelyet az összes végponthoz használnak.
- A következő sor egy POST-kérést határoz meg.
- A tripla hashtag (
###) sor egy kérések közötti elválasztó jel: ami utána következik, az egy másik kéréshez tartozik.
A POST-kérelemhez fejlécekre és tartalomra van szükség. A kérelem ezen részeinek meghatározásához közvetlenül a POST kérelemsor után adja hozzá a következő sorokat:
Content-Type: application/json { "name":"walk dog", "isComplete":true }Az előző kód hozzáad egy Tartalomtípus fejlécet és egy JSON-kérelemtörzset. A TodoApi.http fájlnak most az alábbi példához hasonlóan kell kinéznie, de a portszámmal:
@TodoApi_HostAddress = https://localhost:7057 POST {{TodoApi_HostAddress}}/todoitems Content-Type: application/json { "name":"walk dog", "isComplete":true } ###Futtassa az alkalmazást.
Válassza a Kérés küldése hivatkozást, amely a
POSTkérelemsor felett található.
A POST kérést a rendszer elküldi az alkalmazásnak, és a válasz megjelenik a Válasz panelen.
A GET-végpontok vizsgálata
A mintaalkalmazás több GET-végpontot implementál MapGetmeghívásával:
| API | Description | A kérés tartalma | Válasz törzse |
|---|---|---|---|
GET /todoitems |
Az összes to-do elem lekérése | None | teendők tömbje |
GET /todoitems/complete |
Az összes kész to-do elem lekérése | None | teendők tömbje |
GET /todoitems/{id} |
Elem lekérése azonosító alapján | None | Teendő elem |
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
A GET-végpontok tesztelése
Tesztelje az alkalmazást a GET végpontok böngészőből való meghívásával vagy Endpoints Explorerhasználatával. Az alábbi lépések a Endpoints Explorer-hez tartoznak.
Az Endpoints Explorerterületen kattintson a jobb gombbal az első GET végpontra, és válassza a Kérés létrehozásalehetőséget.
A következő tartalom lesz hozzáadva a
TodoApi.httpfájlhoz:GET {{TodoApi_HostAddress}}/todoitems ###Válassza a Kérés küldése hivatkozást, amely az új
GETkérelemsor felett található.A GET kérést a rendszer elküldi az alkalmazásnak, és a válasz megjelenik a Válasz panelen.
A válasz törzse a következő JSON-hoz hasonló:
[ { "id": 1, "name": "walk dog", "isComplete": true } ]Az Endpoints Explorerterületen kattintson a jobb gombbal a
/todoitems/{id}GET végpontra, és válassza a Kérés létrehozásalehetőséget. A következő tartalom lesz hozzáadva aTodoApi.httpfájlhoz:GET {{TodoApi_HostAddress}}/todoitems/{id} ###Cserélje le
{id}1.Válassza a Kérés küldése hivatkozást, amely az új GET kérelemsor felett található.
A GET kérést a rendszer elküldi az alkalmazásnak, és a válasz megjelenik a Válasz panelen.
A válasz törzse a következő JSON-hoz hasonló:
{ "id": 1, "name": "walk dog", "isComplete": true }
Ez az alkalmazás memórián belüli adatbázist használ. Ha az alkalmazás újraindul, a GET kérés nem ad vissza adatokat. Ha nem ad vissza adatokat, POST adatokat az alkalmazásnak, és próbálkozzon újra a GET kéréssel.
Visszaadott értékek
ASP.NET Core automatikusan szerializálja az objektumot JSON formátumra, és beírja a JSON-t a válaszüzenet törzsébe. A visszatérési típus válaszkódja 200 OK, feltéve, hogy nincsenek kezeletlen kivételek. A nem kezelt kivételek 5xx-hibákká lesznek lefordítva.
A visszatérési típusok a HTTP-állapotkódok széles skáláját jelölhetik. A GET /todoitems/{id} például két különböző állapotértéket adhat vissza:
- Ha egyetlen elem sem felel meg a kért azonosítónak, a metódus egy 404-NotFound hibakódot ad vissza.
- Ellenkező esetben a metódus egy JSON-válasz törzsével adja vissza a 200-t. A
itemvisszaadása HTTP 200-választ eredményez.
A PUT végpont vizsgálata
A mintaalkalmazás egyetlen PUT-végpontot valósít meg MapPut:
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
Ez a módszer hasonló a MapPost metódushoz, kivéve, ha HTTP PUT-t használ. A sikeres válasz a 204 (tartalom nélkül) ad vissza. A HTTP-specifikáció szerint a PUT-kéréshez az ügyfélnek a teljes frissített entitást kell elküldenie, nem csak a módosításokat. A részleges frissítések támogatásához használja HTTP PATCH.
A PUT végpont tesztelése
Ez a minta egy memórián belüli adatbázist használ, amelyet az alkalmazás minden indításakor inicializálni kell. Az adatbázisnak tartalmaznia kell egy elemet, mielőtt PUT-hívást kezdeményezne. A GET hívásával győződjön meg arról, hogy van egy elem az adatbázisban, mielőtt PUT-hívást kezdeményez.
Frissítse a to-do elemet, amely Id = 1-t tartalmaz, és állítsa be a nevét "feed fish".
Az Endpoints Explorer-ben kattintson a jobb gombbal a PUT végpontra, és válassza a Kérés létrehozásalehetőséget.
A következő tartalom lesz hozzáadva a
TodoApi.httpfájlhoz:PUT {{TodoApi_HostAddress}}/todoitems/{id} ###A PUT kérelemsorban cserélje le a
{id}1.Közvetlenül a PUT kérelemsor után adja hozzá a következő sorokat:
Content-Type: application/json { "id": 1, "name": "feed fish", "isComplete": false }Az előző kód hozzáad egy Tartalomtípus fejlécet és egy JSON-kérelemtörzset.
Válassza a Kérés küldése hivatkozást, amely az új PUT kérelemsor felett található.
A PUT kérést a rendszer elküldi az alkalmazásnak, és a válasz megjelenik a Válasz panelen. A válasz törzse üres, az állapotkód pedig 204.
A DELETE végpont vizsgálata és tesztelése
A mintaalkalmazás egyetlen DELETE-végpontot valósít meg MapDelete:
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
Az Endpoints Explorerterületen kattintson a jobb gombbal a DELETE végpontra, és válassza a Kérés létrehozásalehetőséget.
Hozzá van adva egy DELETE kérés a
TodoApi.http-hoz.A
{id}helyett1-et használjon a DELETE kérelemsorban. A DELETE kérésnek a következő példához hasonlóan kell kinéznie:DELETE {{TodoApi_HostAddress}}/todoitems/1 ###Válassza a Küldési kérelem hivatkozást a DELETE kéréshez.
A DELETE kérést a rendszer elküldi az alkalmazásnak, és a válasz megjelenik a Válasz panelen. A válasz törzse üres, az állapotkód pedig 204.
A MapGroup API használata
A mintaalkalmazás kódja minden végpont beállításakor megismétli a todoitems URL-előtagot. Az API-k gyakran rendelkeznek közös URL-előtaggal rendelkező végpontcsoportokkal, és a MapGroup módszer segít az ilyen csoportok rendszerezésében. Csökkenti az ismétlődő kódot, és lehetővé teszi a végpontok teljes csoportjainak testreszabását egyetlen hívással az olyan metódusokhoz, mint a RequireAuthorization és a WithMetadata.
Cserélje le a Program.cs tartalmát a következő kódra:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", async (TodoDb db) =>
await db.Todos.ToListAsync());
todoItems.MapGet("/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
todoItems.MapGet("/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
todoItems.MapPost("/", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
todoItems.MapDelete("/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Az előző kód a következő módosításokat tartalmazza:
- Hozzáad
var todoItems = app.MapGroup("/todoitems");a csoport beállításához az URL-előtag/todoitemshasználatával. - Módosítja az összes
app.Map<HttpVerb>metódusttodoItems.Map<HttpVerb>-re. - Eltávolítja a
/todoitemsURL-előtagot aMap<HttpVerb>metódushívásokból.
Tesztelje a végpontokat annak ellenőrzéséhez, hogy azonosak-e.
A TypedResults API használata
A TypedResults helyett a Results visszaadása számos előnnyel jár, beleértve a tesztelhetőséget, és automatikusan visszaadja a választípus metaadatait az OpenAPI-hoz a végpont leírásához. További információ: TypedResults vs Results.
A Map<HttpVerb> metódusok a lambdák használata helyett útvonalkezelő metódusokat is meghívhatnak. Egy példa megtekintéséhez frissítse a Program.cs a következő kóddal:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
A Map<HttpVerb> kód mostantól metódusokat hív meg a lambdas helyett:
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
Ezek a metódusok olyan objektumokat adnak vissza, amelyek IResult implementálnak, és amelyeket a TypedResultshatároznak meg:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Az egységtesztek meghívhatják ezeket a metódusokat, és tesztelhetik, hogy a megfelelő típust adja vissza. Ha például a módszer GetAllTodos:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
Az egységtesztelési kód képes ellenőrizni, hogy a kezelőmetódus visszaad-e egy Ok<Todo[]> típusú objektumot. Például:
public async Task GetAllTodos_ReturnsOkOfTodosResult()
{
// Arrange
var db = CreateDbContext();
// Act
var result = await TodosApi.GetAllTodos(db);
// Assert: Check for the correct returned type
Assert.IsType<Ok<Todo[]>>(result);
}
Túlküldés megakadályozása
A mintaalkalmazás jelenleg a teljes Todo objektumot teszi elérhetővé. Éles alkalmazásokban a modell egy részhalmazát gyakran használják a bemeneti és visszaadható adatok korlátozására. Ennek több oka is van, és a biztonság a legfontosabb. A modell részhalmazát általában adatátviteli objektumnak (DTO), bemeneti modellnek vagy nézetmodellnek nevezzük. ebben a cikkben DTO- használunk.
A DTO a következőre használható:
- A túlküldés megakadályozása.
- Rejtse el azokat a tulajdonságokat, amelyeket az ügyfeleknek nem szabad megtekinteniük.
- Hagyj ki néhány tulajdonságot, hogy csökkentsük a hasznos teher méretét.
- Beágyazott objektumokat tartalmazó objektumdiagramok simítása. A laposabb objektumgráfok kényelmesebbek lehetnek az ügyfelek számára.
A DTO-megközelítés bemutatásához frissítse a Todo osztályt egy titkos mezőre:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
A titkos mezőt el kell rejteni az alkalmazás elől, de egy felügyeleti alkalmazás dönthet úgy, hogy közzéteszi.
Ellenőrizze, hogy közzéteheti és lekérheti-e a titkos kód mezőt.
Hozzon létre egy TodoItemDTO.cs nevű fájlt a következő kóddal:
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
Cserélje le a Program.cs fájl tartalmát a következő kódra a DTO-modell használatához:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
RouteGroupBuilder todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Select(x => new TodoItemDTO(x)).ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db) {
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).Select(x => new TodoItemDTO(x)).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(new TodoItemDTO(todo))
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(TodoItemDTO todoItemDTO, TodoDb db)
{
var todoItem = new Todo
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
db.Todos.Add(todoItem);
await db.SaveChangesAsync();
todoItemDTO = new TodoItemDTO(todoItem);
return TypedResults.Created($"/todoitems/{todoItem.Id}", todoItemDTO);
}
static async Task<IResult> UpdateTodo(int id, TodoItemDTO todoItemDTO, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = todoItemDTO.Name;
todo.IsComplete = todoItemDTO.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Ellenőrizze, hogy a titkos kód mező kivételével az összes mezőt közzéteheti és lekérheti.
Hibaelhárítás a kész mintával
Ha olyan problémába ütközik, amely nem oldható meg, hasonlítsa össze a kódot a befejezett projektel. Befejezett projekt megtekintése vagy letöltése (miként tölthető le).
Következő lépések
- JSON-szerializálási beállítások konfigurálása.
- Hibák és kivételek kezelése: A fejlesztői kivételoldal alapértelmezés szerint engedélyezve van a minimális API-alkalmazások fejlesztői környezetében. A hibák és kivételek kezeléséről további információt a ASP.NET Core API-k hibáinak kezelésecímű témakörben talál.
- Egy minimális API-alkalmazás tesztelésére példa: ez a GitHub-minta.
- OpenAPI-támogatás minimális API-kban.
- Gyorstalpaló: Közzététel az Azure-ra.
- ASP.NET Core Minimal API-krendszerezése.
Learn more
Tekintse meg Minimális API-k rövid útmutatója
A minimális API-k úgy vannak kialakítva, hogy minimális függőségekkel rendelkező HTTP API-kat hozzanak létre. Ideálisak olyan mikroszolgáltatásokhoz és alkalmazásokhoz, amelyek csak a minimális fájlokat, funkciókat és függőségeket szeretnék belefoglalni a ASP.NET Core-ba.
Ez az oktatóanyag a minimális API-k ASP.NET Core használatával történő létrehozásának alapjait mutatja be. Az API-k ASP.NET Core-ban való létrehozásának másik módszere a vezérlők használata. Ha segítségre van szüksége a minimális API-k és a vezérlőalapú API-k közötti választáshoz, tekintse meg API-k áttekintését. A további funkciókat tartalmazó vezérlők alapuló API-projektek létrehozásáról a Webes API-létrehozása című témakörben olvashat.
Overview
Ez az oktatóanyag a következő API-t hozza létre:
| API | Description | A kérés tartalma | Válasz törzse |
|---|---|---|---|
GET /todoitems |
Az összes to-do elem lekérése | None | teendők tömbje |
GET /todoitems/complete |
Kapj kész to-do elemeket | None | teendők tömbje |
GET /todoitems/{id} |
Elem lekérése azonosító alapján | None | Teendő elem |
POST /todoitems |
Új elem hozzáadása | Teendő elem | Teendő elem |
PUT /todoitems/{id} |
Meglévő elem frissítése | Teendő elem | None |
DELETE /todoitems/{id} |
Elem törlése | None | None |
Prerequisites
Visual Studio 2022 az ASP.NET és webfejlesztés munkaállomással.
API-projekt létrehozása
Indítsa el a Visual Studio 2022-t, és válassza Új projekt létrehozásalehetőséget.
Az Új projekt létrehozása párbeszédpanelen:
- Írja be
Emptya Sablonok keresése keresőmezőbe. - Válassza a ASP.NET Core Empty sablont, majd válassza a Következőlehetőséget.
- Írja be
Nevezze el a projektet TodoApi, és válassza a Továbblehetőséget.
A További információk párbeszédpanelen:
- Válassza .NET 7.0
- Törölje a jelölést Ne használjon legfelső szintű utasításokat
- Válassza a lehetőséget, hozza létre a lehetőséget
A kód vizsgálata
A Program.cs fájl a következő kódot tartalmazza:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző kód:
- Létrehoz egy WebApplicationBuilder és egy előre konfigurált alapértelmezett WebApplication.
- Létrehoz egy HTTP GET-végpontot
/, amelyHello World!ad vissza:
Az alkalmazás futtatása
Nyomja le a Ctrl+F5 billentyűkombinációt a hibakereső nélküli futtatáshoz.
A Visual Studio a következő párbeszédpanelt jeleníti meg:
Válassza Igen lehetőséget, ha megbízik az IIS Express SSL-tanúsítványban.
A következő párbeszédpanel jelenik meg:
Válassza Igen lehetőséget, ha elfogadja, hogy megbízik a fejlesztési tanúsítványban.
A Firefox böngésző megbízhatóságáról további információt a Firefox SEC_ERROR_INADEQUATE_KEY_USAGE tanúsítványhibacímű témakörben talál.
A Visual Studio elindítja a Kestrel webkiszolgáló, és megnyit egy böngészőablakot.
Hello World! megjelenik a böngészőben. A Program.cs fájl minimális, de teljes alkalmazást tartalmaz.
NuGet-csomagok hozzáadása
Az oktatóanyagban használt adatbázis és diagnosztikák támogatásához NuGet-csomagokat kell hozzáadni.
- Az Eszközök menüben válassza a NuGet Package Manager > Megoldáshoz készült NuGet-csomagok kezeléselehetőséget.
- Válassza a Tallózás lapot.
- Írja be Microsoft.EntityFrameworkCore.InMemory a keresőmezőbe, majd válassza a
Microsoft.EntityFrameworkCore.InMemory. - Jelölje be a Project jelölőnégyzetet a jobb oldali panelen.
- A Verzió legördülő listában válassza ki a legújabb elérhető 7-es verziót, például
7.0.17, majd válassza a Telepítéslehetőséget. - Az előző utasításokat követve adja hozzá a
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCorecsomagot a legújabb, 7-es verzióval.
A modell és az adatbázis környezeti osztályai
A projektmappában hozzon létre egy Todo.cs nevű fájlt a következő kóddal:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Az előző kód létrehozza az alkalmazás modelljét. A modell egy olyan osztály, amely az alkalmazás által kezelt adatokat jelöli.
Hozzon létre egy TodoDb.cs nevű fájlt a következő kóddal:
using Microsoft.EntityFrameworkCore;
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Az előző kód határozza meg az adatbázis-környezetet, amely az adatmodell Entity Framework funkcióit koordináló fő osztály. Ez az osztály a Microsoft.EntityFrameworkCore.DbContext osztályból származik.
Az API-kód hozzáadása
Cserélje le a Program.cs fájl tartalmát a következő kódra:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Az alábbi kiemelt kód hozzáadja az adatbázis-környezetet a függőséginjektálási (DI) tárolóhoz, és lehetővé teszi az adatbázissal kapcsolatos kivételek megjelenítését:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
A DI-tároló hozzáférést biztosít az adatbázis-környezethez és más szolgáltatásokhoz.
API-tesztelési felhasználói felület létrehozása a Swaggerrel
Számos elérhető webes API-tesztelési eszköz közül választhat, és az oktatóanyag bevezető API-tesztelési lépéseit saját előnyben részesített eszközével követheti.
Ez az oktatóanyag az NSwag.AspNetCore .NET-csomagot használja, amely integrálja a Swagger-eszközöket az OpenAPI-specifikációhoz tartozó tesztelési felhasználói felület létrehozásához:
- NSwag: .NET-kódtár, amely közvetlenül integrálja a Swaggert ASP.NET Core-alkalmazásokba, köztes szoftvereket és konfigurációt biztosítva.
- Swagger: Olyan nyílt forráskódú eszközök készlete, mint az OpenAPIGenerator és a SwaggerUI, amelyek az OpenAPI-specifikációt követő API-tesztoldalakat hoznak létre.
- OpenAPI-specifikáció: Az API képességeit leíró dokumentum a vezérlők és modellek XML- és attribútumjegyzetei alapján.
Az OpenAPI és az NSwag ASP.NET-tel való használatával kapcsolatos további információkért tekintse meg az ASP.NET Core webes API-dokumentációját a Swagger/OpenAPI-val.
A Swagger eszközkészlet telepítése
Futtassa a következő parancsot:
dotnet add package NSwag.AspNetCore
Az előző parancs hozzáadja az NSwag.AspNetCore csomagot, amely swagger-dokumentumok és felhasználói felület létrehozásához szükséges eszközöket tartalmaz.
Swagger köztes szoftver konfigurálása
Adja hozzá a következő kiemelt kódot, mielőtt a
appmeg van határozva avar app = builder.Build();sorban.using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList")); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddOpenApiDocument(config => { config.DocumentName = "TodoAPI"; config.Title = "TodoAPI v1"; config.Version = "v1"; }); var app = builder.Build();
Az előző kódban:
builder.Services.AddEndpointsApiExplorer();: Engedélyezi az API Explorert, amely egy szolgáltatás, amely metaadatokat biztosít a HTTP API-ról. Az API Explorert a Swagger használja a Swagger-dokumentum létrehozásához.builder.Services.AddOpenApiDocument(config => {...});: Hozzáadja a Swagger OpenAPI-dokumentumgenerátort az alkalmazásszolgáltatásokhoz, és úgy konfigurálja, hogy további információt nyújtson az API-ról, például a címéről és a verziójáról. A robusztusabb API-részletekről további információt Az NSwag és ASP.NET Core használatának első lépéseit ismertető cikkben talál.Adja hozzá a következő kiemelt kódot abba a sorba, amelyik a
appután következik, miután avar app = builder.Build();definiálva van.var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseOpenApi(); app.UseSwaggerUi(config => { config.DocumentTitle = "TodoAPI"; config.Path = "/swagger"; config.DocumentPath = "/swagger/{documentName}/swagger.json"; config.DocExpansion = "list"; }); }Az előző kód lehetővé teszi a Swagger köztes szoftver számára a létrehozott JSON-dokumentum és a Swagger felhasználói felület kiszolgálását. A Swagger csak fejlesztési környezetben engedélyezett. A Swagger éles környezetben való engedélyezése potenciálisan bizalmas részleteket tehet közzé az API szerkezetéről és implementációjáról.
Közzétételi adatok tesztelése
A Program.cs következő kódja létrehoz egy HTTP POST-végpontot /todoitems, amely adatokat ad hozzá a memóriában lévő adatbázishoz:
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
Futtassa az alkalmazást. A böngésző 404-et jelenít meg, mert már nincs / végpont.
A POST végpont használatával adatokat adhat hozzá az alkalmazáshoz.
Ha az alkalmazás még mindig fut, a böngészőben navigáljon a
https://localhost:<port>/swaggeroldalra, hogy megjelenítse a Swagger által létrehozott API-tesztelő oldalt.
A Swagger API tesztelési oldalán válassza a Post /todoitems>Próbálja ki.
Vegye figyelembe, hogy a Kérelem törzs mező egy létrehozott példaformátumot tartalmaz, amely az API paramétereit tükrözi.
A kérelem törzsében adja meg a JSON-t egy to-do elemhez az opcionális
idmegadása nélkül:{ "name":"walk dog", "isComplete":true }Válassza a Végrehajtás lehetőséget.
A Swagger Válaszok panelt biztosít a Végrehajtás gomb alatt.
Jegyezze fel néhány hasznos részletet:
- cURL: A Swagger egy példa cURL-parancsot biztosít a Unix/Linux szintaxisban, amely futtatható a parancssorban bármilyen Unix/Linux szintaxist használó Bash-felülettel, beleértve a Git Basht Git for Windows.
- Kérelem URL-címe: A Swagger UI JavaScript-kódja által az API-híváshoz küldött HTTP-kérés egyszerűsített ábrázolása. A tényleges kérések tartalmazhatnak olyan részleteket, mint a fejlécek és a lekérdezési paraméterek, valamint a kérelem törzse.
- Kiszolgáló válasza: Tartalmazza a válasz törzsét és fejléceit. A válasz törzse azt mutatja, hogy a
id1értékre lett állítva. - Válaszkód: A rendszer egy 201-
HTTPállapotkódot adott vissza, amely azt jelzi, hogy a kérés feldolgozása sikeresen megtörtént, és egy új erőforrás létrehozását eredményezte.
A GET-végpontok vizsgálata
A mintaalkalmazás több GET-végpontot implementál MapGetmeghívásával:
| API | Description | A kérés tartalma | Válasz törzse |
|---|---|---|---|
GET /todoitems |
Az összes to-do elem lekérése | None | teendők tömbje |
GET /todoitems/complete |
Az összes kész to-do elem lekérése | None | teendők tömbje |
GET /todoitems/{id} |
Elem lekérése azonosító alapján | None | Teendő elem |
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
A GET-végpontok tesztelése
Tesztelje az alkalmazást úgy, hogy meghívja a végpontokat egy böngészőből vagy egy Swaggerből.
A Swaggerben válassza GET /todoitems>Próbálja ki>Hajtson végre.
Másik lehetőségként a GET /todoitems meghívása böngészőből az URI
http://localhost:<port>/todoitemsbeírásával. Példáulhttp://localhost:5001/todoitems
A GET /todoitems hívása a következőhöz hasonló választ ad:
[
{
"id": 1,
"name": "walk dog",
"isComplete": true
}
]
Hívja meg GET /todoitems/{id} a Swaggerben egy adott azonosító adatainak visszaadásához:
- Válassza GET /todoitems>Próbálja ki.
- Állítsa be a azonosító mezőt
1-re, és válassza a Végrehajtáslehetőséget.
Másik lehetőségként a GET /todoitems meghívása böngészőből az URI
https://localhost:<port>/todoitems/1beírásával. Példáulhttps://localhost:5001/todoitems/1A válasz a következőhöz hasonló:
{ "id": 1, "name": "walk dog", "isComplete": true }
Ez az alkalmazás memórián belüli adatbázist használ. Ha az alkalmazás újraindul, a GET kérés nem ad vissza adatokat. Ha nem ad vissza adatokat, POST adatokat az alkalmazásnak, és próbálkozzon újra a GET kéréssel.
Visszaadott értékek
ASP.NET Core automatikusan szerializálja az objektumot JSON formátumra, és beírja a JSON-t a válaszüzenet törzsébe. A visszatérési típus válaszkódja 200 OK, feltéve, hogy nincsenek kezeletlen kivételek. A nem kezelt kivételek 5xx-hibákká lesznek lefordítva.
A visszatérési típusok a HTTP-állapotkódok széles skáláját jelölhetik. A GET /todoitems/{id} például két különböző állapotértéket adhat vissza:
- Ha egyetlen elem sem felel meg a kért azonosítónak, a metódus egy 404-NotFound hibakódot ad vissza.
- Ellenkező esetben a metódus egy JSON-válasz törzsével adja vissza a 200-t. A
itemvisszaadása HTTP 200-választ eredményez.
A PUT végpont vizsgálata
A mintaalkalmazás egyetlen PUT-végpontot valósít meg MapPut:
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
Ez a módszer hasonló a MapPost metódushoz, kivéve, ha HTTP PUT-t használ. A sikeres válasz a 204 (tartalom nélkül) ad vissza. A HTTP-specifikáció szerint a PUT-kéréshez az ügyfélnek a teljes frissített entitást kell elküldenie, nem csak a módosításokat. A részleges frissítések támogatásához használja HTTP PATCH.
A PUT végpont tesztelése
Ez a minta egy memórián belüli adatbázist használ, amelyet az alkalmazás minden indításakor inicializálni kell. Az adatbázisnak tartalmaznia kell egy elemet, mielőtt PUT-hívást kezdeményezne. A GET hívásával győződjön meg arról, hogy van egy elem az adatbázisban, mielőtt PUT-hívást kezdeményez.
Frissítse a to-do elemet, amely Id = 1-t tartalmaz, és állítsa be a nevét "feed fish".
PUT-kérés küldése a Swagger használatával:
Válassza Put /todoitems/{id}>Próbálja ki.
Állítsa be a azonosító mezőjét
1értékre.Állítsa a kérelem törzsét a következő JSON-ra:
{ "name": "feed fish", "isComplete": false }Válassza a Végrehajtás lehetőséget.
A DELETE végpont vizsgálata és tesztelése
A mintaalkalmazás egyetlen DELETE-végpontot valósít meg MapDelete:
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
DELETE-kérés küldése a Swagger használatával:
Válassza DELETE /todoitems/{id}>Próbálja ki.
Állítsa be a azonosító mezőt
1, és válassza a Végrehajtáslehetőséget.A DELETE kérést elküldik az alkalmazásnak, és a válasz megjelenik a Válaszok panelen. A válasz törzse üres, és a kiszolgáló válasza állapotkódja 204.
A MapGroup API használata
A mintaalkalmazás kódja minden végpont beállításakor megismétli a todoitems URL-előtagot. Az API-k gyakran rendelkeznek közös URL-előtaggal rendelkező végpontcsoportokkal, és a MapGroup módszer segít az ilyen csoportok rendszerezésében. Csökkenti az ismétlődő kódot, és lehetővé teszi a végpontok teljes csoportjainak testreszabását egyetlen hívással az olyan metódusokhoz, mint a RequireAuthorization és a WithMetadata.
Cserélje le a Program.cs tartalmát a következő kódra:
using NSwag.AspNetCore;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddOpenApiDocument(config =>
{
config.DocumentName = "TodoAPI";
config.Title = "TodoAPI v1";
config.Version = "v1";
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseOpenApi();
app.UseSwaggerUi(config =>
{
config.DocumentTitle = "TodoAPI";
config.Path = "/swagger";
config.DocumentPath = "/swagger/{documentName}/swagger.json";
config.DocExpansion = "list";
});
}
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", async (TodoDb db) =>
await db.Todos.ToListAsync());
todoItems.MapGet("/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
todoItems.MapGet("/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
todoItems.MapPost("/", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
todoItems.MapDelete("/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Az előző kód a következő módosításokat tartalmazza:
- Hozzáad
var todoItems = app.MapGroup("/todoitems");a csoport beállításához az URL-előtag/todoitemshasználatával. - Módosítja az összes
app.Map<HttpVerb>metódusttodoItems.Map<HttpVerb>-re. - Eltávolítja a
/todoitemsURL-előtagot aMap<HttpVerb>metódushívásokból.
Tesztelje a végpontokat annak ellenőrzéséhez, hogy azonosak-e.
A TypedResults API használata
A TypedResults helyett a Results visszaadása számos előnnyel jár, beleértve a tesztelhetőséget, és automatikusan visszaadja a választípus metaadatait az OpenAPI-hoz a végpont leírásához. További információ: TypedResults vs Results.
A Map<HttpVerb> metódusok a lambdák használata helyett útvonalkezelő metódusokat is meghívhatnak. Egy példa megtekintéséhez frissítse a Program.cs a következő kóddal:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
A Map<HttpVerb> kód mostantól metódusokat hív meg a lambdas helyett:
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
Ezek a metódusok olyan objektumokat adnak vissza, amelyek IResult implementálnak, és amelyeket a TypedResultshatároznak meg:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Az egységtesztek meghívhatják ezeket a metódusokat, és tesztelhetik, hogy a megfelelő típust adja vissza. Ha például a módszer GetAllTodos:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
Az egységtesztelési kód képes ellenőrizni, hogy a kezelőmetódus visszaad-e egy Ok<Todo[]> típusú objektumot. Például:
public async Task GetAllTodos_ReturnsOkOfTodosResult()
{
// Arrange
var db = CreateDbContext();
// Act
var result = await TodosApi.GetAllTodos(db);
// Assert: Check for the correct returned type
Assert.IsType<Ok<Todo[]>>(result);
}
Túlküldés megakadályozása
A mintaalkalmazás jelenleg a teljes Todo objektumot teszi elérhetővé. Éles alkalmazások Éles alkalmazásokban a modell egy részhalmazát gyakran használják a bemeneti és visszaadható adatok korlátozására. Ennek több oka is van, és a biztonság a legfontosabb. A modell részhalmazát általában adatátviteli objektumnak (DTO), bemeneti modellnek vagy nézetmodellnek nevezzük. ebben a cikkben DTO- használunk.
A DTO a következőre használható:
- A túlküldés megakadályozása.
- Rejtse el azokat a tulajdonságokat, amelyeket az ügyfeleknek nem szabad megtekinteniük.
- Hagyj ki néhány tulajdonságot, hogy csökkentsük a hasznos teher méretét.
- Beágyazott objektumokat tartalmazó objektumdiagramok simítása. A laposabb objektumgráfok kényelmesebbek lehetnek az ügyfelek számára.
A DTO-megközelítés bemutatásához frissítse a Todo osztályt egy titkos mezőre:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
A titkos mezőt el kell rejteni az alkalmazás elől, de egy felügyeleti alkalmazás dönthet úgy, hogy közzéteszi.
Ellenőrizze, hogy közzéteheti és lekérheti-e a titkos kód mezőt.
Hozzon létre egy TodoItemDTO.cs nevű fájlt a következő kóddal:
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
Cserélje le a Program.cs fájl tartalmát a következő kódra a DTO-modell használatához:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
var app = builder.Build();
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.Select(x => new TodoItemDTO(x)).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(new TodoItemDTO(todo))
: Results.NotFound());
app.MapPost("/todoitems", async (TodoItemDTO todoItemDTO, TodoDb db) =>
{
var todoItem = new Todo
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
db.Todos.Add(todoItem);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todoItem.Id}", new TodoItemDTO(todoItem));
});
app.MapPut("/todoitems/{id}", async (int id, TodoItemDTO todoItemDTO, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = todoItemDTO.Name;
todo.IsComplete = todoItemDTO.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Ellenőrizze, hogy a titkos kód mező kivételével az összes mezőt közzéteheti és lekérheti.
Hibaelhárítás a kész mintával
Ha olyan problémába ütközik, amely nem oldható meg, hasonlítsa össze a kódot a befejezett projektel. Befejezett projekt megtekintése vagy letöltése (miként tölthető le).
Következő lépések
- JSON-szerializálási beállítások konfigurálása.
- Hibák és kivételek kezelése: A fejlesztői kivételoldal alapértelmezés szerint engedélyezve van a minimális API-alkalmazások fejlesztői környezetében. A hibák és kivételek kezeléséről további információt a ASP.NET Core API-k hibáinak kezelésecímű témakörben talál.
- Egy minimális API-alkalmazás tesztelésére példa: ez a GitHub-minta.
- OpenAPI-támogatás minimális API-kban.
- Gyorstalpaló: Közzététel az Azure-ra.
- ASP.NET Core Minimal API-krendszerezése.
Learn more
Tekintse meg Minimális API-k rövid útmutatója
A minimális API-k úgy vannak kialakítva, hogy minimális függőségekkel rendelkező HTTP API-kat hozzanak létre. Ideálisak olyan mikroszolgáltatásokhoz és alkalmazásokhoz, amelyek csak a minimális fájlokat, funkciókat és függőségeket szeretnék belefoglalni a ASP.NET Core-ba.
Ez az oktatóanyag a minimális API-k ASP.NET Core használatával történő létrehozásának alapjait mutatja be. Az API-k ASP.NET Core-ban való létrehozásának másik módszere a vezérlők használata. Ha segítségre van szüksége a minimális API-k és a vezérlőalapú API-k közötti választáshoz, tekintse meg API-k áttekintését. A további funkciókat tartalmazó vezérlők alapuló API-projektek létrehozásáról a Webes API-létrehozása című témakörben olvashat.
Overview
Ez az oktatóanyag a következő API-t hozza létre:
| API | Description | A kérés tartalma | Válasz törzse |
|---|---|---|---|
GET /todoitems |
Az összes to-do elem lekérése | None | teendők tömbje |
GET /todoitems/complete |
Kapj kész to-do elemeket | None | teendők tömbje |
GET /todoitems/{id} |
Elem lekérése azonosító alapján | None | Teendő elem |
POST /todoitems |
Új elem hozzáadása | Teendő elem | Teendő elem |
PUT /todoitems/{id} |
Meglévő elem frissítése | Teendő elem | None |
DELETE /todoitems/{id} |
Elem törlése | None | None |
Prerequisites
- Visual Studio 2022 az ASP.NET és webfejlesztés munkaállomással.
- .NET 6 SDK
API-projekt létrehozása
Indítsa el a Visual Studio 2022-t, és válassza Új projekt létrehozásalehetőséget.
Az Új projekt létrehozása párbeszédpanelen:
- Írja be
Emptya Sablonok keresése keresőmezőbe. - Válassza a ASP.NET Core Empty sablont, majd válassza a Következőlehetőséget.
- Írja be
Nevezze el a projektet TodoApi, és válassza a Továbblehetőséget.
A További információk párbeszédpanelen:
- Válassza .NET 6.0
- Törölje a jelölést Ne használjon legfelső szintű utasításokat
- Válassza a lehetőséget, hozza létre a lehetőséget
A kód vizsgálata
A Program.cs fájl a következő kódot tartalmazza:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző kód:
- Létrehoz egy WebApplicationBuilder és egy előre konfigurált alapértelmezett WebApplication.
- Létrehoz egy HTTP GET-végpontot
/, amelyHello World!ad vissza:
Az alkalmazás futtatása
Nyomja le a Ctrl+F5 billentyűkombinációt a hibakereső nélküli futtatáshoz.
A Visual Studio a következő párbeszédpanelt jeleníti meg:
Válassza Igen lehetőséget, ha megbízik az IIS Express SSL-tanúsítványban.
A következő párbeszédpanel jelenik meg:
Válassza Igen lehetőséget, ha elfogadja, hogy megbízik a fejlesztési tanúsítványban.
A Firefox böngésző megbízhatóságáról további információt a Firefox SEC_ERROR_INADEQUATE_KEY_USAGE tanúsítványhibacímű témakörben talál.
A Visual Studio elindítja a Kestrel webkiszolgáló, és megnyit egy böngészőablakot.
Hello World! megjelenik a böngészőben. A Program.cs fájl minimális, de teljes alkalmazást tartalmaz.
NuGet-csomagok hozzáadása
Az oktatóanyagban használt adatbázis és diagnosztikák támogatásához NuGet-csomagokat kell hozzáadni.
- Az Eszközök menüben válassza a NuGet Package Manager > Megoldáshoz készült NuGet-csomagok kezeléselehetőséget.
- Válassza a Tallózás lapot.
- Írja be Microsoft.EntityFrameworkCore.InMemory a keresőmezőbe, majd válassza a
Microsoft.EntityFrameworkCore.InMemory. - Jelölje be a Project jelölőnégyzetet a jobb oldali panelen.
- A Verzió legördülő listában válassza ki a legújabb elérhető 7-es verziót, például
6.0.28, majd válassza a Telepítéslehetőséget. - Az előző utasításokat követve adja hozzá a
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCorecsomagot a legújabb, 7-es verzióval.
A modell és az adatbázis környezeti osztályai
A projektmappában hozzon létre egy Todo.cs nevű fájlt a következő kóddal:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Az előző kód létrehozza az alkalmazás modelljét. A modell egy olyan osztály, amely az alkalmazás által kezelt adatokat jelöli.
Hozzon létre egy TodoDb.cs nevű fájlt a következő kóddal:
using Microsoft.EntityFrameworkCore;
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Az előző kód határozza meg az adatbázis-környezetet, amely az adatmodell Entity Framework funkcióit koordináló fő osztály. Ez az osztály a Microsoft.EntityFrameworkCore.DbContext osztályból származik.
Az API-kód hozzáadása
Cserélje le a Program.cs fájl tartalmát a következő kódra:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Az alábbi kiemelt kód hozzáadja az adatbázis-környezetet a függőséginjektálási (DI) tárolóhoz, és lehetővé teszi az adatbázissal kapcsolatos kivételek megjelenítését:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
A DI-tároló hozzáférést biztosít az adatbázis-környezethez és más szolgáltatásokhoz.
API-tesztelési felhasználói felület létrehozása a Swaggerrel
Számos elérhető webes API-tesztelési eszköz közül választhat, és az oktatóanyag bevezető API-tesztelési lépéseit saját előnyben részesített eszközével követheti.
Ez az oktatóanyag az NSwag.AspNetCore .NET-csomagot használja, amely integrálja a Swagger-eszközöket az OpenAPI-specifikációhoz tartozó tesztelési felhasználói felület létrehozásához:
- NSwag: .NET-kódtár, amely közvetlenül integrálja a Swaggert ASP.NET Core-alkalmazásokba, köztes szoftvereket és konfigurációt biztosítva.
- Swagger: Olyan nyílt forráskódú eszközök készlete, mint az OpenAPIGenerator és a SwaggerUI, amelyek az OpenAPI-specifikációt követő API-tesztoldalakat hoznak létre.
- OpenAPI-specifikáció: Az API képességeit leíró dokumentum a vezérlők és modellek XML- és attribútumjegyzetei alapján.
Az OpenAPI és az NSwag ASP.NET-tel való használatával kapcsolatos további információkért tekintse meg az ASP.NET Core webes API-dokumentációját a Swagger/OpenAPI-val.
A Swagger eszközkészlet telepítése
Futtassa a következő parancsot:
dotnet add package NSwag.AspNetCore
Az előző parancs hozzáadja az NSwag.AspNetCore csomagot, amely swagger-dokumentumok és felhasználói felület létrehozásához szükséges eszközöket tartalmaz.
Swagger köztes szoftver konfigurálása
A Program.cs fájlban adja hozzá a következő
usingutasításokat az elején:using NSwag.AspNetCore;Adja hozzá a következő kiemelt kódot, mielőtt a
appmeg van határozva avar app = builder.Build();sorban.using NSwag.AspNetCore; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList")); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddOpenApiDocument(config => { config.DocumentName = "TodoAPI"; config.Title = "TodoAPI v1"; config.Version = "v1"; }); var app = builder.Build();
Az előző kódban:
builder.Services.AddEndpointsApiExplorer();: Engedélyezi az API Explorert, amely egy szolgáltatás, amely metaadatokat biztosít a HTTP API-ról. Az API Explorert a Swagger használja a Swagger-dokumentum létrehozásához.builder.Services.AddOpenApiDocument(config => {...});: Hozzáadja a Swagger OpenAPI-dokumentumgenerátort az alkalmazásszolgáltatásokhoz, és úgy konfigurálja, hogy további információt nyújtson az API-ról, például a címéről és a verziójáról. A robusztusabb API-részletekről további információt Az NSwag és ASP.NET Core használatának első lépéseit ismertető cikkben talál.Adja hozzá a következő kiemelt kódot abba a sorba, amelyik a
appután következik, miután avar app = builder.Build();definiálva van.var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseOpenApi(); app.UseSwaggerUi(config => { config.DocumentTitle = "TodoAPI"; config.Path = "/swagger"; config.DocumentPath = "/swagger/{documentName}/swagger.json"; config.DocExpansion = "list"; }); }Az előző kód lehetővé teszi a Swagger köztes szoftver számára a létrehozott JSON-dokumentum és a Swagger felhasználói felület kiszolgálását. A Swagger csak fejlesztési környezetben engedélyezett. A Swagger éles környezetben való engedélyezése potenciálisan bizalmas részleteket tehet közzé az API szerkezetéről és implementációjáról.
Közzétételi adatok tesztelése
A Program.cs következő kódja létrehoz egy HTTP POST-végpontot /todoitems, amely adatokat ad hozzá a memóriában lévő adatbázishoz:
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
Futtassa az alkalmazást. A böngésző 404-et jelenít meg, mert már nincs / végpont.
A POST végpont használatával adatokat adhat hozzá az alkalmazáshoz.
Ha az alkalmazás még mindig fut, a böngészőben navigáljon a
https://localhost:<port>/swaggeroldalra, hogy megjelenítse a Swagger által létrehozott API-tesztelő oldalt.
A Swagger API tesztelési oldalán válassza a Post /todoitems>Próbálja ki.
Vegye figyelembe, hogy a Kérelem törzs mező egy létrehozott példaformátumot tartalmaz, amely az API paramétereit tükrözi.
A kérelem törzsében adja meg a JSON-t egy to-do elemhez az opcionális
idmegadása nélkül:{ "name":"walk dog", "isComplete":true }Válassza a Végrehajtás lehetőséget.
A Swagger Válaszok panelt biztosít a Végrehajtás gomb alatt.
Jegyezze fel néhány hasznos részletet:
- cURL: A Swagger egy példa cURL-parancsot biztosít a Unix/Linux szintaxisban, amely futtatható a parancssorban bármilyen Unix/Linux szintaxist használó Bash-felülettel, beleértve a Git Basht Git for Windows.
- Kérelem URL-címe: A Swagger UI JavaScript-kódja által az API-híváshoz küldött HTTP-kérés egyszerűsített ábrázolása. A tényleges kérések tartalmazhatnak olyan részleteket, mint a fejlécek és a lekérdezési paraméterek, valamint a kérelem törzse.
- Kiszolgáló válasza: Tartalmazza a válasz törzsét és fejléceit. A válasz törzse azt mutatja, hogy a
id1értékre lett állítva. - Válaszkód: A rendszer egy 201-
HTTPállapotkódot adott vissza, amely azt jelzi, hogy a kérés feldolgozása sikeresen megtörtént, és egy új erőforrás létrehozását eredményezte.
A GET-végpontok vizsgálata
A mintaalkalmazás több GET-végpontot implementál MapGetmeghívásával:
| API | Description | A kérés tartalma | Válasz törzse |
|---|---|---|---|
GET /todoitems |
Az összes to-do elem lekérése | None | teendők tömbje |
GET /todoitems/complete |
Az összes kész to-do elem lekérése | None | teendők tömbje |
GET /todoitems/{id} |
Elem lekérése azonosító alapján | None | Teendő elem |
app.MapGet("/", () => "Hello World!");
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
A GET-végpontok tesztelése
Tesztelje az alkalmazást úgy, hogy meghívja a végpontokat egy böngészőből vagy egy Swaggerből.
A Swaggerben válassza GET /todoitems>Próbálja ki>Hajtson végre.
Másik lehetőségként a GET /todoitems meghívása böngészőből az URI
http://localhost:<port>/todoitemsbeírásával. Példáulhttp://localhost:5001/todoitems
A GET /todoitems hívása a következőhöz hasonló választ ad:
[
{
"id": 1,
"name": "walk dog",
"isComplete": true
}
]
Hívja meg GET /todoitems/{id} a Swaggerben egy adott azonosító adatainak visszaadásához:
- Válassza GET /todoitems>Próbálja ki.
- Állítsa be a azonosító mezőt
1-re, és válassza a Végrehajtáslehetőséget.
Másik lehetőségként a GET /todoitems meghívása böngészőből az URI
https://localhost:<port>/todoitems/1beírásával. Például:https://localhost:5001/todoitems/1A válasz a következőhöz hasonló:
{ "id": 1, "name": "walk dog", "isComplete": true }
Ez az alkalmazás memórián belüli adatbázist használ. Ha az alkalmazás újraindul, a GET kérés nem ad vissza adatokat. Ha nem ad vissza adatokat, POST adatokat az alkalmazásnak, és próbálkozzon újra a GET kéréssel.
Visszaadott értékek
ASP.NET Core automatikusan szerializálja az objektumot JSON formátumra, és beírja a JSON-t a válaszüzenet törzsébe. A visszatérési típus válaszkódja 200 OK, feltéve, hogy nincsenek kezeletlen kivételek. A nem kezelt kivételek 5xx-hibákká lesznek lefordítva.
A visszatérési típusok a HTTP-állapotkódok széles skáláját jelölhetik. A GET /todoitems/{id} például két különböző állapotértéket adhat vissza:
- Ha egyetlen elem sem felel meg a kért azonosítónak, a metódus egy 404-NotFound hibakódot ad vissza.
- Ellenkező esetben a metódus egy JSON-válasz törzsével adja vissza a 200-t. A
itemvisszaadása HTTP 200-választ eredményez.
A PUT végpont vizsgálata
A mintaalkalmazás egyetlen PUT-végpontot valósít meg MapPut:
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
Ez a módszer hasonló a MapPost metódushoz, kivéve, ha HTTP PUT-t használ. A sikeres válasz a 204 (tartalom nélkül) ad vissza. A HTTP-specifikáció szerint a PUT-kéréshez az ügyfélnek a teljes frissített entitást kell elküldenie, nem csak a módosításokat. A részleges frissítések támogatásához használja HTTP PATCH.
A PUT végpont tesztelése
Ez a minta egy memórián belüli adatbázist használ, amelyet az alkalmazás minden indításakor inicializálni kell. Az adatbázisnak tartalmaznia kell egy elemet, mielőtt PUT-hívást kezdeményezne. A GET hívásával győződjön meg arról, hogy van egy elem az adatbázisban, mielőtt PUT-hívást kezdeményez.
Frissítse a to-do elemet, amely Id = 1-t tartalmaz, és állítsa be a nevét "feed fish".
PUT-kérés küldése a Swagger használatával:
Válassza Put /todoitems/{id}>Próbálja ki.
Állítsa be a azonosító mezőjét
1értékre.Állítsa a kérelem törzsét a következő JSON-ra:
{ "name": "feed fish", "isComplete": false }Válassza a Végrehajtás lehetőséget.
A DELETE végpont vizsgálata és tesztelése
A mintaalkalmazás egyetlen DELETE-végpontot valósít meg MapDelete:
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
DELETE-kérés küldése a Swagger használatával:
Válassza DELETE /todoitems/{id}>Próbálja ki.
Állítsa be a azonosító mezőt
1, és válassza a Végrehajtáslehetőséget.A DELETE kérést elküldik az alkalmazásnak, és a válasz megjelenik a Válaszok panelen. A válasz törzse üres, és a kiszolgáló válasza állapotkódja 204.
Túlküldés megakadályozása
A mintaalkalmazás jelenleg a teljes Todo objektumot teszi elérhetővé. Éles alkalmazások Éles alkalmazásokban a modell egy részhalmazát gyakran használják a bemeneti és visszaadható adatok korlátozására. Ennek több oka is van, és a biztonság a legfontosabb. A modell részhalmazát általában adatátviteli objektumnak (DTO), bemeneti modellnek vagy nézetmodellnek nevezzük. ebben a cikkben DTO- használunk.
A DTO a következőre használható:
- A túlküldés megakadályozása.
- Rejtse el azokat a tulajdonságokat, amelyeket az ügyfeleknek nem szabad megtekinteniük.
- Hagyj ki néhány tulajdonságot, hogy csökkentsük a hasznos teher méretét.
- Beágyazott objektumokat tartalmazó objektumdiagramok simítása. A laposabb objektumgráfok kényelmesebbek lehetnek az ügyfelek számára.
A DTO-megközelítés bemutatásához frissítse a Todo osztályt egy titkos mezőre:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
A titkos mezőt el kell rejteni az alkalmazás elől, de egy felügyeleti alkalmazás dönthet úgy, hogy közzéteszi.
Ellenőrizze, hogy közzéteheti és lekérheti-e a titkos kód mezőt.
Hozzon létre egy TodoItemDTO.cs nevű fájlt a következő kóddal:
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
Cserélje le a Program.cs fájl tartalmát a következő kódra a DTO-modell használatához:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
var app = builder.Build();
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.Select(x => new TodoItemDTO(x)).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(new TodoItemDTO(todo))
: Results.NotFound());
app.MapPost("/todoitems", async (TodoItemDTO todoItemDTO, TodoDb db) =>
{
var todoItem = new Todo
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
db.Todos.Add(todoItem);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todoItem.Id}", new TodoItemDTO(todoItem));
});
app.MapPut("/todoitems/{id}", async (int id, TodoItemDTO todoItemDTO, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = todoItemDTO.Name;
todo.IsComplete = todoItemDTO.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Ellenőrizze, hogy a titkos kód mező kivételével az összes mezőt közzéteheti és lekérheti.
Minimális API tesztelése
Egy minimális API-alkalmazás tesztelésére példa: ez a GitHub-minta.
Közzététel az Azure-ban
Az Azure-ban való üzembe helyezésről további információért lásd: Gyorsútmutató: ASP.NET webalkalmazás üzembe helyezése.
További erőforrások
A minimális API-k úgy vannak kialakítva, hogy minimális függőségekkel rendelkező HTTP API-kat hozzanak létre. Olyan mikroszolgáltatásokhoz és alkalmazásokhoz ideálisak, amelyek csak a minimális fájlokat, funkciókat és függőségeket szeretnék belefoglalni a ASP.NET Core-ba.
Ez az oktatóanyag a minimális API-k ASP.NET Core használatával történő létrehozásának alapjait mutatja be. Az API-k ASP.NET Core-ban való létrehozásának másik módszere a vezérlők használata. Ha segítségre van szüksége a minimális API-k és a vezérlőalapú API-k közötti választáshoz, tekintse meg API-k áttekintését. A további funkciókat tartalmazó vezérlők alapuló API-projektek létrehozásáról a Webes API-létrehozása című témakörben olvashat.
Overview
Ez az oktatóanyag a következő API-t hozza létre:
| API | Description | A kérés tartalma | Válasz törzse |
|---|---|---|---|
GET /todoitems |
Az összes to-do elem lekérése | None | teendők tömbje |
GET /todoitems/complete |
Kapj kész to-do elemeket | None | teendők tömbje |
GET /todoitems/{id} |
Elem lekérése azonosító alapján | None | Teendő elem |
POST /todoitems |
Új elem hozzáadása | Teendő elem | Teendő elem |
PUT /todoitems/{id} |
Meglévő elem frissítése | Teendő elem | None |
DELETE /todoitems/{id} |
Elem törlése | None | None |
Prerequisites
Visual Studio 2022 az ASP.NET és webfejlesztés munkaállomással.
API-projekt létrehozása
Indítsa el a Visual Studio 2022-t, és válassza Új projekt létrehozásalehetőséget.
Az Új projekt létrehozása párbeszédpanelen:
- Írja be
Emptya Sablonok keresése keresőmezőbe. - Válassza a ASP.NET Core Empty sablont, majd válassza a Következőlehetőséget.
- Írja be
Nevezze el a projektet TodoApi, és válassza a Továbblehetőséget.
A További információk párbeszédpanelen:
- Válassza .NET 8.0 (hosszú távú támogatás)
- Törölje a jelölést Ne használjon legfelső szintű utasításokat
- Válassza a lehetőséget, hozza létre a lehetőséget
A kód vizsgálata
A Program.cs fájl a következő kódot tartalmazza:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző kód:
- Létrehoz egy WebApplicationBuilder és egy előre konfigurált alapértelmezett WebApplication.
- Létrehoz egy HTTP GET-végpontot
/, amelyHello World!ad vissza:
Az alkalmazás futtatása
Nyomja le a Ctrl+F5 billentyűkombinációt a hibakereső nélküli futtatáshoz.
A Visual Studio a következő párbeszédpanelt jeleníti meg:
Válassza Igen lehetőséget, ha megbízik az IIS Express SSL-tanúsítványban.
A következő párbeszédpanel jelenik meg:
Válassza Igen lehetőséget, ha elfogadja, hogy megbízik a fejlesztési tanúsítványban.
A Firefox böngésző megbízhatóságáról további információt a Firefox SEC_ERROR_INADEQUATE_KEY_USAGE tanúsítványhibacímű témakörben talál.
A Visual Studio elindítja a Kestrel webkiszolgáló, és megnyit egy böngészőablakot.
Hello World! megjelenik a böngészőben. A Program.cs fájl minimális, de teljes alkalmazást tartalmaz.
Zárja be a böngészőablakot.
NuGet-csomagok hozzáadása
Az oktatóanyagban használt adatbázis és diagnosztikák támogatásához NuGet-csomagokat kell hozzáadni.
- Az Eszközök menüben válassza a NuGet Package Manager > Megoldáshoz készült NuGet-csomagok kezeléselehetőséget.
- Válassza a Tallózás lapot.
- Írja be Microsoft.EntityFrameworkCore.InMemory a keresőmezőbe, majd válassza a
Microsoft.EntityFrameworkCore.InMemory. - Jelölje be a Project jelölőnégyzetet a jobb oldali panelen, majd válassza a Telepítéslehetőséget.
- A
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCorecsomag hozzáadásához kövesse az előző utasításokat.
A modell és az adatbázis környezeti osztályai
- A projektmappában hozzon létre egy
Todo.csnevű fájlt a következő kóddal:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Az előző kód létrehozza az alkalmazás modelljét. A modell egy olyan osztály, amely az alkalmazás által kezelt adatokat jelöli.
- Hozzon létre egy
TodoDb.csnevű fájlt a következő kóddal:
using Microsoft.EntityFrameworkCore;
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Az előző kód határozza meg az adatbázis-környezetet, amely az adatmodell Entity Framework funkcióit koordináló fő osztály. Ez az osztály a Microsoft.EntityFrameworkCore.DbContext osztályból származik.
Az API-kód hozzáadása
- Cserélje le a
Program.csfájl tartalmát a következő kódra:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Az alábbi kiemelt kód hozzáadja az adatbázis-környezetet a függőséginjektálási (DI) tárolóhoz, és lehetővé teszi az adatbázissal kapcsolatos kivételek megjelenítését:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
A DI-tároló hozzáférést biztosít az adatbázis-környezethez és más szolgáltatásokhoz.
Ez az oktatóanyag az Endpoints Explorer-t és a .http fájlokat használja az API teszteléséhez.
Közzétételi adatok tesztelése
A Program.cs következő kódja létrehoz egy HTTP POST-végpontot /todoitems, amely adatokat ad hozzá a memóriában lévő adatbázishoz:
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
Futtassa az alkalmazást. A böngésző 404-et jelenít meg, mert már nincs / végpont.
A POST végpont használatával adatokat adhat hozzá az alkalmazáshoz.
Válassza a Nézet>Egyéb ablakok>Endpoints Explorer.
Kattintson a jobb gombbal a POST végpontra, és válassza a Kérés létrehozásalehetőséget.
Egy új fájl jön létre a
TodoApi.httpnevű projektmappában, amely a következő példához hasonló tartalommal rendelkezik:@TodoApi_HostAddress = https://localhost:7031 Post {{TodoApi_HostAddress}}/todoitems ###- Az első sor létrehoz egy változót, amelyet az összes végponthoz használnak.
- A következő sor egy POST-kérést határoz meg.
- A tripla hashtag (
###) sor egy kérések közötti elválasztó jel: ami utána következik, az egy másik kéréshez tartozik.
A POST-kérelemhez fejlécekre és tartalomra van szükség. A kérelem ezen részeinek meghatározásához közvetlenül a POST kérelemsor után adja hozzá a következő sorokat:
Content-Type: application/json { "name":"walk dog", "isComplete":true }Az előző kód hozzáad egy Tartalomtípus fejlécet és egy JSON-kérelemtörzset. A TodoApi.http fájlnak most az alábbi példához hasonlóan kell kinéznie, de a portszámmal:
@TodoApi_HostAddress = https://localhost:7057 Post {{TodoApi_HostAddress}}/todoitems Content-Type: application/json { "name":"walk dog", "isComplete":true } ###Futtassa az alkalmazást.
Válassza a Kérés küldése hivatkozást, amely a
POSTkérelemsor felett található.
A POST kérést a rendszer elküldi az alkalmazásnak, és a válasz megjelenik a Válasz panelen.
A GET-végpontok vizsgálata
A mintaalkalmazás több GET-végpontot implementál MapGetmeghívásával:
| API | Description | A kérés tartalma | Válasz törzse |
|---|---|---|---|
GET /todoitems |
Az összes to-do elem lekérése | None | teendők tömbje |
GET /todoitems/complete |
Az összes kész to-do elem lekérése | None | teendők tömbje |
GET /todoitems/{id} |
Elem lekérése azonosító alapján | None | Teendő elem |
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
A GET-végpontok tesztelése
Tesztelje az alkalmazást a GET végpontok böngészőből való meghívásával vagy Endpoints Explorerhasználatával. Az alábbi lépések a Endpoints Explorer-hez tartoznak.
Az Endpoints Explorerterületen kattintson a jobb gombbal az első GET végpontra, és válassza a Kérés létrehozásalehetőséget.
A következő tartalom lesz hozzáadva a
TodoApi.httpfájlhoz:Get {{TodoApi_HostAddress}}/todoitems ###Válassza a Kérés küldése hivatkozást, amely az új
GETkérelemsor felett található.A GET kérést a rendszer elküldi az alkalmazásnak, és a válasz megjelenik a Válasz panelen.
A válasz törzse a következő JSON-hoz hasonló:
[ { "id": 1, "name": "walk dog", "isComplete": true } ]Az Endpoints Explorerterületen kattintson a jobb gombbal a
/todoitems/{id}GET végpontra, és válassza a Kérés létrehozásalehetőséget. A következő tartalom lesz hozzáadva aTodoApi.httpfájlhoz:GET {{TodoApi_HostAddress}}/todoitems/{id} ###Cserélje le
{id}1.Válassza a Kérés küldése hivatkozást, amely az új GET kérelemsor felett található.
A GET kérést a rendszer elküldi az alkalmazásnak, és a válasz megjelenik a Válasz panelen.
A válasz törzse a következő JSON-hoz hasonló:
{ "id": 1, "name": "walk dog", "isComplete": true }
Ez az alkalmazás memórián belüli adatbázist használ. Ha az alkalmazás újraindul, a GET kérés nem ad vissza adatokat. Ha nem ad vissza adatokat, POST adatokat az alkalmazásnak, és próbálkozzon újra a GET kéréssel.
Visszaadott értékek
ASP.NET Core automatikusan szerializálja az objektumot JSON formátumra, és beírja a JSON-t a válaszüzenet törzsébe. A visszatérési típus válaszkódja 200 OK, feltéve, hogy nincsenek kezeletlen kivételek. A nem kezelt kivételek 5xx-hibákká lesznek lefordítva.
A visszatérési típusok a HTTP-állapotkódok széles skáláját jelölhetik. A GET /todoitems/{id} például két különböző állapotértéket adhat vissza:
- Ha egyetlen elem sem felel meg a kért azonosítónak, a metódus egy 404-NotFound hibakódot ad vissza.
- Ellenkező esetben a metódus egy JSON-válasz törzsével adja vissza a 200-t. A
itemvisszaadása HTTP 200-választ eredményez.
A PUT végpont vizsgálata
A mintaalkalmazás egyetlen PUT-végpontot valósít meg MapPut:
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
Ez a módszer hasonló a MapPost metódushoz, kivéve, ha HTTP PUT-t használ. A sikeres válasz a 204 (tartalom nélkül) ad vissza. A HTTP-specifikáció szerint a PUT-kéréshez az ügyfélnek a teljes frissített entitást kell elküldenie, nem csak a módosításokat. A részleges frissítések támogatásához használja HTTP PATCH.
A PUT végpont tesztelése
Ez a minta egy memórián belüli adatbázist használ, amelyet az alkalmazás minden indításakor inicializálni kell. Az adatbázisnak tartalmaznia kell egy elemet, mielőtt PUT-hívást kezdeményezne. A GET hívásával győződjön meg arról, hogy van egy elem az adatbázisban, mielőtt PUT-hívást kezdeményez.
Frissítse a to-do elemet, amely Id = 1-t tartalmaz, és állítsa be a nevét "feed fish".
Az Endpoints Explorer-ben kattintson a jobb gombbal a PUT végpontra, és válassza a Kérés létrehozásalehetőséget.
A következő tartalom lesz hozzáadva a
TodoApi.httpfájlhoz:Put {{TodoApi_HostAddress}}/todoitems/{id} ###A PUT kérelemsorban cserélje le a
{id}1.Közvetlenül a PUT kérelemsor után adja hozzá a következő sorokat:
Content-Type: application/json { "name": "feed fish", "isComplete": false }Az előző kód hozzáad egy Tartalomtípus fejlécet és egy JSON-kérelemtörzset.
Válassza a Kérés küldése hivatkozást, amely az új PUT kérelemsor felett található.
A PUT kérést a rendszer elküldi az alkalmazásnak, és a válasz megjelenik a Válasz panelen. A válasz törzse üres, az állapotkód pedig 204.
A DELETE végpont vizsgálata és tesztelése
A mintaalkalmazás egyetlen DELETE-végpontot valósít meg MapDelete:
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
Az Endpoints Explorerterületen kattintson a jobb gombbal a DELETE végpontra, és válassza a Kérés létrehozásalehetőséget.
Hozzá van adva egy DELETE kérés a
TodoApi.http-hoz.A
{id}helyett1-et használjon a DELETE kérelemsorban. A DELETE kérésnek a következő példához hasonlóan kell kinéznie:DELETE {{TodoApi_HostAddress}}/todoitems/1 ###Válassza a Küldési kérelem hivatkozást a DELETE kéréshez.
A DELETE kérést a rendszer elküldi az alkalmazásnak, és a válasz megjelenik a Válasz panelen. A válasz törzse üres, az állapotkód pedig 204.
A MapGroup API használata
A mintaalkalmazás kódja minden végpont beállításakor megismétli a todoitems URL-előtagot. Az API-k gyakran rendelkeznek közös URL-előtaggal rendelkező végpontcsoportokkal, és a MapGroup módszer segít az ilyen csoportok rendszerezésében. Csökkenti az ismétlődő kódot, és lehetővé teszi a végpontok teljes csoportjainak testreszabását egyetlen hívással az olyan metódusokhoz, mint a RequireAuthorization és a WithMetadata.
Cserélje le a Program.cs tartalmát a következő kódra:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", async (TodoDb db) =>
await db.Todos.ToListAsync());
todoItems.MapGet("/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
todoItems.MapGet("/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
todoItems.MapPost("/", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
todoItems.MapDelete("/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Az előző kód a következő módosításokat tartalmazza:
- Hozzáad
var todoItems = app.MapGroup("/todoitems");a csoport beállításához az URL-előtag/todoitemshasználatával. - Módosítja az összes
app.Map<HttpVerb>metódusttodoItems.Map<HttpVerb>-re. - Eltávolítja a
/todoitemsURL-előtagot aMap<HttpVerb>metódushívásokból.
Tesztelje a végpontokat annak ellenőrzéséhez, hogy azonosak-e.
A TypedResults API használata
A TypedResults helyett a Results visszaadása számos előnnyel jár, beleértve a tesztelhetőséget, és automatikusan visszaadja a választípus metaadatait az OpenAPI-hoz a végpont leírásához. További információ: TypedResults vs Results.
A Map<HttpVerb> metódusok a lambdák használata helyett útvonalkezelő metódusokat is meghívhatnak. Egy példa megtekintéséhez frissítse a Program.cs a következő kóddal:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
A Map<HttpVerb> kód mostantól metódusokat hív meg a lambdas helyett:
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
Ezek a metódusok olyan objektumokat adnak vissza, amelyek IResult implementálnak, és amelyeket a TypedResultshatároznak meg:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Az egységtesztek meghívhatják ezeket a metódusokat, és tesztelhetik, hogy a megfelelő típust adja vissza. Ha például a módszer GetAllTodos:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
Az egységtesztelési kód képes ellenőrizni, hogy a kezelőmetódus visszaad-e egy Ok<Todo[]> típusú objektumot. Például:
public async Task GetAllTodos_ReturnsOkOfTodosResult()
{
// Arrange
var db = CreateDbContext();
// Act
var result = await TodosApi.GetAllTodos(db);
// Assert: Check for the correct returned type
Assert.IsType<Ok<Todo[]>>(result);
}
Túlküldés megakadályozása
A mintaalkalmazás jelenleg a teljes Todo objektumot teszi elérhetővé. Éles alkalmazások Éles alkalmazásokban a modell egy részhalmazát gyakran használják a bemeneti és visszaadható adatok korlátozására. Ennek több oka is van, és a biztonság a legfontosabb. A modell részhalmazát általában adatátviteli objektumnak (DTO), bemeneti modellnek vagy nézetmodellnek nevezzük. ebben a cikkben DTO- használunk.
A DTO a következőre használható:
- A túlküldés megakadályozása.
- Rejtse el azokat a tulajdonságokat, amelyeket az ügyfeleknek nem szabad megtekinteniük.
- Hagyj ki néhány tulajdonságot, hogy csökkentsük a hasznos teher méretét.
- Beágyazott objektumokat tartalmazó objektumdiagramok simítása. A laposabb objektumgráfok kényelmesebbek lehetnek az ügyfelek számára.
A DTO-megközelítés bemutatásához frissítse a Todo osztályt egy titkos mezőre:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
A titkos mezőt el kell rejteni az alkalmazás elől, de egy felügyeleti alkalmazás dönthet úgy, hogy közzéteszi.
Ellenőrizze, hogy közzéteheti és lekérheti-e a titkos kód mezőt.
Hozzon létre egy TodoItemDTO.cs nevű fájlt a következő kóddal:
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
Cserélje le a Program.cs fájl tartalmát a következő kódra a DTO-modell használatához:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
RouteGroupBuilder todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Select(x => new TodoItemDTO(x)).ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db) {
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).Select(x => new TodoItemDTO(x)).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(new TodoItemDTO(todo))
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(TodoItemDTO todoItemDTO, TodoDb db)
{
var todoItem = new Todo
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
db.Todos.Add(todoItem);
await db.SaveChangesAsync();
todoItemDTO = new TodoItemDTO(todoItem);
return TypedResults.Created($"/todoitems/{todoItem.Id}", todoItemDTO);
}
static async Task<IResult> UpdateTodo(int id, TodoItemDTO todoItemDTO, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = todoItemDTO.Name;
todo.IsComplete = todoItemDTO.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Ellenőrizze, hogy a titkos kód mező kivételével az összes mezőt közzéteheti és lekérheti.
Hibaelhárítás a kész mintával
Ha olyan problémába ütközik, amely nem oldható meg, hasonlítsa össze a kódot a befejezett projektel. Befejezett projekt megtekintése vagy letöltése (miként tölthető le).
Következő lépések
- JSON-szerializálási beállítások konfigurálása.
- Hibák és kivételek kezelése: A fejlesztői kivételoldal alapértelmezés szerint engedélyezve van a minimális API-alkalmazások fejlesztői környezetében. A hibák és kivételek kezeléséről további információt a ASP.NET Core API-k hibáinak kezelésecímű témakörben talál.
- Egy minimális API-alkalmazás tesztelésére példa: ez a GitHub-minta.
- OpenAPI-támogatás minimális API-kban.
- Gyorstalpaló: Közzététel az Azure-ra.
- ASP.NET Core Minimal API-krendszerezése.
Learn more
Tekintse meg Minimális API-k rövid útmutatója