Nguon: Microsoft Learn · .NET 8.0

Tài liệu tham khảo nhanh về Minimal APIs

Nguồn: Minimal APIs quick reference

WebApplication

Cài đặt cơ bản

csharp
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

Cách tạo thay thế

csharp
var app = WebApplication.Create(args);

app.MapGet("/", () => "Hello World!");

app.Run();

Làm việc với Ports (cổng)

Một cổng

csharp
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");

Nhiều cổng

csharp
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();

Dòng lệnh

dotnetcli
dotnet run --urls="https://localhost:7777"

Biến môi trường

code
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000

Lắng nghe trên tất cả các giao diện mạng

csharp
// Dùng ký tự đại diện
app.Urls.Add("http://*:3000");

// Dùng dấu cộng
app.Urls.Add("http://+:3000");

// Dùng địa chỉ IP
app.Urls.Add("http://0.0.0.0:3000");

Biến môi trường:

code
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
ASPNETCORE_HTTP_PORTS=3000;5005
ASPNETCORE_HTTPS_PORTS=5000

Cấu hình HTTPS

Certificate (chứng chỉ) phát triển

csharp
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();

Certificate tùy chỉnh qua appsettings.json

json
{
  "Kestrel": {
    "Certificates": {
      "Default": {
        "Path": "cert.pem",
        "KeyPath": "key.pem"
      }
    }
  }
}

Certificate tùy chỉnh qua cấu hình code

csharp
var builder = WebApplication.CreateBuilder(args);
builder.Configuration["Kestrel:Certificates:Default:Path"] = "cert.pem";
builder.Configuration["Kestrel:Certificates:Default:KeyPath"] = "key.pem";
var app = builder.Build();
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();

Dùng Certificate APIs

csharp
using System.Security.Cryptography.X509Certificates;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
    options.ConfigureHttpsDefaults(httpsOptions =>
    {
        var certPath = Path.Combine(builder.Environment.ContentRootPath, "cert.pem");
        var keyPath = Path.Combine(builder.Environment.ContentRootPath, "key.pem");
        httpsOptions.ServerCertificate = X509Certificate2.CreateFromPemFile(certPath, keyPath);
    });
});

var app = builder.Build();
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();

Cấu hình WebApplicationBuilder

Thay đổi Content Root, Application Name và Environment (môi trường)

csharp
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    Args = args,
    ApplicationName = typeof(Program).Assembly.FullName,
    ContentRootPath = Directory.GetCurrentDirectory(),
    EnvironmentName = Environments.Staging,
    WebRootPath = "customwwwroot"
});

Console.WriteLine($"Application Name: {builder.Environment.ApplicationName}");
Console.WriteLine($"Environment Name: {builder.Environment.EnvironmentName}");
Console.WriteLine($"ContentRoot Path: {builder.Environment.ContentRootPath}");
Console.WriteLine($"WebRootPath: {builder.Environment.WebRootPath}");

var app = builder.Build();

Biến môi trường và đối số dòng lệnh

Tính năngBiến môi trườngĐối số dòng lệnh
Application nameASPNETCORE_APPLICATIONNAME--applicationName
Environment nameASPNETCORE_ENVIRONMENT--environment
Content rootASPNETCORE_CONTENTROOT--contentRoot

Thêm Configuration Providers (nhà cung cấp cấu hình)

csharp
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();

Đọc Configuration

csharp
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();

Kiểm tra Environment

csharp
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
    Console.WriteLine($"Running in development.");
}
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();

Thêm Logging Providers (nhà cung cấp ghi log)

csharp
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddJsonConsole();
var app = builder.Build();
app.MapGet("/", () => "Hello JSON console!");
app.Run();

Thêm Services (dịch vụ)

csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMemoryCache();
builder.Services.AddScoped<ITodoRepository, TodoRepository>();
var app = builder.Build();

Tùy chỉnh IHostBuilder

