C# Academy · 课时

创建第一个 Minimal API

初始化 Minimal API 项目,定义路由处理程序,并以最少的样板代码返回类型化结果。

第 1 / 4 课13 个步骤

创建第一个 Minimal API 是 CoddyKit 上的免费 C# Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。

什么是最小 API

最小 API 于 .NET 6 引入,可以用极少的样板代码构建 HTTP 端点——无需控制器和操作特性,只需在 Program.cs 中直接定义路由处理程序。它们非常适合微服务和轻量级 API。

最简单的最小 API

只需几行代码即可完成一个 HTTP API。MapGet、MapPost、MapPut 和 MapDelete 方法分别为每种 HTTP 方法定义路由处理程序。

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

app.MapGet("/", () => "Hello, Minimal API!");
app.MapGet("/ping", () => Results.Ok(new { status = "pong" }));

app.Run();
// That's it — no Startup.cs, no controllers

使用类型化结果返回正确的 HTTP 响应

使用 Results 或 TypedResults 返回正确的 HTTP 状态码和内容类型。对于 OpenAPI 架构推断,优先使用 TypedResults。

app.MapGet("/products/{id}", async (int id, AppDbContext db) =>
{
    var product = await db.Products.FindAsync(id);
    return product is null
        ? Results.NotFound()
        : Results.Ok(product);
});

app.MapPost("/products", async (Product product, AppDbContext db) =>
{
    db.Products.Add(product);
    await db.SaveChangesAsync();
    return Results.Created($"/products/{product.Id}", product);
});

路由参数与查询字符串

路由参数从 URL 路径中获取,查询字符串参数会自动从查询中绑定,请求正文则从 JSON 反序列化得到。

// Route param {id} + query param ?includeDeleted
app.MapGet("/orders/{id}", async (
    int id,
    bool includeDeleted = false,
    AppDbContext db) =>
{
    var query = db.Orders.AsQueryable();
    if (!includeDeleted) query = query.Where(o => !o.IsDeleted);
    var order = await query.FirstOrDefaultAsync(o => o.Id == id);
    return order is null ? Results.NotFound() : Results.Ok(order);
});

路由处理程序中的依赖注入

在 DI 容器中注册的服务可以直接注入为路由处理程序参数。框架会自动解析这些服务。

builder.Services.AddScoped<ProductService>();

app.MapGet("/products", async (ProductService svc) =>
{
    var products = await svc.GetAllAsync();
    return Results.Ok(products);
});

app.MapDelete("/products/{id}", async (int id, ProductService svc) =>
{
    var deleted = await svc.DeleteAsync(id);
    return deleted ? Results.NoContent() : Results.NotFound();
});

请求正文绑定

与已注册服务匹配的参数会被注入;其他所有参数都会从请求正文中绑定(默认使用 JSON)。如有需要,请显式使用 [FromBody]。

record CreateProductRequest(string Name, decimal Price, int Stock);

app.MapPost("/products", async (
    CreateProductRequest req,
    ProductService svc) =>
{
    var product = await svc.CreateAsync(req.Name, req.Price, req.Stock);
    return TypedResults.Created($"/products/{product.Id}", product);
});

返回不同的状态码

Results 为所有常见的 HTTP 响应提供工厂方法。请使用这些方法构建语义正确的 REST API。

app.MapPut("/products/{id}", async (int id, Product update, AppDbContext db) =>
{
    var existing = await db.Products.FindAsync(id);
    if (existing is null) return Results.NotFound();

    existing.Name  = update.Name;
    existing.Price = update.Price;
    await db.SaveChangesAsync();
    return Results.Ok(existing);
});

// Other useful Results:
// Results.BadRequest("message")
// Results.Conflict()
// Results.UnprocessableEntity(errors)
// Results.Accepted()

使用 WithName 和 WithTags 添加元数据

为端点附加元数据,以改善文档和路由。使用 WithName、WithTags 和 WithSummary 生成结构清晰的 OpenAPI 输出。

app.MapGet("/products/{id}", GetProduct)
   .WithName("GetProductById")
   .WithTags("Products")
   .WithSummary("Retrieves a product by its ID")
   .Produces<Product>()
   .Produces(404);

static async Task<IResult> GetProduct(int id, AppDbContext db)
{
    var p = await db.Products.FindAsync(id);
    return p is null ? Results.NotFound() : Results.Ok(p);
}

最小 API 中的授权

应用 RequireAuthorization() 保护端点,或使用 AllowAnonymous() 选择免授权。策略的工作方式与控制器中相同。

builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();

app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/profile", (ClaimsPrincipal user) =>
    Results.Ok(user.Identity!.Name))
   .RequireAuthorization();

app.MapGet("/public", () => "No auth needed")
   .AllowAnonymous();

使用静态方法组织代码

对于较大的 API,可将路由处理程序移至静态方法或扩展方法中,以保持 Program.cs 整洁且便于浏览。

// Extension method groups endpoints by feature
public static class ProductEndpoints
{
    public static void MapProductEndpoints(this WebApplication app)
    {
        app.MapGet("/products",    GetAll);
        app.MapGet("/products/{id}", GetById);
        app.MapPost("/products",   Create);
    }

    private static async Task<IResult> GetAll(AppDbContext db)
        => Results.Ok(await db.Products.AsNoTracking().ToListAsync());

    // ... other handlers
}

// In Program.cs:
app.MapProductEndpoints();

真实案例:完整的 CRUD 最小 API

一个针对 Todo 资源的完整最小 CRUD API——简洁、可测试,并且可用于生产环境。

app.MapGet("/todos", async (AppDbContext db) =>
    Results.Ok(await db.Todos.AsNoTracking().ToListAsync()));

app.MapGet("/todos/{id}", async (int id, AppDbContext db) =>
{
    var todo = await db.Todos.FindAsync(id);
    return todo is null ? Results.NotFound() : Results.Ok(todo);
});

app.MapPost("/todos", async (Todo todo, AppDbContext db) =>
{
    db.Todos.Add(todo);
    await db.SaveChangesAsync();
    return Results.Created($"/todos/{todo.Id}", todo);
});

app.MapDelete("/todos/{id}", async (int id, AppDbContext db) =>
{
    int n = await db.Todos.Where(t => t.Id == id).ExecuteDeleteAsync();
    return n > 0 ? Results.NoContent() : Results.NotFound();
});

快速检查

最小 API 的路由处理程序如何接收已注册的 DI 服务?

回顾:创建您的第一个最小 API

要点:

  • MapGet/Post/Put/Delete 可直接在 Program.cs 中定义路由处理程序
  • 使用 Results / TypedResults 返回正确的 HTTP 状态码
  • 路由、查询、正文和 DI 参数都会自动绑定
  • 使用 RequireAuthorization() 和 AllowAnonymous() 进行身份验证
  • 使用扩展方法或路由组组织大型 API
免费开始

用 AI 导师学习 C# — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
93
课程
346

常见问题解答

「创建第一个 Minimal API」课时是免费的吗?

是的 — 「创建第一个 Minimal API」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。

「创建第一个 Minimal API」这节课中我会学到什么?

初始化 Minimal API 项目,定义路由处理程序,并以最少的样板代码返回类型化结果。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C# Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「创建第一个 Minimal API」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C# Academy 课中编写并运行代码吗?

能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 创建第一个 Minimal API
  2. 路由组、参数与验证
  3. Minimal API 中间件与筛选器
  4. OpenAPI、版本控制与部署
← 返回 C# Academy