問題和需求
從2004年上線,ZLDNN.COM運行已經超過16年了,一直使用DotNetNuke平台(現在叫DNN Platform),從最初的DotNetNuke 2.1到現在使用的7.4。先是在亦庄的獨立服務器托管,后來遷到美國的PowerDNN的雲服務器ECS,再后來遷移到阿里雲的ECS,采用Windows 2008系統,運行幾年以后,C盤已經滿了,可又沒有辦法清理,網站速度越來越慢,干脆長痛不如短痛,徹底更新一下。
DotNetNuke嚴重依賴Web Form技術,其開發團隊到現在也沒有找到從.Net Framework遷移到.Net Core以及最新的.Net 5或.Net 6的合適技術路線,導致其只能在Windows下運行。另外一個問題是DotNetNuke只能使用SqlServer數據庫,無法使用更便宜更靈活的數據庫。網站的遷移實際上是在滿足現有基本功能的前提下,采用新的技術重新開發。在選擇新的技術之前,首先需要梳理一下網站的功能,確定哪些需要保留,哪些可以通過其它方式替代,哪些可以暫時不實現。網站需要保留的部分包括:
- 數據:包括用戶數據、訂單數據、技術支持數據等。
- 網站頁面的Url: 大部分Url已經是SEO友好,但有些頁面仍然采用web form模式,比如GetLicense.aspx,這部分Url也需要保留。
- 關鍵功能:諸如訂單接收、產品激活等。
其它的需求還有,希望網站可以運行在維護成本比較低的輕量級應用服務器中,可以采用MySql等開源數據庫,視覺效果上盡量與原有系統相同等等。還要留有用戶管理已經用戶注冊的接口。
在大的技術路線上,仍然采用.Net體系,研究了幾種技術,包括Qutane、Orchard等,最后決定采用Abp vNext進行開發。
開發
將開發中遇到的具體問題和最終的解決方案總結一下。
外觀
采用ABP自帶的Theme,根據現有網站的風格進行修改,保持風格大體一致。修改的辦法是從Abp源碼中復制Theme相關文件到自定義項目對應的目錄中,直接修改就可以了。需要修改的文件如下圖:
網站的顏色等需要修改文件global-styles.css:
首頁
DotNetNuke完全采用動態頁面,原來的首頁采用的是HTML模塊加上DNNArticle的子模塊,考慮到首頁的更新頻率不高,這次采用靜態頁面。
維護頁面
這部分主要是產品、版本、訂單等等的維護,屬於標准的CRUD界面。這部分采用ABP的標准化設計,首先設計各個實體,然后使用AbpHelper.Gui和AbpHelper.CLI生成相關代碼和界面。所生成的界面基本可以使用,需要改造的地方是增加查詢功能和調整權限。這里簡單介紹一下如何增加查詢功能。
ABP MVC/Razor Page 模板生成的基於DataTables.Net的頁面支持分頁和排序,但缺省情況下不支持查詢,需要根據實際情況自行添加。我們可以利用DataTables.Net自帶的查詢功能實現查詢。
首先修改Application項目,增加帶有查詢的Application服務。先在PagedAndSortedResultRequestDto基礎上定義帶有關鍵字的Dto:
public class OrderNotificationSearchDto: PagedAndSortedResultRequestDto
{
public string Key { get; set; }
}
然后在Application 服務中增加查詢服務:
public async Task<PagedResultDto<OrderNotificationDto>> GetSearchListAsync(OrderNotificationSearchDto input)
{
var query = await CreateFilteredQueryAsync(input);
if (!string.IsNullOrEmpty(input.Key))
{
query = query.Where(o => o.InvoiceID.Contains(input.Key)
|| o.OptionName.Contains(input.Key)
|| o.PackageName.Contains(input.Key)
|| o.BillToEmail.Contains(input.Key));
}
var totalCount = await AsyncExecuter.CountAsync(query);
query = ApplySorting(query, input);
query = ApplyPaging(query, input);
var entities = await AsyncExecuter.ToListAsync(query);
var entityDtos = await MapToGetListOutputDtosAsync(entities);
return new PagedResultDto<OrderNotificationDto>(
totalCount,
entityDtos
);
}
然后需要改造客戶端,首先將index.js中datatables的設置searching改為true:
var dataTable = $('#OrderNotificationTable').DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
searching: true,
接下來修改ajax的定義:
//ajax: abp.libs.datatables.createAjax(service.getList),
ajax: abp.libs.datatables.createAjax(service.getSearchList, inputAction, responseCallback),
將getList修改為新的getSearchList,增加新的傳入參數和Callback。這兩個函數定義如下:
var inputAction = function (requestData, dataTableSettings) {
var ctl = $("#OrderNotificationTable_filter input").val();
return {
key: ctl,
};
};
var responseCallback = function (result) {
// your custom code.
return {
recordsTotal: result.totalCount,
recordsFiltered: result.totalCount,
data: result.items
};
};
網站數據的導入
這部分主要包括產品數據和與激活相關的數據,采用自己寫的一個面向.Net Core的ADO庫,將原有的數據導出到Xml中,在新的應用中從Xml中讀取數據進行初始化。
產品內容頁
產品的內容原來保持在數據庫中,現在改為在文件中保存,加載產品頁時,從文件讀出展示。
外部數據交換
主要包括接收從DNNStore發來的數據和產品激活兩部分。采用Application Service實現,通過Apb框架的動態Web Api可以訪問。
Url重定位
包括與外界交換數據的Url和為了保證SEO一致的界面Url。采用.Net Core的ReWrite中間件實現,感覺這部分真的很好用。代碼如下:
var options = new RewriteOptions()
.AddRewrite(@"^GetLicense.aspx", "Products/Services/ManualActivate",true)
.AddRewrite(@"^Products/currentpage/(\d+)", "Products?currentpage=$1", true)
.AddRewrite(@"^ProductDetail/(.+)", "Products/ViewDetail?name=$1", true)
.AddRewrite(@"^LicenseCode.aspx", "api/app/activate/req-license-code", true)
.AddRewrite(@"^desktopmodules/OrderNotification/OrderNotify.aspx", "api/app/activate/save-order", true)
app.UseRewriter(options);
還有其它一些細節包括關閉多租戶、關閉用戶注冊、國際化修改等等。
從十一前開始,斷斷續續開發了兩到三周的時間。
部署和運行
以前一直在Windows生態中,部署應用似乎不是大問題,只有在IIS上創建網站或者應用就可以了。現在希望將ZLDNN.COM遷移到阿里雲的輕量級服務器,在Linux系統下部署,還是遇到一些挑戰。
首先解決.Net Core應用在Linux上運行的問題。由於在生產環境中只運行一個.Net Core應用,所以在生成部署文件時采用獨立運行模式,這樣就不需要在生產環境中安裝.Net框架。這一步沒有遇到大問題,測試應用能夠運行。
然后是ABP應用在生產環境上運行,這里遇到一個問題,Couldn’t find a valid ICU package installed on the system.這個問題在本地測試沒有遇到,查了一下是沒有安裝ICU庫,安裝完成后問題解決了。
數據庫的配置沒有遇到太大麻煩,但在后期運行時出現了MySql異常退出的問題,發現是內存問題,創建內存交換文件后解決了。
Apache服務器配置花了一些時間,因為兩個域名駐留在同一個服務器上,需要將Apache服務器配置為反向代理服務器,由於對Apache服務器不熟悉,折騰了一些時間,不過最后也成功了。
到現在新網站運行了兩個多月,基本沒有遇到太大的問題。效果還是不錯的,速度提升很多。