csharp
var builder = WebApplication.CreateBuilder(args);
builder.Host.ConfigureHostOptions(o => o.ShutdownTimeout = TimeSpan.FromSeconds(30));
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();

Tùy chỉnh IWebHostBuilder

csharp
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseHttpSys();
var app = builder.Build();
app.MapGet("/", () => "Hello HTTP.sys");
app.Run();

Thay đổi Web Root

csharp
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    Args = args,
    WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();

DI Container (vùng chứa Dependency Injection) tùy chỉnh - ví dụ Autofac

csharp
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(builder => 
    builder.RegisterModule(new MyApplicationModule()));
var app = builder.Build();

Middleware (phần mềm trung gian)

Các middleware phổ biến cho Minimal APIs:

MiddlewareMô tảAPI
Authentication (xác thực)Hỗ trợ xác thựcUseAuthentication
Authorization (phân quyền)Hỗ trợ phân quyềnUseAuthorization
CORSCấu hình Cross-Origin Resource SharingUseCors
Exception HandlerXử lý exception toàn cụcUseExceptionHandler
Forwarded HeadersChuyển tiếp các header được proxyUseForwardedHeaders
HTTPS RedirectionChuyển hướng HTTP sang HTTPSUseHttpsRedirection
HSTSHTTP Strict Transport SecurityUseHsts
Request LoggingGhi log HTTP request/responseUseHttpLogging
Request TimeoutsCấu hình timeout cho requestUseRequestTimeouts
W3C Request LoggingGhi log request định dạng W3CUseW3CLogging
Response CachingCache (bộ nhớ đệm) responseUseResponseCaching
Response CompressionNén responseUseResponseCompression
SessionQuản lý phiên người dùngUseSession
Static FilesPhục vụ file tĩnhUseStaticFiles, UseFileServer
WebSocketsBật giao thức WebSocketsUseWebSockets

Thêm Middleware

csharp
var app = WebApplication.Create(args);
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();

Routing (định tuyến)

Các HTTP Verbs (phương thức HTTP)

csharp
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "This is a GET");
app.MapPost("/", () => "This is a POST");
app.MapPut("/", () => "This is a PUT");
app.MapDelete("/", () => "This is a DELETE");

app.MapMethods("/options-or-head", new[] { "OPTIONS", "HEAD" }, 
    () => "This is an options or head request");

app.Run();

Route Handlers (bộ xử lý route)

Lambda expression (biểu thức lambda)

csharp
app.MapGet("/inline", () => "This is an inline lambda");

var handler = () => "This is a lambda variable";
app.MapGet("/", handler);

Local Function (hàm cục bộ)

csharp
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);

Instance Method (phương thức của đối tượng)

csharp
var handler = new HelloHandler();
app.MapGet("/", handler.Hello);

class HelloHandler
{
    public string Hello()
    {
        return "Hello Instance method";
    }
}

Static Method (phương thức tĩnh)

csharp
app.MapGet("/", HelloHandler.Hello);

class HelloHandler
{
    public static string Hello()
    {
        return "Hello static method";
    }
}

Endpoint định nghĩa ngoài Program.cs

Program.cs

csharp
using MinAPISeparateFile;

var builder = WebApplication.CreateSlimBuilder(args);
var app = builder.Build();

TodoEndpoints.Map(app);
app.Run();

TodoEndpoints.cs

csharp
namespace MinAPISeparateFile;

public static class TodoEndpoints
{
    public static void Map(WebApplication app)
    {
        app.MapGet("/", async context =>
        {
            await context.Response.WriteAsJsonAsync(new { Message = "All todo items" });
        });

        app.MapGet("/{id}", async context =>
        {
            await context.Response.WriteAsJsonAsync(new { Message = "One todo item" });
        });
    }
}
csharp
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/hello", () => "Hello named route")
   .WithName("hi");

app.MapGet("/", (LinkGenerator linker) => 
    $"The link to the hello route is {linker.GetPathByName("hi", values: null)}");

