.NET Core WebAPI 中 HTTP 请求方法详解:从新手到精通

.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 请求方法!

相关推荐
松涛和鸣20 分钟前
49、智能电源箱项目技术栈解析
服务器·c语言·开发语言·http·html·php
汤愈韬37 分钟前
NAT ALG (应用层网关)
网络·网络协议·网络安全·security·huawei
ps酷教程4 小时前
HttpPostRequestDecoder源码浅析
java·http·netty
汤愈韬4 小时前
双向NAT
网络·网络协议·网络安全·security·huawei
*才华有限公司*4 小时前
RTSP视频流播放系统
java·git·websocket·网络协议·信息与通信
寻星探路6 小时前
【Python 全栈测开之路】Python 基础语法精讲(一):常量、变量与运算符
java·开发语言·c++·python·http·ai·c#
栗子叶6 小时前
网页接收服务端消息的几种方式
前端·websocket·http·通信
Filotimo_8 小时前
桥接服务概念
网络协议·网络安全·信息与通信
镜中人★8 小时前
408计算机网络考纲知识点(更新中)
网络·网络协议·计算机网络
罗马苏丹默罕默德9 小时前
Ubuntu下部署.NetCore WebApi的方法
数据库·ubuntu·.netcore