Nguon: Microsoft Learn · .NET 8.0

Tạo Web API với ASP.NET Core và MongoDB

Nguồn: Create a web API with ASP.NET Core and MongoDB

Hướng dẫn toàn diện này hướng dẫn tạo web API thực hiện các thao tác CRUD (Create, Read, Update, Delete - Tạo, Đọc, Cập nhật, Xóa) trên cơ sở dữ liệu NoSQL MongoDB sử dụng ASP.NET Core.

Tổng quan

Hướng dẫn dạy cách:

Yêu cầu tiên quyết

Yêu cầu cốt lõi

Công cụ phát triển

Visual Studio:

Visual Studio Code:

Các bước cấu hình MongoDB

  1. Cài đặt MongoDB Shell
  2. macOS/Linux: Giải nén và thêm mongosh vào PATH
  3. Windows: Đã có tại C:\Users\{USER}\AppData\Local\Programs\mongosh
  4. Cài đặt MongoDB
  5. macOS/Linux: Thường tại /usr/local/mongodb
  6. Windows: Vị trí mặc định C:\Program Files\MongoDB
  7. Tạo thư mục dữ liệu
  8. macOS/Linux: /usr/local/var/mongodb
  9. Windows: C:\BooksData
  10. Khởi động server MongoDB
console
mongod --dbpath {ĐƯỜNG DẪN THƯ MỤC DỮ LIỆU}

Thiết lập cơ sở dữ liệu

Kết nối với MongoDB Shell

console
mongosh

Tạo cơ sở dữ liệu và collection

console
use BookStore
db.createCollection('Books')

Chèn dữ liệu mẫu

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

Xác minh dữ liệu

console
db.Books.find().pretty()

Thiết lập dự án

Tạo dự án ASP.NET Core Web API

Visual Studio:

  1. File > New > Project (Tệp > Mới > Dự án)
  2. Chọn ASP.NET Core Web API
  3. Tên: BookStoreApi
  4. Framework: .NET 10.0 (hoặc phiên bản phù hợp)
  5. Bỏ chọn "Use controllers" cho .NET 10/11 (minimal APIs)
  6. Chọn "Enable OpenAPI support" (Bật hỗ trợ OpenAPI)

Visual Studio Code:

dotnetcli
dotnet new webapi -o BookStoreApi
code BookStoreApi

Cài đặt MongoDB Driver (trình điều khiển MongoDB)

powershell
Install-Package MongoDB.Driver

Hoặc với .NET CLI:

dotnetcli
dotnet add package MongoDB.Driver

Model thực thể

Tạo Models/Book.cs:

csharp
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System.Text.Json.Serialization;

namespace BookStoreApi.Models;

public class Book
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string? Id { get; set; }

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

    public decimal Price { get; set; }

    public string Category { get; set; } = null!;

    public string Author { get; set; } = null!;
}

Các thuộc tính quan trọng:

Cấu hình cơ sở dữ liệu

Cập nhật appsettings.json