app.Run();

Tiêu chí đặt tên endpoint:

Route Parameters (tham số route)

csharp
app.MapGet("/users/{userId}/books/{bookId}", 
    (int userId, int bookId) => $"The user id is {userId} and book id is {bookId}");

Wildcard và Catch-All Routes

csharp
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");

Route Constraints (ràng buộc route)

csharp
app.MapGet("/todos/{id:int}", (int id) => db.Todos.Find(id));
app.MapGet("/todos/{text}", (string text) => db.Todos.Where(t => t.Text.Contains(text)));
app.MapGet("/posts/{slug:regex(^[a-z0-9_-]+$)}", (string slug) => $"Post {slug}");
Route TemplateVí dụ URI
/todos/{id:int}/todos/1
/todos/{text}/todos/something
/posts/{slug:regex(^[a-z0-9_-]+$)}/posts/mypost

Route Groups (nhóm route)

csharp
app.MapGroup("/public/todos")
    .MapTodosApi()
    .WithTags("Public");

app.MapGroup("/private/todos")
    .MapTodosApi()
    .WithTags("Private")
    .AddEndpointFilterFactory(QueryPrivateTodos)
    .RequireAuthorization();

public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
    group.MapGet("/", GetAllTodos);
    group.MapGet("/{id}", GetTodo);
    group.MapPost("/", CreateTodo);
    group.MapPut("/{id}", UpdateTodo);
    group.MapDelete("/{id}", DeleteTodo);
    return group;
}

Nested Route Groups (nhóm route lồng nhau)

csharp
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");

Parameter Binding (ràng buộc tham số)

Parameter binding chuyển đổi dữ liệu request thành các tham số strongly typed (kiểu mạnh).

Các nguồn binding được hỗ trợ:

csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<Service>();
var app = builder.Build();

app.MapGet("/{id}", (int id,
                     int page,
                     [FromHeader(Name = "X-CUSTOM-HEADER")] string customHeader,
                     Service service) => { });

class Service { }

Các tính năng chính:

Hỗ trợ Validation (kiểm tra hợp lệ) trong Minimal APIs

Bật validation bằng AddValidation:

csharp
builder.Services.AddValidation();
csharp
public record Product(
    [Required] string Name,
    [Range(1, 1000)] int Quantity);

Tắt validation cho endpoint cụ thể:

csharp
app.MapPost("/products",
    ([EvenNumber(ErrorMessage = "Product ID must be even")] int productId, [Required] string name)
        => TypedResults.Ok(productId))
    .DisableValidation();

Responses (phản hồi)

Các kiểu giá trị trả về

Kiểu trả vềHành viContent-Type
IResultFramework gọi IResult.ExecuteAsyncDo implementation quyết định
stringGhi trực tiếp vào responsetext/plain
T (bất kỳ kiểu nào khác)Serialize thành JSONapplication/json

Trả về String

csharp
app.MapGet("/hello", () => "Hello World");

Trả về JSON

csharp
app.MapGet("/hello", () => new { Message = "Hello World" });

TypedResults

csharp
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));

IResult Return

csharp
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));

app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
    await db.Todos.FindAsync(id) 
        is Todo todo
        ? Results.Ok(todo) 
        : Results.NotFound())
   .Produces<Todo>(StatusCodes.Status200OK)
   .Produces(StatusCodes.Status404NotFound);

Các Results phổ biến

csharp
// JSON
app.MapGet("/hello", () => Results.Json(new { Message = "Hello World" }));

// Mã trạng thái tùy chỉnh
app.MapGet("/405", () => Results.StatusCode(405));

// Text
app.MapGet("/text", () => Results.Text("This is some text"));

// Stream
var proxyClient = new HttpClient();
app.MapGet("/pokemon", async () => 
{
    var stream = await proxyClient.GetStreamAsync("http://contoso/pokedex.json");
    return Results.Stream(stream, "application/json");
});

