.NET Core开发实战(第31课:APIController:定义API的最佳实践)--学习笔记
31 | APIController:定义API的最佳实践
首先看一个传统意义上三层架构定义的 Controller
[HttpPost]
public Task<long> CreateOrder([FromBody]CreateOrderVeiwModel viewModel)
{
var model = viewModel.ToModel();
return await orderService.CreateOrder(model);
}
class OrderService : IOrderService
{
public long CreateOrder(CreateOrderModel model)
{
var address = new Address("wen san lu", "hangzhou", "310000");
var order = new Order("xiaohong1999", "xiaohong", 25, address);
_orderRepository.Add(order);
await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
return order.Id;
}
}
可以看到这里的 Controller 负责模型转换,还负责服务调用,服务里面实际上就是领域模型的操作部分
随着业务逻辑的越来越复杂,Controller 会越来越膨胀,在 DDD 领域驱动设计的理念下,我们更倾向于把应用程序的每一层明确区分,然后层与层之间的界限应该是明确的,在实现上面应该也是隔离的
Controller 这一层负责与前端用户的交互,它主要的责任就是定义输入和输出,实现身份认证,授权功能,它不应该处理领域模型,处理仓储,所以不建议以上的写法,不建议在 Controller 里面写模型转换和服务调用
namespace GeekTime.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class OrderController : ControllerBase
{
IMediator _mediator;
public OrderController(IMediator mediator)
{
_mediator = mediator;
}
[HttpPost]
public async Task<long> CreateOrder([FromBody]CreateOrderCommand cmd)
{
return await _mediator.Send(cmd, HttpContext.RequestAborted);
}
[HttpGet]
public async Task<List<string>> QueryOrder([FromBody]MyOrderQuery myOrderQuery)
{
return await _mediator.Send(myOrderQuery);
}
}
}
这里使用了中间者模式 Mediator,它通过把命令发送出去,然后我们在 Commands 目录下面定义了每一个命令的 handler,这样就可以将业务逻辑的部分和 Controller 处理的部分,输入输出定义的部分进行隔离,我们的 Controller 还需要去定义路由的规则,路由验证的规则
再看一下 Controller 的构造函数,从设计上建议 Controller 所依赖的服务都通过它的构造函数注入进来,之前有讲过,通过容器进行属性注入的方式,但这种方式我们并不推荐使用,当一个 Controller 依赖了很多服务的时候,可以发现有一部分服务是大部分的 Action 都会依赖到的,有一部分服务只是个别 Action 依赖到的,这个时候就可以使用 FromServices,而不需要在构造函数里面注入它,这样有个好处是在编写单元测试的时候,可以在容器里面 Mock 所有的服务
public async Task<long> CreateOrder([FromServices] IEventBus eventBus, [FromBody]CreateOrderCommand cmd)
这里不建议使用属性注入的方式来注入服务,是因为使用属性注入的时候,会把这些属性,比如说 IOrderService,有可能由其他代码 set 我们的 OrderService,造成意外的情况,使我们的代码的维护不可控
public IOrderService orderService { get; set; }
还有一个关键的点是建议尽可能定义异步的 action,尽可能地使用 async 和 await 这样的组合来实现我们的代码,这样对提高我们应用程序的吞吐量是有一定的帮助的
总结一下
APIController 实际上是负责了对前端用户的输入输出的定义,它还负责了身份验证,授权,Url 定义的部分
APIController 不应该负责业务逻辑的承载,应该把这些职责交给我们命令处理程序或者说领域服务来定义
再一个我们也讲解了 APIController 在注入服务时的一些方法,通过构造函数的注入,通过 FromServices 的方式获取服务,不建议的做法时使用属性注入的方式注入
GitHub源码链接:
https://github.com/witskeeper/geektime



