發表文章

目前顯示的是 12月, 2014的文章

在錯誤中學習ASP.NET MVC 第 30 篇 - 認識View - DisplayTemplates與EditorTemplates補充

圖片
  今天是最後一天囉!把之前說好要講的東西補一下XD,在講完Model之後,應該對於整個MVC架構比較有概念了,接下來我們就可以好好利用所謂的Template,也就是View的其中一種,關於View的類型介紹可以參考 Day15 Day15 ,廢話不多說,直接看Code! 在專案的Shared資料夾下加入DisplayTemplates與EditorTemplates資料夾,切記不要打錯字 DisplayTemplates 顧名思義就是要與@Html.Display或@Html.DisplayFor來使用,一般就是拿來做資料呈現。 如果今天想要將註冊日期(資料庫存DateTime資料類型)改用民國年的方式顯示,要怎麼透過DisplayTemplates來實做呢?在還沒講Templates之前,是不是都在透過後端程式做日期的轉換,然後再透過View作呈現,雖然可以透過共用方法來處理這件事,但如果今天客戶過了幾年後反悔,想改回西元年來顯示怎麼辦?啊不就是改共用的處理時間的方法就好了啊!是有多難啊XD 那如果今天客戶除了想要改回西元年並且要以紅色的字加粗體顯示,那要怎麼辦?喔不... 真的要挫賽了,可能就要打開有顯示日期的View一支一支慢慢改...,若運氣好一點就是當初套板時設計師就已經有建立一個給日期顯示的css了,所以只要去修改css內容就好,不過哪裡找心思這麼細膩的設計師XD。對面這種用的次數很多但程式碼不複雜卻很零散的顯示資料的功能,就很適合使用 DisplayTemplates 建立DisplayTemplates下的檢視,取名為TaiwanDate.cshtml,並將@model宣告成DateTime,然後透過TaiwanCalendar做日期的轉換,第7~9行將值顯示 在User/Details.cshtml內加入程式碼,第17行是使用預設的內建樣板來呈現日期資料,第25行則選擇自己定義的樣板名稱,就完成設定囉!是不是非常方便呢,不管以後客戶對日期有什麼疑難雜症,統一改這個Template就可以了 另外也可搭配套用UIHint屬性來使用,在Models/UserPartial.cs下將Create_Date套用TaiwanDate樣板 再次瀏覽User/Details會發現,步驟2的第17行明明沒有指定Temaplte卻也顯示TaiwanDate樣版的內容

在錯誤中學習ASP.NET MVC 第 29 篇 - 認識Model - ModelState

圖片
  當驗證失敗時,上一次在表單內輸入的值還是會存在,不是在說廢話嗎,就都Model Binding了,值當然會在XD 觀察UserController內的Create Action當使用者送出表單後,我們可以看到已經綁定到User這個物件上了 並且可以透過ModelState.IsValid來判斷是驗證成功,如果新增成功就導回清單頁,否則就顯示原頁面,透過中斷點來觀察ModelState的資料,發現裡面也會保存表單的輸入資訊 如果今天想在使用者輸入非A開頭的帳號時,直接幫他加上A_這個字串讓他可以直接新增的話要怎麼做呢,例如下圖,讓使用者輸入Bob按下Create按鈕時,停留在原畫面並將Bob改為A_Bob 這功能還不簡單嘛!阿不就驗證失敗的時候加工一下Name的值就好了 很抱歉!改了竟然沒用!!!不是應該顯示A_Bob嗎?此時你就算檢查一百萬遍確定你真的有重新設定user.Name的值也沒用,用中斷點看一千萬次也一樣,明明就已經改成A_Bob了,但顯示的時候還是很固執的顯示Bob 當初我遇到這個問題時都沒辦法解決,問人也問不出所以然,直到幾個月過去之後,同事竟然找到解法了!使用ModelState.Clear(),當時也沒想太多!用就對了XD 喔耶!終於可以正常顯示了!但是我的錯誤訊息勒?一樣被Clear清掉了XD 所以必須自己手動加回去,提示使用者可以自行修改或是使用程式自動產生的A_直接新增 再次瀏覽User/Create,完美! 好像還沒講到重點,寫程式當然不能只是不明究理的亂用,我們應該是探討究竟是什麼原因引起這種鬼打牆的狀況,明明Model Binding的值就已經透過程式修改了,但是到顯示的時候卻又顯示被程式修改前的狀態,其中原因當然跟ModelState脫不了關係,好!要來公布解答了! 答案就是ModelState的值有最高的顯示優先權,而透過ModelState.Clear()將值清空之後,自然就不會使用ModelState的值顯示了,改以第二順位的Action指定的Model值來做顯示 其實這情況不常遇到,不過除了我別人也有遇到過,所以我想這應該也算是個值得一提的觀念吧XD 下載今日專案: https://github.com/juben-wang/MvcApplication29

在錯誤中學習ASP.NET MVC 第 28 篇 - 認識Model - LINQ to Entities 與 導覽屬性

