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

相关推荐
玖玥拾1 天前
C# 语言进阶(十三)网络 DLL 库分层设计
服务器·开发语言·网络·网络协议·c#
大师兄66681 天前
HarmonyOS7 HTTP 网络请求封装:统一拦截器实战
网络·网络协议·http·arkui·harmonyos7·实战讲解
韩曙亮1 天前
【Flutter】iOS 网络权限设置 ② ( 配置 iOS 平台可使用 HTTP 访问 | ATS 网络安全强制规范 )
网络·flutter·http·ios·https·网络权限·ats
tiantianuser1 天前
NVME-oF IP 设计1 :为什么要设计它?
网络·网络协议·rdma·roce v2·nvme of
有毒的教程1 天前
生产环境Socket编程落地实战指南(TCP/UDP工程化方案)
网络协议·tcp/ip·udp
草根站起来1 天前
“双算法SSL证书”伪方案、国产SSL证书营销话术与等保绑定乱象批判
网络·网络协议·ssl
江华森2 天前
Web 开发基础:HTTP 与 REST
前端·网络协议·http
her_heart2 天前
把 ChatGPT 5.6 放进需求评审和测试设计之后,我反而减少了“一次成稿”的期待
网络·人工智能·网络协议·chatgpt·测试用例
coderhuo2 天前
libcurl blind sleep导致的耗时问题
网络协议
treesforest2 天前
做内容平台,IP地址精准定位和IP高精度定位查询怎么帮我们提升用户留存
网络·网络协议·tcp/ip