網站遷移紀實:從Web Form 到 Asp.Net Core (Abp vNext 自定義開發)

尋找無名的特質發表於2021-12-30

問題和需求

從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伺服器不熟悉,折騰了一些時間,不過最後也成功了。

到現在新網站執行了兩個多月,基本沒有遇到太大的問題。效果還是不錯的,速度提升很多。

相關文章