如何在ASP.NET Core中编写高效的控制器
通过遵循最佳实践,可以编写更好的控制器。所谓的“瘦”控制器(指代码更少、职责更少的控制器)更容易阅读和维护。而且,一旦你的控制器很瘦,可能就不需要对它们进行太多测试了。相反,你可以专注于测试业务逻辑和数据访问代码。瘦控制器的另一个优点是,它更容易维护控制器的多个版本。
这篇文章讨论了使控制器变胖的坏习惯,然后探索了使控制器变瘦和易于管理的方法。我列出编写控制器的最佳实践可能并不全面,但我已经讨论了最重要的一些,并在适当的情况下提供了相关的源代码。在接下来的几节中,我们将研究什么是胖控制器,为什么它是一种代码坏味道,瘦控制器是什么,为什么它是有益的,以及如何使控制器瘦、简单、可测试和可管理。
从控制器中删除数据访问代码
在编写控制器时,你应该坚持单一责任原则,这意味着控制器应该有“一个责任”或“有且只有一个原因可以更改”。换句话说,你希望将更改控制器代码的原因减至最少。下面的代码显示了具有数据访问逻辑的典型控制器。
在.NET生态系统中使用特定的技术堆栈会产生一些困惑,因为有很多选择,比如应该使用哪种类型的运行时?在这篇文章中,我们将试图把这些要点都说清楚。
public class AuthorController : Controller
{
private AuthorContext dataContext = new AuthorContext();
public ActionResult Index(int authorId)
{
var authors = dataContext.Authors
.OrderByDescending(x=>x.JoiningDate)
.Where(x=>x.AuthorId == authorId)
.ToList();
return View(authors);
}
}
在action内部使用数据上下文实例读取数据,违反了单一职责原则,并使你的控制器充斥着不应该出现在那里的代码。在本例中,我们使用一个DataContext(假设我们使用Entity Framework Core)来连接、处理数据库中的数据。
明天如果你决定更改数据访问技术(为了更好的性能或其他原因),你也必须更改你的控制器。例如,如果我想使用Dapper连接到底层数据库该怎么办?更好的方法是使用repository类来封装数据访问逻辑(尽管我不太喜欢repository模式)。让我们用以下代码更新AuthorController。
public class AuthorController : Controller
{
private AuthorRepository authorRepository = new AuthorRepository();
public ActionResult Index(int authorId)
{
var authors = authorRepository.GetAuthor(authorId);
return View(authors);
}
}
控制器现在看起来更瘦了。那么这是编写这个控制器的最佳方法吗?不是。如果你的控制器正在访问数据访问组件,那么它将做太多的事情,因此违反了单一职责原则。控制器不应该有直接访问数据访问组件的数据访问逻辑或代码。下面是AuthorController类的改进版本。
public class AuthorController : Controller
{
private AuthorService authorService = new AuthorService();
public ActionResult Index(int authorId)
{
var authors = authorService.GetAuthor(authorId);
return View(authors);
}
}
AuthorService类利用AuthorRepository类执行CRUD操作。
public class AuthorService
{
private AuthorRepository authorRepository = new AuthorRepository();
public Author GetAuthor (int authorId)
{
return authorRepository.GetAuthor(authorId);
}
}
避免编写样板代码来映射对象
你经常需要映射数据传输对象(DTO)和域对象,反之亦然。请参考下面给出的代码片段,它显示了控制器方法内部的映射逻辑。
public IActionResult GetAuthor(int authorId)
{
var author = authorService.GetAuthor(authorId);
var authorDTO = new AuthorDTO();
authorDTO.AuthorId = author.AuthorId;
authorDTO.FirstName = author.FirstName;
authorDTO.LastName = author.LastName;
authorDTO.JoiningDate = author.JoiningDate;
}
你不应该在控制器中编写这样的映射逻辑,因为它会使控制器膨胀并增加额外的责任。如果你要编写映射逻辑,可以利用像AutoMapper这样的对象映射器工具来避免编写大量样板代码。
最后,你应该将映射逻辑移到前面创建的服务类中。注意AutoMapper是如何被用来映射两个不兼容的类型Author和AuthorDTO的。
public class AuthorService
{
private AuthorRepository authorRepository = new AuthorRepository();
public AuthorDTO GetAuthor (int authorId)
{
var author = authorRepository.GetAuthor(authorId);
return Mapper.Map<AuthorDTO>(author);
}
}
避免在控制器中编写业务逻辑代码
不应该在控制器中编写业务逻辑或验证逻辑。控制器应该只接受一个请求,然后跳转下一个action,除此之外没有其他的。所有的业务逻辑代码都应该转移到其他类中(比如我们前面创建的AuthorService类)。有几种方法可以在请求管道中设置验证器,而不要在控制器中编写验证逻辑。这会使你的控制器变得不必要的臃肿,并让它负责它不应该做的任务。
更喜欢依赖注入而不是组合
你应该更喜欢在控制器中使用依赖项注入来管理依赖项。依赖注入是控制反转(IoC)原则的一个子集。它用于通过允许从外部注入的依赖项删除内部依赖项。
通过利用依赖注入,你不必关心对象的实例化、初始化等。你可以有一个返回所需类型实例的工厂,然后可以使用构造函数注入来使用该实例。下面的代码片段说明了如何使用构造函数将IAuthorService类型的实例注入到AuthorController。(假设IAuthorService是AuthorService类扩展的接口。)
public class AuthorController : Controller
{
private IAuthorService authorService = new AuthorService();
public AuthorController(IAuthorService authorService)
{
this.authorService = authorService;
}
}
使用action过滤器来消除重复的代码
可以在asp.net core中使用action过滤器在请求管道中的特定点执行定制代码。例如,你可以使用action过滤器在操作action方法执行之前和之后执行自定义代码。你可以从控制器的action方法中删除验证逻辑,并将其写入action过滤器中,而不是在控制器中编写验证逻辑。下面的代码片段显示了如何实现这一点。
[ValidateModelState]
[HttpPost]
public ActionResult Create(AuthorRequest request)
{
AuthorService authorService = new AuthorService();
authorService.Save(request);
return RedirectToAction("Home");
}
你将多个职责分配给了一个控制器,那么也会有多个原因导致控制器更改。因此,这违反了单一责任原则,该原则规定类应该有且只有一个变更的理由。
原文链接:https://www.infoworld.com/article/3404472/how-to-write-efficient-controllers-in-aspnet-core.html
如何在ASP.NET Core中编写高效的控制器的更多相关文章
- 如何在ASP.NET Core中自定义Azure Storage File Provider
文章标题:如何在ASP.NET Core中自定义Azure Storage File Provider 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p ...
- 如何在 ASP.Net Core 中使用 Lamar
ASP.Net Core 自带了一个极简的 开箱即用 的依赖注入容器,实际上,你还可以使用第三方的 依赖注入容器 来替代它,依赖注入是一种设计模式,它能够有效的实现对象之间的解耦并有利于提高单元测试和 ...
- 如何在ASP.NET Core中实现CORS跨域
注:下载本文的完整代码示例请访问 > How to enable CORS(Cross-origin resource sharing) in ASP.NET Core 如何在ASP.NET C ...
- 如何在ASP.NET Core中实现一个基础的身份认证
注:本文提到的代码示例下载地址> How to achieve a basic authorization in ASP.NET Core 如何在ASP.NET Core中实现一个基础的身份认证 ...
- 如何在ASP.NET Core中应用Entity Framework
注:本文提到的代码示例下载地址> How to using Entity Framework DB first in ASP.NET Core 如何在ASP.NET Core中应用Entity ...
- [转]如何在ASP.NET Core中实现一个基础的身份认证
本文转自:http://www.cnblogs.com/onecodeonescript/p/6015512.html 注:本文提到的代码示例下载地址> How to achieve a bas ...
- 如何在ASP.NET Core中使用Azure Service Bus Queue
原文:USING AZURE SERVICE BUS QUEUES WITH ASP.NET CORE SERVICES 作者:damienbod 译文:如何在ASP.NET Core中使用Azure ...
- 如何在ASP.NET Core中使用JSON Patch
原文: JSON Patch With ASP.NET Core 作者:.NET Core Tutorials 译文:如何在ASP.NET Core中使用JSON Patch 地址:https://w ...
- [翻译] 如何在 ASP.Net Core 中使用 Consul 来存储配置
[翻译] 如何在 ASP.Net Core 中使用 Consul 来存储配置 原文: USING CONSUL FOR STORING THE CONFIGURATION IN ASP.NET COR ...
随机推荐
- BootstrapValidator验证规则、BootStrap表格:列参数
BootstrapValidator验证规则 需引用组件 <script src="~/Scripts/jquery-1.10.2.js"></script> ...
- 重绘和回流(Repaint & Reflow)总结,以及如何进行优化
1. 浏览器渲染机制 浏览器采用流式布局模型(Flow Based Layout) 浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了渲染树(Render Tre ...
- php 7.4 vcruntime140.dll not compatible with PHP
安装PHP7.4以上版本时,在运行PHP时会提示如下: PHP Warning: 'vcruntime140.dll' 14.0 is not compatible with this PHP bui ...
- yum.repos.d中的变量($releasever与$basearch)
今天打算更新一下centos的repo源,把原先国外的repo地址换成国内的,速度快一些.主要替换的文件是/etc/yum.repos.d/Centos-Base.repo .替换的时候,不知道大家有 ...
- 浅谈Winform控件开发(一):使用GDI+美化基础窗口
写在前面: 本系列随笔将作为我对于winform控件开发的心得总结,方便对一些读者在GDI+.winform等技术方面进行一个入门级的讲解,抛砖引玉. 别问为什么不用WPF,为什么不用QT.问就是懒, ...
- Python3列表、元组及之间的区别和转换
文章目录 1. 列表(list) 1.1 列表创建.切片.删除.检索 1.2 列表常用函数 2. 元组(tuple) 3. 列表与元组区别及转换 1. 列表(list) 1.1 列表创建.切片.删除. ...
- 搭建tdh平台
1.卸载tdh平台(见tdh集群卸载文件夹) 在manager节点执行chmod +x uninstall.sh (非root用户执行sudo chmod +x uninstall.sh)开始卸载TD ...
- HDU2065 "红色病毒"问题 【组合数学 二项式定理】
HDU2065 "红色病毒"问题 Description: 医学界发现的新病毒因其蔓延速度和Internet上传播的"红色病毒"不相上下,被称为"红色 ...
- acm内容
- AtCoder Beginner Contest 188 E - Peddler (树)
题意:有\(n\)个点,\(m\)条单向边,保证每条边的起点小于终点,每个点都有权值,找到联通的点的两个点的最大差值. 题解:因为题目说了起点小于终点,所以我们可以反向存边,然后维护连通边的前缀最小值 ...