Pages

Showing posts with label MVC. Show all posts
Showing posts with label MVC. Show all posts

2016-05-25

MVC Razor迴圈分組顯示

在MVC Views (*.cshtml)裏要將一個資料集合作loop迴圈分組顯示,一般正規的Razor程式寫法如下圖:

Rzaor Regular Grouping

應用在Table裏,它就可以輸出下圖行列的分組效果。

Razor Regular Output

但是一個View裏可能會存在多個群組顯示,若每個區塊都放上述的Razor源碼,不僅容易變數衝突,也缺乏程式ReUse的精神,所以我們可以利用C# Action Delegate把需要客制化的部分抽取出來,下圖函式內部裏的StringBuilder可以省略掉,以適應更多的變化:

Action Method

日後在Razor View裏,就可以輕易輸出Grouping HTML自訂字串了。
Razor Custom Grouping

MVC最主要精神就是不要在View裏寫複雜的邏輯程式判斷,應該要將這些分組寫法放到Model去,再包一層Method來簡化呈現參數,例如只提供群組數量就好。

2016-05-18

ASP.NET MVC的執行亂碼訊息

在使用VS2015開發ASP.NET MVC5 Web Application時,若要一步步偵錯當然是執行Debug模式,但它的執行速度比較慢,而且進入點不好控制。所以若很複雜的偵錯,我通常直接使用Release模式(Ctrl+F5)來測跑結果,有錯誤訊息再修改就好。畢竟程序寫久有經驗了,通常只是打錯字而己。

我的習慣是修改後,直接在View的頁面(*.cshtml)視窗按滑鼠右鍵,選擇「View in Browser」來作執行測試:

View in Browser

當cs源碼裏執行有錯誤時,卻發現它出現是亂碼,即使在Web.config設定<customErrors>也無法正常顯示錯誤訊息。偶然一次機會裏,在執行jQuery AJAX存取某頁面View時,我發現在js裏可以讀出正常編碼。

因此我安裝Chrome Postman這個套件,使用GET方式貼上測試頁面的網址(下圖編號2),即可產生正確的錯誤訊息。從此,這樣的方式就是我慣用的MVC專案除錯模式了。

Chrome Postman

在ASP.NET 4.6.1的MVC5 「Web Application」裏,每當異動了cs程式碼,均需重新Build Project,沒有「Website」專案自動編譯的方便功能,可惜MVC5並不完整支援Website專案。值得慶幸的是,WebApp正佈網站時,日後的cs異動只需要直接覆蓋主要的DLL即可,不需要像Website須重新Publish,算是功過相抵能接受。

2015-11-25

MVC聯絡表單Design Pattern

以下是一個MVC前端表單的設計模式,雖是我是第1次寫MVC,但有隱約把握到MVC的分層精神,自己的心得體會給大家參考看看。

Form Submit

ASP.NET MVC5裏前端View裏,那些@Html.XXXFor(),ValidateFor()這類的標籤輸助函式我都儘量不用,因為它不是標準的HTML,還得依賴Server端的解讀。雖然它能簡化產生html碼,但其轉譯代價明顯不合算。View提供的功能應該是協助前端HTML,JS而存在,而不是去取代或扭曲它,不足之處就靠前端JS框架來補足即可。事實上證明,下一版的MVC6提出Tag Helper,它的方式比較適合一些。上面表單驗證我使用jQuery Validation來取代MVC提供的Model Validation的前端作法,但保持其後端的ModelState驗證檢查。

Controller Action的表單接受方式為下圖,其精神就是儘量把商業邏輯寫入Model裏, Controller只寫「很簡單」的頁面請求服務判斷。這也是為何MVVM(Model-View-ViewModel)模式會被提出的理由,因為HTML的JS AJAX已經明顯選擇好了服務URL,Controller已不像字面上的「控制者」角色,精確來說它只是一個請求轉貼者(Forwarder),重點應在Service Model如何處理請求及讀寫DB (with Repository Model),最後產生ViewModel帶入View中顯示而己。

Action Code

既然MVC的Controller是虛職角色,真正處理請求邏輯的Model目錄,就得依其功能分類成主要三類:「Repository, Service, ViewModel」。你可以理解各種水果(DbTable)有它們削皮處理的方式,那麼Respository就是處理單一水果讀取的角色,而把它們拼成不同的水果盤,就是Service角色,包括各種水果再切片搭配或舖盤美化。最後完整的水果盤被端出,就是所謂的ViewModel。

Model Category