json
{
  "BookStoreDatabase": {
    "ConnectionString": "mongodb://localhost:27017",
    "DatabaseName": "BookStore",
    "BooksCollectionName": "Books"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Tạo Model cấu hình

Models/BookStoreDatabaseSettings.cs:

csharp
namespace BookStoreApi.Models;

public class BookStoreDatabaseSettings
{
    public string ConnectionString { get; set; } = null!;
    public string DatabaseName { get; set; } = null!;
    public string BooksCollectionName { get; set; } = null!;
}

Đăng ký cấu hình trong Program.cs

csharp
using BookStoreApi.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<BookStoreDatabaseSettings>(
    builder.Configuration.GetSection("BookStoreDatabase"));

Service CRUD (dịch vụ CRUD)

Tạo Services/BooksService.cs:

csharp
using BookStoreApi.Models;
using Microsoft.Extensions.Options;
using MongoDB.Driver;

namespace BookStoreApi.Services;

public class BooksService(IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings)
{
    private readonly IMongoCollection<Book> _booksCollection = 
        new MongoClient(bookStoreDatabaseSettings.Value.ConnectionString)
            .GetDatabase(bookStoreDatabaseSettings.Value.DatabaseName)
            .GetCollection<Book>(bookStoreDatabaseSettings.Value.BooksCollectionName);

    public async Task<List<Book>> GetAsync() =>
        await _booksCollection.Find(_ => true).ToListAsync();

    public async Task<Book?> GetAsync(string id) =>
        await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync();

    public async Task CreateAsync(Book newBook) =>
        await _booksCollection.InsertOneAsync(newBook);

    public async Task UpdateAsync(string id, Book updatedBook) =>
        await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook);

    public async Task RemoveAsync(string id) =>
        await _booksCollection.DeleteOneAsync(x => x.Id == id);
}

Đăng ký Service trong Program.cs

csharp
using BookStoreApi.Services;

builder.Services.AddSingleton<BooksService>();

Các Endpoint API (Minimal APIs - .NET 10/11)

Thêm vào Program.cs:

csharp
var booksGroup = app.MapGroup("/books");

booksGroup.MapGet("/", async (BooksService booksService) =>
{
    var books = await booksService.GetAsync();
    return Results.Ok(books);
});

booksGroup.MapGet("/{id:length(24)}", async (string id, BooksService booksService) =>
{
    var book = await booksService.GetAsync(id);
    return book is null ? Results.NotFound() : Results.Ok(book);
});

booksGroup.MapPost("/", async (Book newBook, BooksService booksService) =>
{
    await booksService.CreateAsync(newBook);
    return Results.Created($"/books/{newBook.Id}", newBook);
});

booksGroup.MapPut("/{id:length(24)}", async (string id, Book updatedBook, BooksService booksService) =>
{
    var book = await booksService.GetAsync(id);
    if (book is null) return Results.NotFound();
    
    updatedBook.Id = book.Id;
    await booksService.UpdateAsync(id, updatedBook);
    return Results.NoContent();
});

booksGroup.MapDelete("/{id:length(24)}", async (string id, BooksService booksService) =>
{
    var book = await booksService.GetAsync(id);
    if (book is null) return Results.NotFound();
    
    await booksService.RemoveAsync(id);
    return Results.NoContent();
});

Các Endpoint API (dựa trên Controller - phiên bản trước)

Tạo Controllers/BooksController.cs:

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

namespace BookStoreApi.Controllers;

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

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

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

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

    [HttpPost]
    public async Task<IActionResult> Post(Book newBook)
    {
        await _booksService.CreateAsync(newBook);
        return CreatedAtAction(nameof(Get), new { id = newBook.Id }, newBook);
    }

    [HttpPut("{id:length(24)}")]
    public async Task<IActionResult> Update(string id, Book updatedBook)
    {
        var book = await _booksService.GetAsync(id);
        if (book is null) return NotFound();
        
        updatedBook.Id = book.Id;
        await _booksService.UpdateAsync(id, updatedBook);
        return NoContent();
    }

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

Cấu hình JSON Serialization

Minimal APIs (.NET 10/11)

csharp
builder.Services.Configure<Microsoft.AspNetCore.Http.Json.JsonOptions>(options =>
{
    options.SerializerOptions.PropertyNamingPolicy = null;
});

Controller-based APIs

csharp
builder.Services.AddControllers()
    .AddJsonOptions(options => 
        options.JsonSerializerOptions.PropertyNamingPolicy = null);

Cấu hình này đảm bảo tên thuộc tính giữ nguyên dạng PascalCase thay vì camelCase.

Kiểm thử API

Visual Studio

Dùng Endpoints Explorer với file .http để kiểm thử

Visual Studio Code

  1. Cài đặt Swagger UI:
dotnetcli
dotnet add package NSwag.AspNetCore
  1. Cấu hình middleware trong Program.cs:
csharp
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
    app.UseSwaggerUi(options =>
    {
        options.DocumentPath = "/openapi/v1.json";
    });
}
  1. Truy cập https://localhost:{PORT}/swagger

Ví dụ Response API

json
[
  {
    "Id": "61a6058e6c43f32854e51f51",
    "Name": "Design Patterns",
    "Price": 54.93,
    "Category": "Computers",
    "Author": "Ralph Johnson"
  },
  {
    "Id": "61a6058e6c43f32854e51f52",
    "Name": "Clean Code",
    "Price": 43.15,
    "Category": "Computers",
    "Author": "Robert C. Martin"
  }
]

Xác thực

Để bảo mật API, Microsoft khuyến nghị:

Lưu ý: Duende Software có thể yêu cầu cấp phép cho môi trường production.