2014年8月17日 星期日

ASP.NET MVC - 下拉選單的日期選擇器 Part.6 - @helper ?

前面有用了三篇在說明將下拉選單日期選擇器建立為 Editor Templates,在 ASP.NET MVC 的開發時可以有很大的彈性,不過呢…… 我卻是很少看到有人在專案裡使用,尤其是獨自學習或是在短時間囫圇吞棗般的硬學 ASP.NET MVC 的朋友。有些朋友對於 ASP.NET MVC 的學習態度是很嚴謹,但也有一些朋友會認為學習 ASP.NET MVC 不需要多久的時間,甚至有人還說出只需要兩小時的說法,學習態度嚴謹的朋友在學習上就會追根究柢、鉅細靡遺,而沒有花時間、下功夫學習的人,就只會看到 ASP.NET MVC 的皮毛而已。

而 @helper (razor helper)是個相當方便的功能,可以提供很多靈活與彈性的操作,但是好用的功能也應該用在適當的情境與場合,但如果是將這個下拉選單日期選擇器改用 razor helper 的方式來建立與使用呢?

 


有使用 razor helper 的朋友應該都會知道,當建立的 razor helper 要讓專案裡的所有檢視頁面來使用的話,那麼就要在 ASP.NET MVC 網站專案下建立「App_Code」目錄,然後建立一個檢視頁面檔案(*.cshtml)再把 razor helper 放到新建的檢視頁面裡。詳細的操作說明可以詳閱「ScottGu's Blog - ASP.NET MVC 3 and the @helper syntax within Razor」。

我是在 App_Code 目錄下另外建立 share 子目錄,然後再去新增 input.cshtml 檔案,

image

在 input.cshtml 裡面是將下拉選單日期選擇器以另外一種方式建立,如下:

image

不過這只是 razor helper 在 input.cshtml 的部分,還有些部分尚未完成。

 

_Layout.cshtml

在 _Layout.cshtml 的 head 部分加入 javascript 程式,先建立一個 Array,然後新增一個 function,這個 function 是用來讓之後有需要在頁面準備好之後就執行的前端程式給加入到前面所建立的「window.WaitExecutes」陣列。

image

在 _Layout.cshtml 的最後,當頁面已經 render 完成之後,就要去執行放在「window.WaitExecutes」的程式,

image

 

使用

在檢視頁面上的使用就無關模型類別,也無關 Html Helper,就是將那種「include」的觀念以及就像在程式裡去使用 method 的方式一樣,

image

執行結果

image

image

 

如果我想要改變下拉選單的設定內容,應該要怎麼做呢?

有幾種方式可以解決,例如增加 razor helper 的方法參數,或是再增加不同的 razor helper,都是可行的作法,

 
@helper DatePicker(string elementId, string value)
{
    DateTime dt = new DateTime();
    bool isDate = DateTime.TryParse(value, out dt);
 
    var dateValue = isDate
        ? dt.ToString("yyyy/MM/dd")
        : string.Empty;
    
    <input type="text" id="@(elementId)" value="@(dateValue)" />
 
    <;script type="text/javascript">
        window.AddWaitExecutes(function () {
            $('#@(elementId)').dateDropDowns({
                dateFormat: 'yy/MM/DD',
                monthNames: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
                yearStart: '1914', yearEnd: '2014',
                yearOption: 'Year', monthOption: 'Month', dayOption: 'Day'
            });
        });
    <;/script>
}
 
@helper TaiwanCalendarDatePicker(string elementId, string value)
{
    DateTime dt = new DateTime();
    bool isDate = DateTime.TryParse(value, out dt);
 
    var dateValue = isDate
        ? dt.ToString("yyyy/MM/dd")
        : string.Empty;
        <input type="text" id="@(elementId)" value="@(dateValue)" />
 
        <;script type="text/javascript">
            window.AddWaitExecutes(function () {
                $('#@(elementId)').dateDropDowns({
                    dateFormat: 'yy/MM/DD',
                    monthNames: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
                    yearStart: '1914', yearEnd: '2014',
                    taiwanCalendarYear: true,
                    yearOption: '年', monthOption: '月', dayOption: '日'
                });
            });
        <;/script>
}
image

