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的翻譯)