詳解如何在ASP.NET Core中編寫高效的控制器
通過遵循最佳實踐,可以編寫更好的控制器。所謂的“瘦”控制器(指代碼更少、職責(zé)更少的控制器)更容易閱讀和維護(hù)。而且,一旦你的控制器很瘦,可能就不需要對它們進(jìn)行太多測試了。相反,你可以專注于測試業(yè)務(wù)邏輯和數(shù)據(jù)訪問代碼。瘦控制器的另一個優(yōu)點是,它更容易維護(hù)控制器的多個版本。
這篇文章討論了使控制器變胖的壞習(xí)慣,然后探索了使控制器變瘦和易于管理的方法。我列出編寫控制器的最佳實踐可能并不全面,但我已經(jīng)討論了最重要的一些,并在適當(dāng)?shù)那闆r下提供了相關(guān)的源代碼。在接下來的幾節(jié)中,我們將研究什么是胖控制器,為什么它是一種代碼壞味道,瘦控制器是什么,為什么它是有益的,以及如何使控制器瘦、簡單、可測試和可管理。
從控制器中刪除數(shù)據(jù)訪問代碼
在編寫控制器時,你應(yīng)該堅持單一責(zé)任原則,這意味著控制器應(yīng)該有“一個責(zé)任”或“有且只有一個原因可以更改”。換句話說,你希望將更改控制器代碼的原因減至最少。下面的代碼顯示了具有數(shù)據(jù)訪問邏輯的典型控制器。
在.NET生態(tài)系統(tǒng)中使用特定的技術(shù)堆棧會產(chǎn)生一些困惑,因為有很多選擇,比如應(yīng)該使用哪種類型的運行時?在這篇文章中,我們將試圖把這些要點都說清楚。
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內(nèi)部使用數(shù)據(jù)上下文實例讀取數(shù)據(jù),違反了單一職責(zé)原則,并使你的控制器充斥著不應(yīng)該出現(xiàn)在那里的代碼。在本例中,我們使用一個DataContext(假設(shè)我們使用Entity Framework Core)來連接、處理數(shù)據(jù)庫中的數(shù)據(jù)。
明天如果你決定更改數(shù)據(jù)訪問技術(shù)(為了更好的性能或其他原因),你也必須更改你的控制器。例如,如果我想使用Dapper連接到底層數(shù)據(jù)庫該怎么辦?更好的方法是使用repository類來封裝數(shù)據(jù)訪問邏輯(盡管我不太喜歡repository模式)。讓我們用以下代碼更新AuthorController。
public class AuthorController : Controller { private AuthorRepository authorRepository = new AuthorRepository(); public ActionResult Index(int authorId) { var authors = authorRepository.GetAuthor(authorId); return View(authors); } }
控制器現(xiàn)在看起來更瘦了。那么這是編寫這個控制器的最佳方法嗎?不是。如果你的控制器正在訪問數(shù)據(jù)訪問組件,那么它將做太多的事情,因此違反了單一職責(zé)原則??刂破鞑粦?yīng)該有直接訪問數(shù)據(jù)訪問組件的數(shù)據(jù)訪問邏輯或代碼。下面是AuthorController類的改進(jìn)版本。
public class AuthorController : Controller { private AuthorService authorService = new AuthorService(); public ActionResult Index(int authorId) { var authors = authorService.GetAuthor(authorId); return View(authors); } }
AuthorService類利用AuthorRepository類執(zhí)行CRUD操作。
public class AuthorService { private AuthorRepository authorRepository = new AuthorRepository(); public Author GetAuthor (int authorId) { return authorRepository.GetAuthor(authorId); } }
避免編寫樣板代碼來映射對象
你經(jīng)常需要映射數(shù)據(jù)傳輸對象(DTO)和域?qū)ο?,反之亦然。請參考下面給出的代碼片段,它顯示了控制器方法內(nèi)部的映射邏輯。
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; }
你不應(yīng)該在控制器中編寫這樣的映射邏輯,因為它會使控制器膨脹并增加額外的責(zé)任。如果你要編寫映射邏輯,可以利用像AutoMapper這樣的對象映射器工具來避免編寫大量樣板代碼。
最后,你應(yīng)該將映射邏輯移到前面創(chuàng)建的服務(wù)類中。注意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); } }
避免在控制器中編寫業(yè)務(wù)邏輯代碼
不應(yīng)該在控制器中編寫業(yè)務(wù)邏輯或驗證邏輯。控制器應(yīng)該只接受一個請求,然后跳轉(zhuǎn)下一個action,除此之外沒有其他的。所有的業(yè)務(wù)邏輯代碼都應(yīng)該轉(zhuǎn)移到其他類中(比如我們前面創(chuàng)建的AuthorService類)。有幾種方法可以在請求管道中設(shè)置驗證器,而不要在控制器中編寫驗證邏輯。這會使你的控制器變得不必要的臃腫,并讓它負(fù)責(zé)它不應(yīng)該做的任務(wù)。
更喜歡依賴注入而不是組合
你應(yīng)該更喜歡在控制器中使用依賴項注入來管理依賴項。依賴注入是控制反轉(zhuǎn)(IoC)原則的一個子集。它用于通過允許從外部注入的依賴項刪除內(nèi)部依賴項。
通過利用依賴注入,你不必關(guān)心對象的實例化、初始化等。你可以有一個返回所需類型實例的工廠,然后可以使用構(gòu)造函數(shù)注入來使用該實例。下面的代碼片段說明了如何使用構(gòu)造函數(shù)將IAuthorService類型的實例注入到AuthorController。(假設(shè)IAuthorService是AuthorService類擴(kuò)展的接口。)
public class AuthorController : Controller { private IAuthorService authorService = new AuthorService(); public AuthorController(IAuthorService authorService) { this.authorService = authorService; } }
使用action過濾器來消除重復(fù)的代碼
可以在asp.net core中使用action過濾器在請求管道中的特定點執(zhí)行定制代碼。例如,你可以使用action過濾器在操作action方法執(zhí)行之前和之后執(zhí)行自定義代碼。你可以從控制器的action方法中刪除驗證邏輯,并將其寫入action過濾器中,而不是在控制器中編寫驗證邏輯。下面的代碼片段顯示了如何實現(xiàn)這一點。
[ValidateModelState] [HttpPost] public ActionResult Create(AuthorRequest request) { AuthorService authorService = new AuthorService(); authorService.Save(request); return RedirectToAction("Home"); }
你將多個職責(zé)分配給了一個控制器,那么也會有多個原因?qū)е驴刂破鞲?。因此,這違反了單一責(zé)任原則,該原則規(guī)定類應(yīng)該有且只有一個變更的理由。
到此這篇關(guān)于詳解如何在ASP.NET Core中編寫高效的控制器的文章就介紹到這了,更多相關(guān)ASP.NET Core 控制器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- ASP.NET?Core?MVC創(chuàng)建控制器與依賴注入講解
- ASP.NET Core MVC解決控制器同名Action請求不明確的問題
- Asp.Net Core控制器如何接收原始請求正文內(nèi)容詳解
- Asp.net Core MVC中怎么把二級域名綁定到特定的控制器上
- ASP.NET MVC從視圖傳參到控制器的幾種形式
- 詳解Asp.Net MVC——控制器與動作(Controller And Action)
- ASP.NET MVC從控制器傳遞數(shù)據(jù)到視圖的四種方式詳解
- Asp.net MVC中獲取控制器的名稱的方法
- ASP.NET中MVC從后臺控制器傳遞數(shù)據(jù)到前臺視圖的方式
- ASP.NET MVC 控制器與視圖
- ASP.NET?MVC從控制器中獲取URL值
相關(guān)文章
獲取遠(yuǎn)程網(wǎng)頁的內(nèi)容之一(downmoon原創(chuàng))
獲取遠(yuǎn)程網(wǎng)頁的內(nèi)容之一(downmoon原創(chuàng))...2007-03-03dz asp.net論壇中函數(shù)--根據(jù)Url獲得源文件內(nèi)容
從asp.net dz論壇發(fā)現(xiàn)的這個函數(shù),學(xué)習(xí)一下高手的經(jīng)驗代碼2008-09-09ASP.NET?Core?MVC自定義Tag?Helpers用法介紹
這篇文章介紹了ASP.NET?Core?MVC自定義Tag?Helpers的用法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-02-02ASP.NET MVC3 SEO優(yōu)化:利用Routing特性提高站點權(quán)重
這篇文章主要介紹了ASP.NET MVC3 SEO優(yōu)化:利用Routing特性消除多個路徑指向同一個Action,從而提高站點權(quán)重,需要的朋友可以參考下。2016-06-06.NET下通過HttpListener實現(xiàn)簡單的Http服務(wù)
這篇文章主要為大家詳細(xì)介紹了.NET下通過HttpListener實現(xiàn)簡單Http服務(wù)的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-09-09ASP.NET開發(fā)者使用jQuery應(yīng)該了解的幾件事情
如果你是有著APS.NET開發(fā)背景的人員,那么jQuery的幾個概念建議你應(yīng)該忘掉。像使用其它的framework一樣,你應(yīng)該學(xué)習(xí)一下jQuery的所有語法等約定來讓它更好的為你服務(wù)。2009-09-09