← 返回首页目录
# 使用ASP.NET Core创建基于控制器的Web API完整教程
**作者:吉祥法师**
## 教程概述
本教程旨在教授如何使用ASP.NET Core构建基于控制器的Web API应用程序,该API将集成数据库功能。在ASP.NET Core中,创建API的另一种方式是使用最小API(Minimal APIs)。开发者在选择两种方案时,可以参考微软官方提供的API概览文档进行决策。若需要了解最小API的创建方法,可查阅专门的最小API教程。
本教程将构建一个功能完整的待办事项(Todo)管理API,涵盖以下核心端点:
- **GET /api/todoitems**:获取所有待办事项,无需请求体,返回待办事项数组
- **GET /api/todoitems/{id}**:根据ID获取特定待办事项,无需请求体,返回单个待办事项
- **POST /api/todoitems**:添加新的待办事项,请求体为待办事项对象,返回新建的待办事项
- **PUT /api/todoitems/{id}**:更新现有待办事项,请求体为待办事项对象,无需响应体
- **DELETE /api/todoitems/{id}**:删除指定待办事项,无需请求体和响应体
## 环境准备与项目创建
### 所需开发环境
**Visual Studio 方案**:需要安装Visual Studio 2022,并确保包含"ASP.NET和Web开发"工作负载。
**Visual Studio Code方案**:需要安装VS Code、C# Dev Kit扩展以及.NET 9 SDK。该方案支持在macOS、Linux或Windows系统上操作,若使用其他集成开发环境可能需要相应调整。
### 创建Web API项目
**Visual Studio创建步骤**:
1. 从"文件"菜单选择"新建"→"项目"
2. 搜索"Web API",选择"ASP.NET Core Web API"模板
3. 将项目命名为"TodoApi"并点击"下一步"
4. 在附加信息对话框中,确认框架为.NET 9.0,勾选"启用OpenAPI支持"和"使用控制器"选项
**Visual Studio Code创建步骤**:
1. 打开集成终端,切换到项目存放目录
2. 执行以下命令序列:
- `dotnet new webapi --use-controllers -o TodoApi`:创建新Web API项目
- `cd TodoApi`:进入项目目录
- `dotnet add package Microsoft.EntityFrameworkCore.InMemory`:添加内存数据库支持
- `code -r .`:在当前VS Code实例中打开项目
### 添加NuGet包
项目需要添加Microsoft.EntityFrameworkCore.InMemory包来支持内存数据库。在Visual Studio中,可通过"工具"→"NuGet包管理器"→"管理解决方案的NuGet包"进行安装,搜索并选择对应包后点击安装即可。
## 项目运行与初始验证
### 运行项目
**Visual Studio**:按Ctrl+F5启动应用。首次运行可能需要信任IIS Express SSL证书和开发证书,依次点击"是"确认即可。应用启动后,终端窗口会显示监听地址,如https://localhost:7260。
**Visual Studio Code**:先运行`dotnet dev-certs https --trust`信任HTTPS开发证书,然后执行`dotnet run --launch-profile https`启动应用。
### 验证API
由于初始项目没有根端点,直接访问https://localhost:端口会返回404错误。在URL后追加`/weatherforecast`即可测试预置的WeatherForecast API,浏览器会返回JSON格式的天气数据,包含日期、温度(摄氏和华氏)及天气摘要等信息。
## 添加Swagger测试工具
为提高API测试效率,本教程使用NSwag.AspNetCore包集成Swagger工具:
### 安装和配置
1. 执行`dotnet add package NSwag.AspNetCore`添加包
2. 在Program.cs中配置Swagger中间件,仅在开发环境中启用:
```csharp
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.UseSwaggerUi(options => {
options.DocumentPath = "/openapi/v1.json";
});
}
```
注意:Swagger仅在开发环境启用,因为生产环境暴露API结构可能带来安全风险。
### 查看OpenAPI规范
运行项目后,访问https://localhost:端口/openapi/v1.json可以查看描述API端点、请求/响应格式、参数等信息的JSON格式OpenAPI规范文档。
## 创建数据模型
### 添加TodoItem模型类
在项目中创建Models文件夹,添加TodoItem.cs文件:
```csharp
namespace TodoApi.Models;
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
```
Id属性在关系数据库中作为唯一键使用。模型类虽可放在项目任意位置,但按惯例放置在Models文件夹中。
## 配置数据库上下文
### 创建TodoContext类
在Models文件夹中添加TodoContext.cs:
```csharp
using Microsoft.EntityFrameworkCore;
namespace TodoApi.Models;
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions options)
: base(options)
{
}
public DbSet TodoItems { get; set; } = null!;
}
```
该数据库上下文类派生自DbContext,是协调Entity Framework功能的核心类。
### 注册数据库上下文
在Program.cs中注册服务,指定使用内存数据库:
```csharp
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddOpenApi();
builder.Services.AddDbContext(opt =>
opt.UseInMemoryDatabase("TodoList"));
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.UseSwaggerUi(options => {
options.DocumentPath = "/openapi/v1.json";
});
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
```
这段代码完成了数据库上下文的依赖注入注册,并指定使用名为"TodoList"的内存数据库。
## 生成API控制器
### Visual Studio方案
1. 右键单击Controllers文件夹,选择"添加"→"新建脚手架项"
2. 选择"使用Entity Framework的API控制器"
3. 在对话框中,模型类选择TodoItem,数据上下文类选择TodoContext
4. 点击"添加"完成生成
### VS Code方案
执行以下命令序列安装脚手架工具并生成控制器:
```bash
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet tool uninstall -g dotnet-aspnet-codegenerator
dotnet tool install -g dotnet-aspnet-codegenerator
dotnet tool update -g dotnet-aspnet-codegenerator
dotnet aspnet-codegenerator controller -name TodoItemsController -async -api -m TodoItem -dc TodoContext -outDir Controllers
```
生成的控制器具备以下特点:
- 标记[ApiController]属性,表明该控制器响应Web API请求
- 通过依赖注入获取数据库上下文,用于CRUD操作
- 路由模板不含[action]标记,这意味着方法名不参与路由匹配
## 实现CRUD操作
### POST方法优化
将PostTodoItem方法中的硬编码字符串替换为nameof操作符:
```csharp
[HttpPost]
public async Task> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetTodoItem),
new { id = todoItem.Id }, todoItem);
}
```
CreatedAtAction方法在成功时返回HTTP 201状态码,这是POST方法创建资源的标准响应,同时添加包含新资源URI的Location头。使用nameof关键字避免了硬编码方法名。
### GET方法解析
控制器包含两个GET端点:
```csharp
[HttpGet]
public async Task>> GetTodoItems()
{
return await _context.TodoItems.ToListAsync();
}
[HttpGet("{id}")]
public async Task> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return todoItem;
}
```
路由构造原则:URL路径以控制器Route属性中的模板字符串"api/[controller]"开头,[controller]被替换为控制器名(去掉Controller后缀)。对于带参数的路径,"{id}"是待办事项唯一标识的占位符,其值会传递给方法的id参数。
### 返回值类型说明
ActionResult类型允许返回多种HTTP状态码。ASP.NET Core会自动将对象序列化为JSON并写入响应体。无异常时返回200 OK,未处理异常转换为5xx错误。GetTodoItem方法可返回404(未找到匹配项)或200(成功返回JSON响应体)。
### PUT方法详解
```csharp
[HttpPut("{id}")]
public async Task PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}
_context.Entry(todoItem).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
```
PUT方法与POST类似,但使用HTTP PUT语义,响应为204 No Content。根据HTTP规范,PUT请求要求客户端发送完整的更新实体,如需部分更新应使用HTTP PATCH。
### DELETE方法实现
```csharp
[HttpDelete("{id}")]
public async Task DeleteTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
_context.TodoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return NoContent();
}
```
## API测试实践
### 使用Endpoints Explorer测试
Visual Studio的Endpoints Explorer可以右键点击端点生成测试请求,自动创建.http文件。对于POST请求,需要提供JSON格式的请求体:
```json
{
"name": "walk dog",
"isComplete": true
}
```
发送请求后可在响应面板查看返回结果,包括201状态码和新建项的ID。
### 使用Swagger UI测试
运行应用后,访问https://localhost:端口/swagger进入测试页面。点击Try it out按钮,填充请求参数后执行。Swagger提供cURL命令示例、请求URL和服务器响应等详细信息,便于调试。
### 完整测试流程建议
1. 通过POST创建新待办事项(如"walk dog")
2. 使用GET验证创建结果
3. 通过PUT更新事项名称(如改为"feed fish"),验证204响应
4. 使用DELETE删除事项,确认204响应
5. 再次GET验证删除成功
注意:内存数据库每次应用重启后数据清空,需要重新POST数据。
## 安全考虑与最佳实践
### 防止过度发布(Over-Posting)
当前示例暴露了整个TodoItem对象,生产环境应用通常通过数据传输对象(DTO)限制输入和返回的数据子集,防止恶意用户提交额外字段修改不应更改的数据。这需要创建专门的请求/响应模型,并在控制器中进行映射。
### 其他测试工具
除Swagger外,开发者还可使用HTTP REPL、curl命令行工具或Fiddler等工具测试Web API。Swagger会显示其提交的curl命令,方便复制使用。
## 总结
本教程完整演示了使用ASP.NET Core创建控制器基础Web API的全过程,涵盖项目创建、依赖配置、数据模型定义、数据库上下文设置、控制器生成及CRUD操作实现。通过使用内存数据库和Swagger测试工具,开发者可以快速理解Web API的核心概念并投入实际开发。生产环境部署时需考虑数据库持久化、数据验证、安全性增强和API版本管理等扩展需求。