当前位置: 首页 > news >正文

C#开发后端:API 控制器(Controller)

要理解 API 控制器(Controller)的作用和代码构成,核心可以总结为:它是 “前端(小程序)和后端(服务 / 数据库)的中间桥梁”—— 接收前端请求、转发给服务层处理、返回结果给前端

具体来说,整个流程的终点就是数据库:

  1. 前端收集用户输入的活动信息(如标题、时间、类型等);
  2. 前端通过接口调用(如 POST 请求)将信息发送给后端的ActivityController
  3. 后端控制器(ActivityController)中的CreateActivity方法接收数据,经过验证和处理(如自动填充AddTimeUpdateTime)后,通过数据库上下文(DbContext)将数据保存到数据库;
  4. 最终,这些活动内容会被写入数据库中名为sr_activity的表(对应实体类Sr_Activity[Table("sr_activity")]配置),你可以在数据库中查询该表看到新增的活动记录

以下举例以微信小程序商城的banner和product举例

一、API 控制器(Controller)的核心作用

简单说,Controller 只做 “3 件事”,不承担复杂业务逻辑(复杂逻辑交给 Service 层):

  1. 接收请求:接收小程序发送的 HTTP 请求(比如 “获取 Banner 列表”“查询商品详情”),拿到请求参数(如商品 ID、分页页码)。
  2. 转发处理:把请求参数传给对应的 Service 层(比如 BannerServiceProductService),让 Service 去调用数据库或处理业务。
  3. 返回响应:接收 Service 层的处理结果,包装成小程序能识别的格式(如 JSON),返回给前端(成功则带数据,失败则带错误信息)。

二、Controller 里一般要写的代码(完整结构 + 示例)

代码结构分为 5 个核心部分,每部分都有明确用途:

1. 基础结构(必须有)
  • 命名空间:对应项目目录(如 项目.Controllers)。
  • 继承 ControllerBase:ASP.NET Core 提供的 API 控制器基类,包含返回响应的方法(如 Ok()BadRequest())。
  • 特性标签:
    • [ApiController]:自动启用参数校验、JSON 格式返回等 API 专属功能。
    • [Route("api/[controller]")]:定义接口的基础 URL(如 BannerController 对应 api/bannerProductController 对应 api/product)。
// 1. 基础结构:命名空间+继承+特性
using Microsoft.AspNetCore.Mvc;
using Pgy_Wx.Services; // 引用服务层
using Pgy_Wx.Entities.Dto; // 引用请求/响应的DTO(数据传输对象)namespace Pgy_Wx.Controllers
{[ApiController] // 标记为API控制器[Route("api/[controller]")] // 基础URL:api/bannerpublic class BannerController : ControllerBase // 继承ControllerBase{// 2. 依赖注入:注入对应的Service(核心,避免Controller直接操作数据库)private readonly IBannerService _bannerService;// 构造函数:通过依赖注入获取Service实例public BannerController(IBannerService bannerService){_bannerService = bannerService;}// 3. Action方法:具体的API接口(每个方法对应一个前端请求)// 示例1:小程序端获取Banner列表(GET请求)[HttpGet("list")] // 完整URL:api/banner/list(GET请求)public async Task<IActionResult> GetBannerList(){// 步骤1:调用Service层获取数据(Controller不做复杂逻辑)var bannerList = await _bannerService.GetActiveBannerAsync();// 步骤2:包装响应返回给前端(JSON格式,带状态码)return Ok(new { code = 200, // 自定义业务状态码(方便前端判断)message = "获取成功", data = bannerList // 实际返回的数据});}// 示例2:后台管理端新增Banner(POST请求,需授权)[HttpPost("add")] // 完整URL:api/banner/add(POST请求)[Authorize(Roles = "Admin")] // 只有管理员能调用(需配置JWT授权)public async Task<IActionResult> AddBanner([FromBody] BannerAddDto dto){// 步骤1:参数校验(简单校验放Controller,复杂校验放Service)if (string.IsNullOrEmpty(dto.ImageUrl)){return BadRequest(new { code = 400, message = "Banner图片地址不能为空" });}if (string.IsNullOrEmpty(dto.JumpUrl)){return BadRequest(new { code = 400, message = "Banner跳转地址不能为空" });}// 步骤2:调用Service层执行新增逻辑await _bannerService.AddBannerAsync(dto);// 步骤3:返回成功响应return Ok(new { code = 200, message = "Banner新增成功" });}// 示例3:根据ID删除Banner(DELETE请求)[HttpDelete("delete/{id}")] // 完整URL:api/banner/delete/1(1是Banner的ID)[Authorize(Roles = "Admin")]public async Task<IActionResult> DeleteBanner(int id){// 步骤1:调用Service判断Banner是否存在var exists = await _bannerService.CheckBannerExistsAsync(id);if (!exists){return NotFound(new { code = 404, message = "Banner不存在" });}// 步骤2:调用Service执行删除await _bannerService.DeleteBannerAsync(id);// 步骤3:返回响应return Ok(new { code = 200, message = "Banner删除成功" });}}
}
2. 核心代码模块拆解

结合上面的示例,Controller 里的代码主要包含以下 4 类核心内容:

代码模块作用关键细节
依赖注入注入 Service 层实例,让 Controller 能调用业务逻辑(解耦,不直接操作数据库)必须通过构造函数注入(如 private readonly IBannerService _bannerService),不能自己 new Service。
Action 方法对应具体的 API 接口,每个方法处理一种前端请求用 [HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete] 标记请求类型,括号里写接口的子路径(如 [HttpGet("list")])。
参数处理接收前端传递的参数(如商品 ID、分页参数、新增数据)常用参数来源:- [FromQuery]:URL 参数(如 api/product/list?page=1&size=10)- [FromBody]:请求体(POST/PUT 传递 JSON 数据,如新增 Banner 的图片 / 跳转地址)- [FromRoute]:URL 路径参数(如 api/banner/delete/{id} 中的 id
响应返回把处理结果包装成前端能识别的格式返回用 ControllerBase 提供的方法:- Ok():成功(HTTP 200)- BadRequest():参数错误(HTTP 400)- NotFound():资源不存在(HTTP 404)- Unauthorized():未授权(HTTP 401)返回内容建议包含 code(业务状态码)、message(提示信息)、data(数据),方便前端统一处理。

三、Controller 的核心原则(避坑重点)

  1. 不写复杂业务逻辑:Controller 只做 “转发” 和 “简单校验”,比如参数是否为空、ID 是否为正数;复杂逻辑(如 Banner 排序、商品库存判断)必须放在 Service 层。
  2. 参数校验要做:简单的参数合法性校验(如必填项、格式)放在 Controller,避免无效请求传到 Service 层,提高效率。
  3. 响应格式统一:所有接口返回相同结构(如 {code, message, data}),让小程序前端能写统一的响应处理逻辑(不用每次判断返回格式)。
  4. 依赖注入解耦:绝对不要在 Controller 里 new IBannerService(),必须通过构造函数注入 —— 这样方便后期替换 Service 实现、写单元测试。

四、再举一个 ProductController 的关键接口示例(加深理解)

[ApiController]
[Route("api/[controller]")] // 基础URL:api/product
public class ProductController : ControllerBase
{private readonly IProductService _productService;public ProductController(IProductService productService){_productService = productService;}// 小程序端:获取商品详情(URL路径参数:api/product/detail/123)[HttpGet("detail/{id}")]public async Task<IActionResult> GetProductDetail(int id){// 1. 参数校验(ID不能小于1)if (id < 1){return BadRequest(new { code = 400, message = "商品ID无效" });}// 2. 调用Service获取商品详情(含关联的SKU、图片、品牌)var productDetail = await _productService.GetProductDetailAsync(id);if (productDetail == null){return NotFound(new { code = 404, message = "商品不存在或已下架" });}// 3. 返回结果return Ok(new { code = 200, message = "获取成功", data = productDetail });}// 小程序端:商品列表(带分页和分类筛选,URL参数:api/product/list?categoryId=2&page=1&size=10)[HttpGet("list")]public async Task<IActionResult> GetProductList([FromQuery] int categoryId = 0, // 分类ID(0表示全部)[FromQuery] int page = 1,       // 页码(默认1)[FromQuery] int size = 10       // 每页数量(默认10)){// 1. 参数校验(分页参数不能小于1)if (page < 1) page = 1;if (size < 1 || size > 50) size = 10; // 限制最大每页50条// 2. 调用Service获取分页列表var (productList, totalCount) = await _productService.GetProductPageAsync(categoryId, page, size);// 3. 返回结果(带总页数,方便前端做分页控件)return Ok(new { code = 200, message = "获取成功", data = new { list = productList, totalCount = totalCount, totalPage = (int)Math.Ceiling((double)totalCount / size) } });}
}

总结

  • Controller 是干嘛的:前端请求的 “接收站” 和 “中转站”,连接小程序和后端服务,不做复杂业务。
  • 里面要写什么:基础结构(命名空间 + 特性)、依赖注入(Service)、Action 方法(接口)、参数处理、统一响应。
  • 关键原则:不堆业务逻辑、参数要校验、响应要统一、依赖要注入。
http://www.dtcms.com/a/531788.html

相关文章:

  • 建湖人才网招工湛江怎么做网站关键词优化
  • 深入理解 Flink SQL 状态:原理、应用与优化
  • Product Hunt 每日热榜 | 2025-10-26
  • Java的语法与Python进行对比学习
  • 【MCAL实战】CanTrcv模块配置实践
  • coco 可视化 txt版
  • idea字体的问题(idea应用本身的字体问题)
  • 计算机操作系统 — 链接
  • 网站图片加altwordpress前端库加速
  • 在linux上使用docker搭建ELK日志框架
  • Docker 应该如何学习 分四个阶段
  • 面试过程中的扣分项,你踩过几个?
  • 中牟高端网站建设专做户外装备测评视频网站
  • CSS属性(二)
  • 2011年下半年试题四:论软件需求获取技术及应用
  • Mujoco 仿真 PPO 强化学习机械臂末端路径规划到达指定位置(代码讲解)
  • 【C#】EventHandler的使用
  • C++ 实际应用系列(第六部分):并发系统的性能优化与工程实践(完)
  • 上市公司网站建设分析wordpress 转 app
  • Prometheus+Grafana 智能监控告警系统(服务器指标采集、mysql指标采集)
  • html5电影网站如何做企业网站流量怎么做
  • <数据集>yolo煤矿安全帽识别数据集<目标检测>
  • excel中加载数据分析工具的步骤
  • 一文厘清:文库 vs 知识库、核心功能清单、开源方案对比
  • 图片转excel vlm 提取手写清单信息 Qwen/Qwen3-VL-235B-A22B-Instruct
  • webrtc代码走读(七)-QOS-FEC-ulpfec rfc5109
  • 第十五章认识Ajax(六)
  • 逻辑回归解释
  • B038基于博途西门子1200PLC物料分拣控制系统仿真
  • 第十二章认识Ajax(三)