圖片
  眼看就要進入尾聲了,今天就來講如何從資料庫撈資料吧!使用的語言就是Language-Integrated Query (LINQ),LINQ除了可以針對entity查詢之外,也可以針對object或xml來查詢,今天就直接針對 LINQ to Entities 來做說明,最後再補充 導覽屬性 的應用 LINQ to Entities LINQ to Entities 的查詢提供兩種語法: 以方法為基礎的查詢語法( Lambda 運算式 ) 查詢運算式語法(看起來類似SQL語法) 1.以方法為基礎的查詢語法 使用Scaffold產生的程式碼,預設都是使用『 以方法為基礎的查詢語法 』方式來做CURD,直接看Code: 必須先建立DbContext才能以物件的方式查詢entity,如下圖的UserEntities1繼承DbContext Create(新增User),使用Add()方法 Update(修改User),使用Entry()方法並搭配db.SaveChanges()方法 Read(讀取User),使用Find()方法 Delete(刪除User),使用Remove()方法並搭配db.SaveChanges()方法 而在昨天改寫Scaffold產生的程式碼以符合顯示多筆Email資訊的功能,也有使用到Where()方法,其中的d => d.UserID == id就是 Lambda 運算式 在之前View裡面使用html helper時搭配For結果的方法也時常使用到Lambda 運算式,使用方式如下: 自訂義參數名稱 => 自訂義參數名稱.物件屬性 另外還有很多時常用到的方法,例如:Select()、OrderBy()、Take()與Skip()等等,在初學的時候其實都是邊開發專案邊查詢,相關的使用範例可以看這個網站 101 LINQ Samples 再來看另外一種 2.查詢運算式語法 將昨天透過方法取得資料庫資料的程式碼改寫成「查詢運算式語法」,如下圖39行,跟SQL很類似都是搭配from、where或select這些關鍵字來組成查詢語法,這邊我自己剛開始學習時非常難適應,因為我DB那塊就是弱到爆炸,所以反而很喜歡透過方法查詢的方式,可以透過方法或以物件導向的觀念直接跟DbContext溝通,不過在特殊情況「查詢運算式語法」真的超級好用,例如

在錯誤中學習ASP.NET MVC 第 27 篇 - 認識Model - ViewModel

圖片
  ViewModel就是給View用的Model,什麼?ViewModel就是給View用的Model(又重複一次XD),在之前我們講的Model都是透過EF產生出來的實體類別,而在使用Scaffold產生的程式碼與檢視時,我們就已經選定Model了,詳細可參考 Day22 但如果頁面同時想要顯示兩種實體類別的資料要怎麼辦,一個View只能搭配一個Model來使用阿!為了解決這個問題 ViewModel 就產生了,ViewModel就是專門給View呈現資料用了,除此之外它沒有任何作用。 接續前幾天的專案,我們來看一下,在新增完使用者與多筆Email之後,想在Details頁面同時顯示User資料以及Email資料要怎麼做 原始的Details執行畫面如下 原始的Details Action 程式碼如下,可以知道抓到User這筆之資料之後,直接透過return View將user類別的資料傳入,若不了解Controller是如何傳值給View可以參考 這篇 原始的Details檢視畫面如下,因為要接收由Action傳過來的資料,所以在第一行要使用@model宣告與Action同類別的Model 今天目標:顯示使用者的Email資訊,如下圖 我們先來看一下如果不透過ViewModel要怎麼做 使用ViewBag或ViewData 將Email的值撈出來,這邊撈資料的寫法先忽略,明天會講從資料庫撈值的方式 在View裡面搭配@foreach將值撈出來,不過這邊需要特別注意,因為這邊不是強型別,所以當然沒有自動提示可以用,必須非常小心字有沒有打錯,如果不小心打錯也只能等到執行時期也會發現,除非是傳一些很不重要的字串,不然我平常其實也不太喜歡使用ViewBag與ViewData 使用ViewModel 建立ViewModel,取名為UserDetailViewModel.cs,這邊除了原本顯示的User資料外,還需要多定義一個可以顯示多筆Email的屬性,型別是List 2.在Action內建立型別為UserDetailViewModel 的model,並將model.User與model.EmailList的值設定好,最後傳給View 3.在檢視這邊也要改成同名的UserDetailViewModel ,就在此時,Email就有強型別可以用了!有錯字也會馬上提示,不過比

在錯誤中學習ASP.NET MVC 第 26 篇 - 認識Model - Model Binding

圖片
  之前說明過 Controller如何傳值給View ,今天要來探討怎麼從View將資料傳回至Controller, 在MVC 裡有個Model Binding的功能,中文稱為模型綁定,就是在處裡如何從View傳值給Controller這件事,DefaultModelBinder可以將從url的參數值對應到Action的參數中,或是將值轉換成物件型態。 過去我自己寫php時,透過GET或POST傳遞的資料,都是要透過$_GET["id"]或是$_POST["id"]的方式取值,沒有什麼物件的概念,但在ASP.NET MVC中,幾乎都是透過Model Binding來處理參數,這樣做有一個好處就是資料就是強型別,而且就有自動提示可以用了! 接續昨天的範例,來觀察Model Binding是如何運作的 url參數值應對Action參數 瀏覽User/並在清單頁點選一筆資料觀看詳細資訊,在網址上面可以看到User/Details/1 網址最後面的1其實就是透過get傳遞的id值,比較好理解的寫法應該是這樣User/Details?id=1,但為什麼url的顯示卻面成User/Details/1了呢,有認真看我文章的人應該知道為什麼吧(自言自語中),之前在講 透過url存取Controller 的時候有稍微提過路由設定,網址的結構都是透過路由去定義的,來複習一下App_Start資料夾下的RouteConfig,cs,下圖黃框的地方就是url的定義囉 在講回來Model Binding,在UserContorller的Details Action內設定一個中斷點,可以直接在程式碼最前面,也就是下圖右邊紅色圈圈的位置,按一下就可以產生或取消中斷點,那麼在專案偵錯的狀態下,透過滑鼠移到變數上面就能看到目前的執行狀態,例如我們可以看到在Details宣告的id已經被綁定了,有沒有很神奇,就不用像php那樣還要自己打$_GET["id"]的方式去取值 使用FormCollection 除了透過參數綁定的方式,也有提供透過FormCollection來綁定,使用上類似PHP取值的方式,就是透過["KeyName"]來操作,例如下圖,我們可以得到此表單所有的KeyName清單,如果想要知道值的內容,可以使