很多人會關心MVC裏,SQL命令該怎麼執行?是繼續寫串接式的SQL字串,還是該用Entity化的EF LINQ查詢?若有過ORM的開發經驗,你會很清楚EF的定位是啥,我很認同某人說過「別糾結EF查詢最終轉成什麼SQL法,EF本來對於複雜查詢本來就不是它的目的」。儘管如此,很多人還是會在EF技術群裏,糾結詢問複雜的DB查詢,LINQ該怎麼寫?產生的SQL差異效能如何?我提供一個比較簡單的比喻,傳統SQL寫法就像刀子,而EF是槍,我們要完成的DB動作目的就是要殺生。槍雖然威力強,但子彈成本貴(LINQ轉成SQL),假如要殺一隻老鼠,應該用刀子簡單省錢,因為開槍也是讓子彈像刀子一樣快速射入目標體內,剝奪生命而己。然而,槍畢竟不是刀,刀子除了殺生還能削片處理細節,槍就很難辦到了(LINQ複雜JOIN語法)。

簡言之,當複雜SQL報表查詢,你應該用SQL來寫,若覺得字串相加串條件的寫法很討厭,我這兒提供一個SQL範本式Pattern,能解決SQL動態條件字串問題。以我的作法而言,會先考量查詢效能及管理維護成本,再建立一個Service Model類別來管理DB操作函式,依目的選擇EF或SQL,或兩者併用,只要有統一類別管理它們,它們就能和平共處,共造雙贏局面。

 Model Code

至於,EF Data Model的POCO Class產生方式,我建議使用「CodeFirst from existing database」的工具方式來產生POCO,雖然它缺乏像*.edmx的UI管理工具,但其在連線字串、欄位微調會比EDMX精簡很多。雖然至目前我仍以DB First為主的開發方式,但Code First的優點卻是立即採用(聽說EF7也沒有EDMX了)!

2015-11-19

MVC5 ResolveUrl in static code

ASP.NET MVC5常用Url.Content(virtualPath)來取得實際的URL,若是在static程式區塊裏,要取得頁面實際路徑的簡易方式為System.Web.VirtualPathUtility.ToAbsolute(virtualPath),然而它無法處理http://路徑(會丟出例外),因此要額外處理它:

public static string ResolveUrl(string virtualPath)
{
if (virtualPath == null)
return null;

// VirtualPathUtility can't handle the http://xxx path.
if (virtualPath.IndexOf("://") != -1)
return virtualPath;

// Resolve the ~/ tilde.
if (virtualPath.StartsWith("~"))
return System.Web.VirtualPathUtility.ToAbsolute(virtualPath);

return virtualPath;
}

2015-10-22

MVC的分頁及分組顯示

昔日WebForm有ListView控件,可以輕易分頁及分組顯示,到了MVC沒有Server控件就得自力而為。找到幾個被推薦的分頁UI控件,不過該選擇哪一項,得確認它能滿足以下的需求:

  1. 該分頁控件能持續被維護。
  2. 產生的分頁數字顯示能修改CSS樣式,配合前端網頁風格。
  3. 分頁的顯示方式、文字可以輕易調整修改。

最後選出下面的項目候選:

以MVC的精神,EasyUI分頁是最好的方式,簡單又有提供豐富JS控制函式,但其缺點就是Prev/Next等是用圖示顯示,要修改也不容易(EasyUI雖然開源,但js被minifier且混淆過)。

EasyUI Pager Style

Telerik Kendo UI最符合商業持續被維護的原則且也很美觀,但它的分頁CSS及行為控制,就比較難客製化,而且又得學習其Template Hash語法,後端AJAX綁定也是自己的物件方式,雖然都不用寫啥程式,但受制於人。

Kendo Pager Style

MvcPaging是老牌的分頁控件,不過分頁樣式有點少,要改文字須自己實作Output輸出,有點Dirty。最後覺得X.PagedList的分頁有提供屬性設定,這會比較適合簡易客製化,尤其它的顯示文字及CSS表都容易調整。

PagedList Pager Style

XPagedList Properties

具體教學及樣式,請看這篇教學文章:
mrkt 的程式學習筆記: ASP.NET MVC 資料分頁 - 使用 PagedList.Mvc
http://kevintsengtw.blogspot.tw/2013/10/aspnet-mvc-pagedlistmvc_17.html

站在客戶角度,其實對分頁顯示樣式不是很要求,只要配色能搭配整體即可。其實分頁功能自己寫也行,只是我覺得不用重複造車,遇到客戶特別要求再來研究不遲。因此我個人是建議使用EasyUI分頁即可,其次是X.PagedList。

Server端分頁控件的使用,大抵上就是調整好樣式屬性,最後輸出分頁數字,再綁定JS Click事件以AJAX取出後端的PartialView(依頁碼取出該頁資料,並透過(StaticPagedList<T>()顯示分頁),並更新分頁資料的顯示及分頁狀態。簡易分頁條件用AJAX GET方式即可,複雜的分頁+搜尋條件就用POST+JSON方式。

最後,分頁資料要分組顯示(Group),即一列顯示幾個Item的意思,例如下面圖片中的Table為4欄為一列。

Group List

使用Razor語法就是使用foreach+%餘數判斷式,即可達到分組顯示功能。

Group Razor