image

 

看到這裡,或許大家會覺得用 razor helper 的方式來完成下拉選單日期選擇器的實作也是一個可行的方法,在建立以及設定還有使用上都不是太複雜,甚至於有些地方還比之前的 Editor Templates 稍微簡單,也不需要考慮太多。

但是我必須說,我相當反對這樣的實作方式。

 

執行後的頁面原始碼裡 HTML 與 Javascript 交錯

我們應該要讓頁面更為簡潔,將 Javascript 程式給獨立出去,而不是在原始碼裡面攪和成義大利麵。而且相同的 javascript 程式碼一再地重複出現,當你將頁面上多表單的輸入項目都用 razor helper 的方式來實作,那麼你就會發現頁面檔案大小會很大,用越多這樣方式來做你的網頁,網頁只會越來越臃腫。

 

難以維護

就如上一點說過的,當你將網站裡的表單輸入項目都用 razor helper 的方式來實作,然後又全部擠在幾個 cshtml 裡,這時候你要在眾多的方法要找到要修改的目標時就會是一件困難的事情。而且當你在 razor helper 裡的某一行 javascript code 有錯誤的地方,甚至於破壞了規則(例如 javascript code 與 razor syntax 交錯,又沒有做好符號處理時),這個時候你既使在 Visual Studio 有裝了 ReShaper,「回到定義」這功能就是會被破壞而無法使用。

另外給大家看一個狀況,

image

這是在一個 razor helper 裡去使用了另一個 razor helper,有可能在另一個 razor helper 用了「DateRequired」這個 razor helper,這樣層層疊疊的關係搞得越來越複雜的時候,再加上 Razor Syntax, HTML, Javascript Code 交錯在裡面,當某一個共同使用到的 razor helper 發生問題或是被更改過,那麼就會產生連鎖反應的錯誤,而到時候光是要找出問題點以及受到影響的範圍時,你這時候心裡只會想把這麼搞的人給敲個稀巴爛。

 

使用 Model Binding 要多花功夫

以這篇文章的例子來說,剛好我所使用的 dateDropDowns 是會需要用到一個 TextBox 輸入框,所以只要 TextBox 的 Name 與模型類別的屬性名稱有一致,那麼 Model 資料就會做好繫結,無論是在前端頁面或是後端的 Action 方法。

但如果今天這個下拉選單日期選擇器就只有三個下拉選單的呈現時,我在頁面上呈現 Model 資料時就要另外做處理,甚至於到了後端的 Action 方法,我就無法透過 Model 來取得日期資料,而必須要另外透過 FormCollection 去找出這三個下拉選單的所選項目,然後再去判定是否有無選擇資料,再來判斷所選的日期資料是否正確等。

 


@helper 在適當的地方有其好用與靈活而且彈性的用法,但是大量將網站裡的表單輸入項目或是各種的顯示內容都用 @helper 來做,我就覺得這樣的方式相當不好,只是錯用了 @helper 所帶來的好處,並且也完全忽略了 ASP.NET MVC 裡的 Display Templates 與 Editor Templates,更重要的是完全沒有使用到 ASP.NET MVC 的 Model Binding 所帶來的好處與便利。

正確且適當地使用 @helper,而不是錯用。

 

講到這邊其實還有一個地方還沒有講到,那就是資料驗證的部分,這部分會比較複雜一些,所以就看下一篇的說明。

 

系列文章:

ASP.NET MVC - 下拉選單的日期選擇器 Part.1

ASP.NET MVC - 下拉選單的日期選擇器 Part.2

ASP.NET MVC - 下拉選單的日期選擇器 Part.3 - Editor Templates

ASP.NET MVC - 下拉選單的日期選擇器 Part.4 - Editor Templates

ASP.NET MVC - 下拉選單的日期選擇器 Part.5 - Editor Templates

ASP.NET MVC - 下拉選單的日期選擇器 Part.6 - @helper ?

ASP.NET MVC - 下拉選單的日期選擇器 part.7 - Validation

 

以上

沒有留言:

張貼留言

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。