ABP虛擬檔案系統(VirtualFileSystem)例項------定製選單欄顯示使用者姓名
ABP預設的MVC啟動模板在登入後, 右上角顯示的是使用者名稱:
如果想讓它顯示使用者的姓名該如何做呢?這就需要用到ABP一個非常強大的功能------虛擬檔案系統.
前期準備
使用ABP CLI建立一個名為AbpStudy
的ASP.NET MVC專案:
abp new AbpStudy
關於MVC的啟動模板可以看文件, 這裡就不贅述.
虛擬檔案系統(VirtualFileSystem)
什麼是虛擬檔案系統(簡稱VFS)呢?來看一段官方文件的解釋:
虛擬檔案系統可以管理檔案系統(磁碟)上實際不存在的檔案。 它主要用於將(js,css,image,cshtml ...)檔案嵌入到程式集中,並在執行時將它們用作物理檔案。
是不是還是不太明白VFS有什麼用, 沒關係我第一次看完也是這樣:)
我們首先要知道, ABP是一個模組化的框架, 每個模組都可以互相協作參與到整個應用程式中, 定製應用程式的各個部分, 包括UI部分.
每個模組都可以有自己的UI, 比如我有一個"人事管理"模組, 它要向選單中增加一個名為"人事管理"的選單入口;而另一個模組"財務管理"則需要增加一個"財務管理"的選單入口------在不修改你的應用程式的前提下要把它們整合在一起,這是一個很難的事,ABP的前身ASP.NET BOILERPLATE未能實現這點, 而這一切在ABP中成為了可能.
而除了整合以外, 模組間的檔案同樣也可以覆蓋, 只要檔案的路徑相同,VFS就允許你利用你自己的檔案覆蓋官方模組中的檔案實現UI的定製,因為所有這些檔案都是由VFS來進行管理, 它們都是虛擬的!
覆蓋
如上圖中MVC啟動模板的外觀, 是一個叫Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic
的模組來控制的, 這是一個主題模組, 提供了ASP.NET MVC經典的外觀. 將來ABP還會有別的主題模組,你只要整合進來,你的應用程式就會顯示成另外的樣子了, 當然這是題外話了.
而右上角顯示的使用者名稱也是由它控制的,我們可以通過查閱ABP的原始碼, 找到相關的程式碼是在Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Themes\Basic\Components\Toolbar\UserMenu\Default.cshtml
中:
<a class="btn btn-link dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> @CurrentUser.UserName </a>
這裡的@CurrentUser.UserName
就是渲染使用者名稱的程式碼. 找到它之後, 我們就可以實現"精準打擊"式的覆蓋了.
在我們的Web工程下,仿造路徑結構建立一個Themes\Basic\Components\Toolbar\UserMenu\Default.cshtml
(不需要Default.cshmtl.cs)
你也可以[新建一個模組], 並在新建模組中完成覆蓋,然後在你的應用程式中將該模組整合進來, 這樣的好處是如果將來其他應用程式也想顯示使用者的姓名的話,就可以複用你的模組了. 我們這裡為了簡單起見,直接使用Web工程了.(Web工程同樣也是一個模組)
將原Default.cshtml中的全部程式碼直接複製過來, 但是把其中渲染使用者名稱的程式碼改成渲染姓名:
@* 顯示使用者的名字,而不是使用者名稱 *@
@((await UserManager.GetByIdAsync(CurrentUser.GetId())).Name)
這裡我們使用了UserManager, 通過當前登入使用者的ID獲取使用者的資訊, 其中就包括了使用者的姓名. 要使用UserManager
, 首先需要在Default.cshtml的開始部分增加一行程式碼完成UserManager的注入:
@inject IdentityUserManager UserManager
最後我們需要告知VFS, 在Web工程中有檔案需要加到VFS中. 修改AbpStudyWebModule
的ConfigureVirtualFileSystem
方法, 在開始的方法加入以下程式碼:
// 新增WebModule的檔案到VFS
Configure<virtualfilesystemoptions>(options =>
{
options.FileSets.AddEmbedded<abpstudywebmodule>(typeof(AbpStudyWebModule).Namespace);
});
AddEmbedded
方法會將泛型型別所在的程式集中的嵌入資源(Embedded Resources)加入到VFS中. 一般來講我們需要在檔案的"屬性"視窗將 "生成操作" 設定為 "嵌入式資源". 但是對於我們新增的Razor Page, VFS預設就可以處理不需要額外的設定. 另外我們傳遞給了AddEmbedded
一個名稱空間引數, VFS會將該名稱空間從檔案的全路徑中忽略, 剩下的路徑如果一樣, 則後新增的檔案就會覆蓋之前新增的.
OK, 執行工程讓我們看看效果:
我們在"個人資訊"中將admin的名字設定為"WAKU", 然後重新登入後右上角就會顯示名字了.
再來一點魔法
現在我們不要關閉應用程式,保持它在執行狀態, 然後回到我們新增的Default.cshtml
檔案, 將剛才修改程式碼再新增一點裝飾:
<i class="fa fa-smile-o">@((await UserManager.GetByIdAsync(CurrentUser.GetId())).Name) </i>
我們使用複用fontawesome在名字前面增加了一個笑臉☺圖示, 儲存修改, 回到瀏覽器按F5:
可以看到在未重新編譯的情況下,我們的修改已經生效了! 很神奇吧?
這是因為為了方便開發, VFS設定了在開發階段使用磁碟上的物理檔案(Razor, js, css等), 所以只要我們只要儲存, 不用重新編譯重新整理一下頁面就會載入最新的檔案, 這會大大提升我們的開發效率! 而在釋出後, 則會使用編譯後的程式集中的檔案以提高執行效率.
結語
好了,到此為止我們已經完成了我們的目標------在選單欄上顯示使用者的名字而不是使用者名稱. 雖然從改動上來看只有很小的工作量, 但在這背後是有很多值得學習的東西, ABP框架已經為我們做了很多!通過本文希望你能感受到ABP框架的強大,也希望ABP v1.0能早日釋出!
示例工程放到GITHUB中了.
Happy Coding!
參考文章:
- Designing Modularity on ASP.NET Core: Virtual File System
- 基於ASP.NET Core的模組化設計: 虛擬檔案系統(上一篇文章的中文版, 謝謝@liangshiwei的翻譯)