本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。
.NET Core开发实战(第31课:APIController:定义API的最佳实践)--学习笔记的更多相关文章
- 2月送书福利:ASP.NET Core开发实战
大家都知道我有一个公众号“恰童鞋骚年”,在公众号2020年第一天发布的推文<2020年,请让我重新介绍我自己>中,我曾说到我会在2020年中每个月为所有关注“恰童鞋骚年”公众号的童鞋们送一 ...
- [ASP.NET Core开发实战]开篇词
前言 本系列课程文章主要是学习官方文档,再输出自己学习心得,希望对你有所帮助. 课程大纲 本系列课程主要分为三个部分:基础篇.实战篇和部署篇. 希望通过本系列课程,能让大家初步掌握使用ASP.NET ...
- [ASP.NET Core开发实战]基础篇02 依赖注入
ASP.NET Core的底层机制之一是依赖注入(DI)设计模式,因此要好好掌握依赖注入的用法. 什么是依赖注入 我们看一下下面的例子: public class MyDependency { pub ...
- 测试开发实战[提测平台]20-图表G2Plot在项目的实践实录
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. G2Plot项目应用 上一篇<提测平台19-Echarts图表在项目的实践>讲解了Echarts的图表应用,此篇来看下开箱即用 ...
- .NET Core开发实战(第11课:文件配置提供程序)--学习笔记
11 | 文件配置提供程序:自由选择配置的格式 文件配置提供程序 Microsoft.Extensions.Configuration.Ini Microsoft.Extensions.Configu ...
- 2、SpringBoot接口Http协议开发实战8节课(1-6)
1.SpringBoot2.xHTTP请求配置讲解 简介:SpringBoot2.xHTTP请求注解讲解和简化注解配置技巧 1.@RestController and @RequestMapping是 ...
- [ASP.NET Core开发实战]基础篇03 中间件
什么是中间件 中间件是一种装配到应用管道,以处理请求和响应的组件.每个中间件: 选择是否将请求传递到管道中的下一个中间件. 可在管道中的下一个中间件前后执行. ASP.NET Core请求管道包含一系 ...
- [ASP.NET Core开发实战]基础篇01 Startup
Startup,顾名思义,就是启动类,用于配置ASP.NET Core应用的服务和请求管道. Startup有两个主要作用: 通过ConfigureServices方法配置应用的服务.服务是一个提供应 ...
- 2、SpringBoot接口Http协议开发实战8节课(7-8)
7.SpringBoot2.x文件上传实战 简介:讲解HTML页面文件上传和后端处理实战 1.讲解springboot文件上传 MultipartFile file,源自SpringMVC 1)静态页 ...
- [ASP.NET Core开发实战]基础篇06 配置
配置,是应用程序很重要的组成部分,常常用于提供信息,像第三方应用登录钥匙.上传格式与大小限制等等. ASP.NET Core提供一系列配置提供程序读取配置文件或配置项信息. ASP.NET Core项 ...
随机推荐
- .NET CORE实战项目之CMS 开发篇 思维导图
导图地址下载: 链接:https://pan.baidu.com/s/1sGiNZI-pc_yueqQiddvImQ 提取码:ql4v -------------------------------- ...
- maven总结二: 常用标签及属性
本文为博主原创,未经允许不得转载 目录: 1. maven 依赖属性:groupId.artifactId.version 2.插件执行: execution,id ,phase,goals,con ...
- git或gitee 提交代码到远程仓库
本文为博主原创,未经允许不得转载: 1. 选中远程仓库,并fork 指定的项目到自己的私仓: fork 之后,打开我的仓库便能看到刚刚fork 的项目. 2. clone 项目代码到自己电脑的本地仓库 ...
- ORA-65140: 无效的通用配置文件名称
1.问题 CREATE PROFILE PM_Profile LIMIT SESSIONS_PER_USER 100 PASSWORD_LIFE_TIME 90; 在创建概要文件时,报错:ORA-65 ...
- 使用VS开发人员工具观察类在内存中的布局
1.先要生成相应文件 2.打开VS2019开发人员工具 3.cd至文件目录 4.输入cl /d1 reportSingleClassLayoutanimal demo.cpp 其中reportSing ...
- 【Git】如何在github上提交PR(Pull Request)
[来源]https://mp.weixin.qq.com/s/yHQRjpVeZVV4PuoUKM0FSw
- GoMusic-歌单迁移工具网站 一键迁移网易云/QQ音乐歌单至 Apple/Youtube/Spotify Music
GoMusic是什么: GoMusic是一个在线歌单迁移工具网站,帮助用户一键迁移网易云/QQ音乐歌单至 Apple/Youtube/Spotify Music,直接输入歌单链接,复制查询结果,打开 ...
- [转帖]Strong crypto defaults in RHEL 8 and deprecation of weak crypto algorithms
https://access.redhat.com/articles/3642912 TABLE OF CONTENTS What policies are provided? Removed c ...
- [转帖]一、Kafka Tool使用
一.Kafka Tool使用 1.添加cluster 2.开启SASL_PLAINTEXT 如果kafka 开启SASL_PLAINTEXT认证(用户名和密码认证) 3.高级设置 如果设置的是SASL ...
- 华城金锐申威SW64服务器重装过程
华城金锐申威SW64服务器重装过程 背景 这边为了进行兼容性验证新进了两套申威的服务器. 一台机器带着安装好的操作系统了. 但是另外一套没有对应的系统. 端午期间想着趁着上班的人少, 加吧给处理一下. ...