.NET Core WebAPI 中 HTTP 请求方法详解:从新手到精通
作为一名程序员,理解 HTTP 请求方法就像厨师掌握不同的烹饪技巧一样重要。今天我就用最通俗易懂的方式,带你全面了解 .NET Core WebAPI 中的各种 HTTP 请求方法。
1. 什么是 HTTP 请求方法?
HTTP 请求方法(也叫 HTTP 动词)告诉服务器要对资源执行什么操作。就像我们与人交流时使用不同的动词一样:"请拿 一本书"、"请放下那本书"。
2. 常用的 HTTP 请求方法
2.1 GET - 获取资源
作用:从服务器获取数据,不会改变服务器状态。
特点:
- 安全的(不会修改数据)
- 幂等的(多次请求结果相同)
- 数据通过 URL 传递
.NET Core 示例:
csharp
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
// GET: api/users
[HttpGet]
public async Task<ActionResult<List<User>>> GetUsers()
{
// 获取所有用户列表
var users = await _userService.GetAllUsersAsync();
return Ok(users);
}
// GET: api/users/5
[HttpGet("{id}")]
public async Task<ActionResult<User>> GetUser(int id)
{
// 根据ID获取单个用户
var user = await _userService.GetUserByIdAsync(id);
if (user == null)
{
return NotFound();
}
return Ok(user);
}
// GET: api/users/search?name=张三
[HttpGet("search")]
public async Task<ActionResult<List<User>>> SearchUsers([FromQuery] string name)
{
// 查询用户
var users = await _userService.SearchUsersAsync(name);
return Ok(users);
}
}
使用场景:
- 加载网页
- 查询数据
- 获取用户信息
- 搜索功能
2.2 POST - 创建新资源
作用:向服务器提交数据,用于创建新资源。
特点:
- 非安全的(会修改数据)
- 非幂等的(多次请求会产生多个资源)
- 数据通过请求体传递
.NET Core 示例:
csharp
[HttpPost]
public async Task<ActionResult<User>> CreateUser([FromBody] CreateUserDto createUserDto)
{
// 数据验证
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
// 创建新用户
var newUser = await _userService.CreateUserAsync(createUserDto);
// 返回201 Created状态码和新资源的URL
return CreatedAtAction(nameof(GetUser), new { id = newUser.Id }, newUser);
}
catch (Exception ex)
{
return BadRequest($"创建用户失败: {ex.Message}");
}
}
// DTO(数据传输对象)
public class CreateUserDto
{
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; }
[Range(1, 120)]
public int Age { get; set; }
}
使用场景:
- 用户注册
- 提交表单
- 上传文件
- 创建订单
2.3 PUT - 更新完整资源
作用:更新整个资源,客户端提供完整的更新后资源。
特点:
- 非安全的
- 幂等的(多次请求结果相同)
- 替换整个资源
.NET Core 示例:
csharp
[HttpPut("{id}")]
public async Task<IActionResult> UpdateUser(int id, [FromBody] UpdateUserDto updateUserDto)
{
if (id != updateUserDto.Id)
{
return BadRequest("ID不匹配");
}
try
{
var existingUser = await _userService.GetUserByIdAsync(id);
if (existingUser == null)
{
return NotFound();
}
// 完整更新用户信息
await _userService.UpdateUserAsync(updateUserDto);
return NoContent(); // 204 No Content
}
catch (Exception ex)
{
return BadRequest($"更新用户失败: {ex.Message}");
}
}
public class UpdateUserDto
{
public int Id { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; }
[Range(1, 120)]
public int Age { get; set; }
}
使用场景:
- 更新用户完整信息
- 替换整个文档
- 修改系统配置
2.4 PATCH - 部分更新资源
作用:部分更新资源,只修改提供的字段。
特点:
- 非安全的
- 非幂等的(取决于实现)
- 只更新部分字段
.NET Core 示例:
csharp
[HttpPatch("{id}")]
public async Task<IActionResult> PartialUpdateUser(int id,
[FromBody] JsonPatchDocument<User> patchDocument)
{
try
{
var user = await _userService.GetUserByIdAsync(id);
if (user == null)
{
return NotFound();
}
// 应用部分更新
patchDocument.ApplyTo(user, ModelState);
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
await _userService.UpdateUserAsync(user);
return NoContent();
}
catch (Exception ex)
{
return BadRequest($"部分更新用户失败: {ex.Message}");
}
}
// 客户端请求示例:
// PATCH /api/users/1
// [
// { "op": "replace", "path": "/name", "value": "新名字" },
// { "op": "replace", "path": "/email", "value": "new@email.com" }
// ]
使用场景:
- 修改用户邮箱
- 更新订单状态
- 修改文章标题
2.5 DELETE - 删除资源
作用:删除指定的资源。
特点:
- 非安全的
- 幂等的(删除一次和删除多次结果相同)
.NET Core 示例:
csharp
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteUser(int id)
{
try
{
var user = await _userService.GetUserByIdAsync(id);
if (user == null)
{
return NotFound();
}
// 删除用户
await _userService.DeleteUserAsync(id);
// 返回204 No Content或者200 OK
return NoContent();
}
catch (Exception ex)
{
return BadRequest($"删除用户失败: {ex.Message}");
}
}
使用场景:
- 删除用户
- 取消订单
- 删除文件
3. 其他重要请求方法
3.1 HEAD - 获取头部信息
类似于 GET,但只返回响应头,不返回响应体。
csharp
[HttpHead("{id}")]
public IActionResult HeadUser(int id)
{
var userExists = _userService.UserExists(id);
if (!userExists)
{
return NotFound();
}
// 不返回响应体,只包含头部信息
return Ok();
}
3.2 OPTIONS - 获取支持的方法
获取服务器对某资源支持的 HTTP 方法。
csharp
[HttpOptions]
public IActionResult GetOptions()
{
Response.Headers.Add("Allow", "GET, POST, PUT, DELETE, OPTIONS");
return Ok();
}
4. 实际项目中的最佳实践
4.1 RESTful API 设计示例
csharp
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
// GET: api/products
[HttpGet]
public async Task<ActionResult<List<Product>>> GetProducts()
{
return Ok(await _productService.GetAllAsync());
}
// GET: api/products/5
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetProduct(int id)
{
var product = await _productService.GetByIdAsync(id);
return product != null ? Ok(product) : NotFound();
}
// POST: api/products
[HttpPost]
public async Task<ActionResult<Product>> CreateProduct(Product product)
{
var created = await _productService.CreateAsync(product);
return CreatedAtAction(nameof(GetProduct), new { id = created.Id }, created);
}
// PUT: api/products/5
[HttpPut("{id}")]
public async Task<IActionResult> UpdateProduct(int id, Product product)
{
if (id != product.Id) return BadRequest();
await _productService.UpdateAsync(product);
return NoContent();
}
// DELETE: api/products/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteProduct(int id)
{
await _productService.DeleteAsync(id);
return NoContent();
}
}
4.2 状态码使用指南
csharp
[HttpPost]
public async Task<ActionResult<User>> CreateUser(User user)
{
try
{
var createdUser = await _userService.CreateAsync(user);
// 201 Created - 创建成功
return CreatedAtAction(nameof(GetUser), new { id = createdUser.Id }, createdUser);
}
catch (ArgumentException ex)
{
// 400 Bad Request - 客户端错误
return BadRequest(ex.Message);
}
catch (UnauthorizedAccessException)
{
// 401 Unauthorized - 未授权
return Unauthorized();
}
catch (Exception ex)
{
// 500 Internal Server Error - 服务器错误
return StatusCode(500, ex.Message);
}
}
5. 总结
| 方法 | 安全性 | 幂等性 | 用途 | 示例 |
|---|---|---|---|---|
| GET | 安全 | 幂等 | 获取数据 | 查看用户列表 |
| POST | 不安全 | 不幂等 | 创建数据 | 用户注册 |
| PUT | 不安全 | 幂等 | 完整更新 | 修改用户信息 |
| PATCH | 不安全 | 不幂等 | 部分更新 | 修改用户邮箱 |
| DELETE | 不安全 | 幂等 | 删除数据 | 删除用户 |
记住这个简单的比喻:
- GET = 查看菜单
- POST = 下单点菜
- PUT = 更换整桌菜
- PATCH = 只换其中一道菜
- DELETE = 取消订单
正确使用 HTTP 方法可以让你的 API 更加符合 RESTful 规范,提高代码的可读性和可维护性。希望这篇详解能帮助你更好地理解和使用 .NET Core WebAPI 中的 HTTP 请求方法!