ASP.NET Core: Hướng dẫn tạo API tối thiểu với ASP.NET Core
API tối thiểu được thiết kế để tạo API HTTP với các phụ thuộc tối thiểu. Chúng rất lý tưởng cho các vi dịch vụ và ứng dụng chỉ muốn bao gồm các tệp, tính năng và phần phụ thuộc tối thiểu trong ASP.NET Core.
Hướng dẫn này dạy những kiến thức cơ bản về xây dựng một API tối thiểu với ASP.NET Core. Một cách tiếp cận khác để tạo API trong ASP.NET Core là sử dụng controller. Để được trợ giúp trong việc lựa chọn giữa API tối thiểu và API dựa trên controller, hãy xem Chọn giữa API dựa trên controller và API tối thiểu. Để biết hướng dẫn về cách tạo dự án API dựa trên controller nhiều tính năng hơn, hãy xem Tạo một API web.
Tổng quan
Hướng dẫn này tạo API sau:
API | Mô tả | Request body | Response body |
---|---|---|---|
GET /api/todoitems |
Nhận tất cả các mục việc cần làm | Không có | Mảng việc cần làm |
GET /api/todoitems/{id} |
Nhận một mục theo ID | Không có | Mục việc cần làm |
POST /api/todoitems |
Thêm một mục mới | Mục việc cần làm | Mục việc cần làm |
PUT /api/todoitems/{id} |
Cập nhật một mục hiện có | Mục việc cần làm | Không có |
DELETE /api/todoitems/{id} |
Xóa một mục | Không có | Không có |
Điều kiện tiên quyết
Visual Studio 2022 đã cài đặt ASP.NET and web development.
Tạo một dự án API
- Khởi động Visual Studio 2022 và chọn Create a new project.
- Trong hộp thoại Create a new project:
- Nhập
Empty
vào hộp tìm kiếm Search for templates. - Chọn mẫu ASP.NET Core Empty và chọn Next.
- Nhập
- Đặt tên dự án là TodoApi và chọn Next.
- Trong hộp thoại Additional information:
- Chọn .NET 7.0
- Bỏ chọn Do not use top-level statements
- Chọn Create
Kiểm tra code
Tệp Program.cs
chứa code sau:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Trong đoạn code trên:
- Tạo một WebApplicationBuilder và một WebApplication với các giá trị mặc định được cấu hình sẵn.
- Tạo một điểm cuối HTTP GET / trả về
Hello World!
:
Chạy ứng dụng
Nhấn Ctrl+F5 để chạy mà không cần trình gỡ lỗi.
Visual Studio hiển thị hộp thoại sau:
Chọn Yes nếu bạn tin cậy chứng chỉ SSL IIS Express.
Hộp thoại sau được hiển thị:
Chọn Yes nếu bạn đồng ý tin cậy chứng chỉ phát triển.
Để biết thông tin về cách tin cậy trình duyệt Firefox, hãy xem lỗi chứng chỉ Firefox SEC_ERROR_INADEQUATE_KEY_USAGE.
Visual Studio khởi chạy máy chủ web Kestrel và mở một cửa sổ trình duyệt.
Hello World!
được hiển thị trong trình duyệt. Tệp Program.cs
chứa một ứng dụng tối thiểu nhưng đầy đủ.
Thêm gói NuGet
Các gói NuGet phải được thêm vào để hỗ trợ cơ sở dữ liệu và chẩn đoán được sử dụng trong hướng dẫn này.
- Từ menu Tools, chọn NuGet Package Manager > Manage NuGet Packages for Solution.
- Chọn tab Browse.
- Nhập Microsoft.EntityFrameworkCore.InMemory vào hộp tìm kiếm rồi chọn
Microsoft.EntityFrameworkCore.InMemory
. - Chọn hộp kiểm Project trong ngăn bên phải rồi chọn Install.
- Thực hiện theo các hướng dẫn trước đó để thêm gói
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
.
Các lớp database context và model
Trong thư mục dự án, tạo một tệp có tên Todo.cs
bằng code sau:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Code trên tạo model cho ứng dụng này. Model là một lớp đại diện cho dữ liệu mà ứng dụng quản lý.
Tạo một tệp có tên TodoDb.cs
với code sau:
using Microsoft.EntityFrameworkCore;
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Đoạn code trên định nghĩa database context, là lớp chính phối hợp chức năng Entity Framework cho một model dữ liệu. Lớp này bắt nguồn từ lớp Microsoft.EntityFrameworkCore.DbContext.
Thêm code API
Thay thế nội dung của file Program.cs
bằng code sau:
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();
Code được đánh dấu sau đây sẽ thêm database context vào bộ chứa nội dung Dependency Injection (DI) và cho phép hiển thị các ngoại lệ liên quan đến cơ sở dữ liệu:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
Bộ chứa DI cung cấp quyền truy cập vào database context và các dịch vụ khác.
Cài đặt Postman để kiểm tra ứng dụng
Hướng dẫn này sử dụng Postman để kiểm tra API.
- Cài đặt Postman
- Khởi động ứng dụng web.
- Khởi động Postman.
- Chọn Workspaces > Create Workspace rồi chọn Next.
- Đặt tên cho workspace là TodoApi và chọn Create.
- Chọn biểu tượng bánh răng cài đặt > Settings (General tab) và tắt SSL certificate verification.
Cảnh báo
Bật lại SSL certificate verification sau khi kiểm tra ứng dụng mẫu.
Kiểm thử đăng dữ liệu
Đoạn code sau trong Program.cs
tạo điểm cuối (endpoint) HTTP POST /todoitems
để thêm dữ liệu vào cơ sở dữ liệu trong bộ nhớ:
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
Chạy ứng dụng. Trình duyệt hiển thị lỗi 404 vì không còn điểm cuối /
.
Sử dụng điểm cuối POST để thêm dữ liệu vào ứng dụng:
- Trong Postman, tạo một yêu cầu HTTP mới bằng cách chọn New > HTTP.
- Đặt phương thức HTTP thành
POST
. - Đặt URI thành
https://localhost:<port>/todoitems
. Ví dụ:https://localhost:5001/todoitems
- Chọn tab Body.
- Chọn raw.
- Đặt type thành JSON.
- Trong phần thân yêu cầu, hãy nhập JSON cho mục việc cần làm:
{
"name":"walk dog",
"isComplete":true
}
- Chọn Send.
Kiểm tra các điểm cuối GET
Ứng dụng mẫu triển khai một số điểm cuối GET bằng cách gọi MapGet
:
API | Mô tả | Request body | Response body |
---|---|---|---|
GET /todoitems |
Nhận tất cả các mục việc cần làm | Không có | Mảng việc cần làm |
GET /todoitems/complete |
Nhận tất cả các mục việc cần làm đã hoàn thành | Không có | Mảng việc cần làm |
GET /todoitems/{id} |
Nhận một mục theo ID | Không có | Mục việc cần làm |
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());
Kiểm thử các điểm cuối GET
Kiểm tra ứng dụng bằng cách gọi các điểm cuối từ trình duyệt hoặc Postman. Các bước sau đây dành cho Postman.
- Tạo một yêu cầu HTTP mới.
- Đặt phương thức HTTP thành GET.
- Đặt URI yêu cầu thành
https://localhost:<port>/todoitems
. Ví dụ,https://localhost:5001/todoitems
. - Chọn Send.
Lời gọi để GET /todoitems
tạo ra một phản hồi tương tự như sau:
[
{
"id": 1,
"name": "walk dog",
"isComplete": false
}
]
- Đặt URI yêu cầu thành
https://localhost:<port>/todoitems/1
. Ví dụ,https://localhost:5001/todoitems/1
. - Chọn Send.
- Câu trả lời tương tự như sau:
{ "id": 1, "name": "walk dog", "isComplete": false }
Ứng dụng này sử dụng cơ sở dữ liệu trong bộ nhớ. Nếu ứng dụng được khởi động lại, yêu cầu GET sẽ không trả về bất kỳ dữ liệu nào. Nếu không có dữ liệu nào được trả về, hãy POST dữ liệu vào ứng dụng và thử lại yêu cầu GET.
Giá trị trả về
ASP.NET Core tự động tuần tự hóa đối tượng thành JSON và ghi JSON vào phần thân của thông báo phản hồi. Mã phản hồi cho loại trả về này là 200 OK, giả sử không có ngoại lệ nào chưa được xử lý. Các ngoại lệ chưa được xử lý được dịch thành lỗi 5xx.
Các kiểu trả về có thể đại diện cho nhiều loại mã trạng thái HTTP. Ví dụ: GET /todoitems/{id}
có thể trả về hai giá trị trạng thái khác nhau:
- Nếu không có mục nào khớp với ID được yêu cầu, phương thức này sẽ trả về mã lỗi 404 status NotFound.
- Mặt khác, phương thức trả về 200 với nội dung phản hồi JSON. Trả về
item
kết quả trong phản hồi HTTP 200.
Kiểm tra điểm cuối PUT
Ứng dụng mẫu triển khai một điểm cuối PUT duy nhất bằng cách sử dụng 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();
});
Phương thức này tương tự như phương thức MapPost
, ngoại trừ nó sử dụng HTTP PUT. Phản hồi thành công trả về 204 (Không có nội dung). Theo đặc tả HTTP, yêu cầu PUT yêu cầu máy khách gửi toàn bộ thực thể được cập nhật, không chỉ các thay đổi. Để hỗ trợ cập nhật một phần, hãy sử dụng HTTP PATCH.
Kiểm thử điểm cuối PUT
Mẫu này sử dụng cơ sở dữ liệu trong bộ nhớ phải được khởi tạo mỗi khi khởi động ứng dụng. Phải có một mục trong cơ sở dữ liệu trước khi bạn thực hiện lời gọi PUT. Gọi GET để đảm bảo có một mục trong cơ sở dữ liệu trước khi thực hiện lời gọi PUT.
Cập nhật mục việc cần làm có Id = 1 và đặt tên của mục đó thành "feed fish"
:
{
"id": 1,
"name": "feed fish",
"isComplete": false
}
Kiểm tra và kiểm thử điểm cuối DELETE
Ứng dụng mẫu triển khai một điểm cuối DELETE duy nhất bằng cách sử dụng 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();
});
Sử dụng Postman để xóa một mục việc cần làm:
- Đặt phương thức thành
DELETE
. - Đặt URI của đối tượng cần xóa (ví dụ
https://localhost:5001/todoitems/1
). - Chọn Send.
Sử dụng API MapGroup
Mã ứng dụng mẫu lặp lại tiền tố URL todoitems
mỗi khi thiết lập điểm cuối. Các API thường có các nhóm điểm cuối có tiền tố URL chung và phương thức MapGroup có sẵn để giúp tổ chức các nhóm đó. Nó giảm mã lặp đi lặp lại và cho phép tùy chỉnh toàn bộ nhóm điểm cuối bằng một lệnh gọi duy nhất đến các phương thức như RequireAuthorization và WithMetadata.
Thay thế nội dung của Program.cs
bằng đoạn code sau:
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();
Đoạn code trên có những thay đổi sau:
- Thêm
var todoItems = app.MapGroup("/todoitems");
để thiết lập nhóm bằng tiền tố URL/todoitems
. - Thay đổi tất cả các phương thức
app.Map<HttpVerb>
thànhtodoItems.Map<HttpVerb>
. - Xóa tiền tố URL
/todoitems
khỏi các lời gọi phương thứcMap<HttpVerb>
.
Kiểm tra các điểm cuối để xác minh rằng chúng hoạt động giống nhau.
Sử dụng API TypedResults
Trả về TypedResults thay vì Kết quả có một số lợi thế, bao gồm khả năng kiểm tra và tự động trả về siêu dữ liệu loại phản hồi cho OpenAPI để mô tả điểm cuối. Để biết thêm thông tin, hãy xem TypedResults so với Results.
Các phương thức Map<HttpVerb>
có thể gọi các phương thức xử lý route thay vì sử dụng lambda. Để xem ví dụ, hãy cập nhật Program.cs bằng code sau:
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();
}
Code Map<HttpVerb>
hiện gọi các phương thức thay vì lambda:
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);
Các phương thức này trả về các đối tượng triển khai IResult và được xác định bởi TypedResults:
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();
}
Các đơn vị kiểm thử (unit test) có thể gọi các phương thức này và kiểm tra xem chúng có trả về đúng loại không. Ví dụ: nếu phương thức là GetAllTodos
:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
Code unit test có thể xác minh rằng một đối tượng thuộc kiểu Ok<Todo[]> được trả về từ phương thức xử lý. Ví dụ:
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);
}
Ngăn chặn đăng quá nhiều
Hiện tại, ứng dụng mẫu hiển thị toàn bộ đối tượng Todo
. Các ứng dụng production thường giới hạn dữ liệu được nhập và trả về bằng cách sử dụng một tập hợp con của model. Có nhiều lý do đằng sau điều này và bảo mật là một trong những lý do chính. Tập hợp con của một model thường được gọi là Đối tượng truyền dữ liệu (Data Transfer Object - DTO), model đầu vào hoặc model view. DTO được sử dụng trong bài viết này.
Một DTO có thể được sử dụng để:
- Ngăn chặn đăng quá nhiều.
- Ẩn các property mà khách hàng không được phép xem.
- Bỏ qua một số property để giảm kích thước tải trọng (payload size).
- Làm phẳng đồ thị đối tượng có chứa các đối tượng lồng nhau. Biểu đồ đối tượng phẳng có thể thuận tiện hơn cho khách hàng.
Để minh họa cách tiếp cận DTO, hãy cập nhật lớp Todo
để đưa vào một trường bí mật:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
Trường bí mật cần được ẩn khỏi ứng dụng này nhưng ứng dụng quản trị có thể chọn hiển thị trường đó.
Xác minh rằng bạn có thể đăng và nhận trường bí mật.
Tạo một tệp có tên TodoItemDTO.cs
với code sau:
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);
}
Cập nhật code Program.cs
để sử dụng mô hình DTO này:
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();
}
Xác minh rằng bạn có thể đăng và nhận tất cả các trường ngoại trừ trường bí mật.
Bước tiếp theo
Định cấu hình các tùy chọn tuần tự hóa JSON
Để biết thông tin về cách định cấu hình tuần tự hóa JSON trong các ứng dụng API tối thiểu của bạn, hãy xem Định cấu hình tùy chọn tuần tự hóa JSON.
Xử lý lỗi và ngoại lệ
Trang ngoại lệ dành cho nhà phát triển được bật theo mặc định trong môi trường phát triển cho các ứng dụng API tối thiểu. Để biết thông tin về cách xử lý lỗi và ngoại lệ, hãy xem Xử lý lỗi trong API ASP.NET Core.
Kiểm tra các ứng dụng API tối thiểu
Để biết ví dụ về thử nghiệm ứng dụng API tối thiểu, hãy xem mẫu GitHub này.
Sử dụng OpenAPI (Swagger)
Để biết thông tin về cách sử dụng OpenAPI với các ứng dụng API tối thiểu, hãy xem hỗ trợ OpenAPI trong API tối thiểu.
Xuất bản lên Azure
Để biết thông tin về cách triển khai lên Azure, hãy xem Bắt đầu nhanh: Triển khai ứng dụng web ASP.NET.
Tìm hiểu thêm
Để biết thêm thông tin về các ứng dụng API tối thiểu, hãy xem Tham khảo nhanh về API tối thiểu.