// Redirect (chuyển hướng)
app.MapGet("/old-path", () => Results.Redirect("/new-path"));

// File
app.MapGet("/download", () => Results.File("myfile.text"));

Authorization (phân quyền)

csharp
using Microsoft.AspNetCore.Authorization;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization(o => o.AddPolicy("AdminsOnly", 
    b => b.RequireClaim("admin", "true")));

var app = builder.Build();
app.UseAuthorization();

app.MapGet("/auth", [Authorize] () => "This endpoint requires authorization.");
app.MapGet("/", () => "This endpoint doesn't require authorization.");

app.Run();

Dùng RequireAuthorization

csharp
app.MapGet("/auth", () => "This endpoint requires authorization")
   .RequireAuthorization();

Authorization dựa trên Policy (chính sách)

csharp
app.MapGet("/admin", [Authorize("AdminsOnly")] () => 
    "The /admin endpoint is for admins only.");

app.MapGet("/admin2", () => "The /admin2 endpoint is for admins only.")
   .RequireAuthorization("AdminsOnly");

Cho phép truy cập ẩn danh

csharp
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");

app.MapGet("/login2", () => "This endpoint also for all roles.")
   .AllowAnonymous();

CORS (Cross-Origin Resource Sharing - Chia sẻ tài nguyên khác nguồn gốc)

csharp
const string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
        builder =>
        {
            builder.WithOrigins("http://example.com",
                "http://www.contoso.com");
        });
});

var app = builder.Build();
app.UseCors();

app.MapGet("/", () => "Hello CORS!");

app.Run();

Dùng Attributes

csharp
app.MapGet("/cors", [EnableCors(MyAllowSpecificOrigins)] () => 
    "This endpoint allows cross origin requests!");

app.MapGet("/cors2", () => "This endpoint allows cross origin requests!")
   .RequireCors(MyAllowSpecificOrigins);

ValidateScopes và ValidateOnBuild

Được bật mặc định trong Development, tắt trong các môi trường khác để tăng hiệu suất.

Tắt Validation

csharp
var builder = WebApplication.CreateBuilder(args);

if (builder.Environment.IsDevelopment())
{
    builder.Host.UseDefaultServiceProvider(options =>
    {
        options.ValidateScopes = false;
        options.ValidateOnBuild = false;
    });
}

Truy cập Dependency Injection (DI)

csharp
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddScoped<SampleService>();

var app = builder.Build();

app.MapControllers();

using (var scope = app.Services.CreateScope())
{
    var sampleService = scope.ServiceProvider.GetRequiredService<SampleService>();
    sampleService.DoSomething();
}

app.Run();

Keyed Services (dịch vụ có khóa)

csharp
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");

var app = builder.Build();

app.MapGet("/big", ([FromKeyedServices("big")] ICache bigCache) => bigCache.Get("date"));

app.MapGet("/small", ([FromKeyedServices("small")] ICache smallCache) => smallCache.Get("date"));

app.Run();

Truy cập Environment và Configuration

Đọc Environment

csharp
var app = WebApplication.Create(args);

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/oops");
}

app.MapGet("/", () => "Hello World");
app.MapGet("/oops", () => "Oops! An error happened.");

app.Run();

Configuration

csharp
var app = WebApplication.Create(args);

var message = app.Configuration["HelloKey"] ?? "Config failed!";

app.MapGet("/", () => message);

app.Run();

Logging (ghi log)

csharp
var app = WebApplication.Create(args);

app.Logger.LogInformation("The app started");

app.MapGet("/", () => "Hello World");

app.Run();

Developer Exception Page (trang ngoại lệ cho nhà phát triển)

csharp
var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapGet("/", () =>
{
    throw new InvalidOperationException("Oops, the '/' route has thrown an exception.");
});

app.Run();

Trong chế độ development, trang này hiển thị thông tin lỗi thân thiện thay vì lỗi chung chung.