作者序
筆
者目前任職於多奇數位創意有限公司擔任技術總監一職,負責公司技術
方向的決策。大約在兩年多前,我開始注意到
ASP.NET MVC
技術在國
外漸漸發展起來,起初不覺得有什麼特別的地方,但慢慢看到一些國外討論
的開發觀念與設計樣式,好像真的能夠解決當時
A S P. N E T We b F o r m
開發上
的困難點,例如,內建的控制項不好用、控制項套版不易、抽象的
A S P. N E T
We b F o r m
事件模型經常讓新進開發人員搞不清楚狀況、過大的
Vi e w S t a t e
等
等,這些都是我們日常開發工作會遇到的問題。
直到
2 0 0 9
年 初 ,
A S P. N E T M V C 1 . 0
正 式版 上市 ,除了 還 在 建 置與 維 護 中的
A S P. N E T We b F o r m
專案不會改動之外,我毅然決然的帶領公司所有開發人
員轉向
ASP.NET MVC
的懷抱,並宣告未來所有新專案皆以
ASP.NET MVC
技
術為主,這是一個重大的決定,也是一個至今從未後悔的決定。對我來說,
學習一門全新的技術時「動機」很重要,而且當你接觸一門新技術必須要放
棄許多以往的開發經驗時,如果沒有明確的動機與察覺轉變的價值,很難讓
人改變,因此,要進入一個全新技術的領域,首要目的就是先感受技術的價
值,然後再進一步深入研究技術的細節。
本書歷時一年多的時間,而且在這段期間,
ASP.NET MVC
版本也從
ASP.NET
MVC 1.0
升級到
ASP.NET MVC 2.0
,由於
ASP.NET MVC
的觀念與架構十分
優秀與嚴謹,因此,技術升級的過程非常順利,而且開發觀念不需要重新建
立。對開發人員來說,即使升級至
2.0
在學習上也沒什麼太大負擔,即便未來
的
ASP.NET MVC 3.0
,微軟的
ASP.NET MVC
開發團隊也保證會與
ASP.NET
MVC 1.0
相容,早期寫的程式完全可以順利移轉上去,新版的
ASP.NET MVC
只會繼續在同一套架構上增強功能與強化
Visual Studio 2010
工具的支援,因
此,筆者認為
ASP.NET MVC
未來非常具有發展性。
曾 經想 過 我 們 公 司會 不會 是台 灣唯 一 一個 只用
A S P. N E T M V C
技 術 開發 網 站
ASP.NET MVC2開發實戰
xi
ASP.NET MVC
非常強調「關注點分離」的概念,而且從開發架構上來看就很
容易讓開發人員做到「關注點分離」,這個優勢是
A S P. N E T We b F o r m
完全
無法匹敵的。
本 書 集 結 了 我 在 學 習 與 開 發
A S P. N E T M V C
的 經 驗 與 心 得 , 希 望 能 帶 給 所
有
. N E T
開發人員一個全新且優秀的選擇,讓我們一起擁抱
A S P. N E T M V C
的
世界吧!
能夠順利出版這本書要感謝的人很多。首先,最感謝的是我的
ASP.NET MVC
開發團隊,在公司裡,他們寫的
C o d e
比我寫的字還多出很多很多,本書有很
多 開 發 技 巧 與 學 習 心 得 都 來 自 於 他 們 。 除 此 之 外 , 像 是
D e m o
、
T h o m s e n
、
Danny
、
Bibby
協助撰寫了部分章節的內容,以及星寂、
Jerry
幫我完成了許多
範例程式,還要感謝其他人幫我校稿與練習範例程式,如果沒有他們協助這
本書恐怕很難完成。
同時也非常感謝悅知文化的編輯
Vicky
,在我撰寫的過程中提供許多協助與包
容,因為我從來就 沒有按照規定的「寫作說明」在撰寫文章,即便要出書,
還是覺得用寫部落格的心情與角度比較符合我的風格。
這是我的第一本書,如果讀者對書籍的內容或觀念有任何不理解的地方,歡
迎到我的部落格、
粉絲專頁或在噗浪(
Plurk
)上與我交流互動。
導讀
在
開始學習
ASP.NET MVC
之前,我想許多讀者心中應該都有許多疑惑,尤其
是正宗的
ASP.NET Web Form
開發者更是對
ASP.NET MVC
技術給予異樣的眼
光,甚至是誤解。本書主要分成三篇,將以循序漸進的方式帶領各位揭開
ASP.NET
MVC
的神秘面紗,導引各位建立正確的觀念以及實際體驗
ASP.NET MVC
的強大魅
力。
TIP 建議章節閱讀順序
• 1 → 2 → 3 :想按部就班學習ASP.NET MVC的人
• 1 → 3 → 2 :想先感覺程式,再建立觀念的人
• 3 → 1 → 2 :給懶得閱讀文字,只想看程式碼的人
第一篇:基礎觀念篇
第
1
章:在學習
ASP.NET MVC
之前
本章將介紹
ASP.NET MVC
的基礎知識,幫助你瞭解
ASP.NET MVC
的輪廓。由於著
重於觀念,如果覺得看不懂,可先直接跳過,待後續的章節讀完之後再回頭閱讀,
或許更能幫助你建立正確的觀念。
第
2
章:建立正確的開發觀念
主要說明使用
ASP.NET MVC
進行網站開發時應有的正確觀念。強大的工具若沒有
正確的觀念支持,就像是給你一台馬力強又省油的手排車,而你不知道離合器如何
使用是一樣的,也許你試了一段時間後,覺得車子還是開不快時就提前放棄了一部
好車。本章最後也整理了初學者對
ASP.NET MVC
經常會問的問題,並逐一進行回
答。
第
3
章:新手上路初體驗
將介紹如何利用
Visual Studio 2010
開始一個
ASP.NET MVC
專案,讓讀者親身體驗
ASP.NET MVC
在進行實務開發時的完整過程,相信在逐步教學的帶領之下,能讓
現有的
ASP.NET Web Form
開發人員瞭解與
ASP.NET MVC
開發差異,進而快速上
ASP.NET MVC2開發實戰
xiii
第二篇:技術講解篇
第
4
章:
Routing
與
ASP.NET MVC
生命週期
想要掌握
ASP.NET MVC
,最重要的是瞭解網址路由
(Routing)
與執行生命週期的
重要觀念。網址路由在
ASP.NET MVC
有兩個目的,第一個是比對透過瀏覽器傳來
的
HTTP
要求,並對應到適當的
Controller
與
Action
進行處理;另一個目的則是決定
ASP.NET MVC
應該輸出什麼樣的網址回應給瀏覽器。雖然跳過本章仍然可以成功
建置
ASP.NET MVC
網站,但瞭解它能幫助你理解
ASP.NET MVC
執行時的先後順
序,進而減少犯錯的機會。
第
5
章:
Model
建立資料模型
在
ASP.NET MVC
開發的過程中,通常
Model (
模型
)
是整個專案首要開發的部分,
所有需要資料存取的地方都需仰賴
Model
提供服務。本章將學習如何透過
Visual
Studio 2010
自動建立資料模型與手動建立檢視資料模型,並透過部分類別的擴充達
到基本的欄位驗證,甚至完成商業邏輯驗證,最後透過實作倉儲樣式
(Repository
Pattern)
,讓
ASP.NET MVC
專案更容易進行單元測試與測試驅動開發
(Test-Driven
Development
;
TDD)
。
第
6
章:剖析
Controller
相關技術
ASP.NET MVC
的核心就是
Controller (
控制器
)
,負責處理瀏覽器來的所有要求,並
決定回應的內容,但
Controller
並不負責應如何顯示內容,僅回應特定型態的內容給
ASP.NET MVC
框架,而
View
才是決定回應內容的重要角色。本章也會應用到第
2
章
所提及的「關注點分離」、「以習慣取代配置」、「不要重複你自己」等觀念,讓
你邁入
ASP.NET MVC
的殿堂,發現
ASP.NET MVC
的核心之美。
第
7
章:
View
資料呈現相關技術
View
負責資料的呈現,所有呈現資料的邏輯都會由
View
來控管。不過,
View
開發
應該是整個
ASP.NET MVC
專案最花時間的,因為與顯示邏輯相關的技術五花八
門,包括
HTML
、
CSS
、
JavaScript
、
DOM
、
jQuery
、
JSON
、
AJAX
、
Silverlight
等,
當然不止這些,也不需要全部學會,因在不同的顯示情境下將會用到不同的技術。
本章將會說明如何達到「關注點分離」的目的,讓你的
ASP.NET MVC
網站更容易
第
8
章:
Area
區域相關技術
將介紹如何利用
ASP.NET MVC 2.0
新增的
Area (
區域
)
機制,協助你架構較為大型的
專案,讓獨立性高的功能獨立成一個
ASP.NET MVC
子網站,以降低網站與網站之
間的耦合性,也可以透過
Area
的切割,讓多人同時開發同個專案時,減少互相衝突
的機會。
第三篇:開發實戰篇
第
9
章:
MvcGuestbook
進階實戰
本章將透過第二篇所習得的知識加以強化第
3
章的留言板程式,雖然案例極為簡單
但內容與開發技巧卻涵蓋
ASP.NET MVC
許多精華之處,相信在融會貫通之後,即
可有效運用於其他更複雜的專案上。
第
10
章:
ASP.NET MVC
開發技巧
本章將整理一些在實務上經常使用的開發技巧,包括:多國語言支援、隱藏
HTTP
標頭版本編號、如何在
ASP.NET MVC
與
ASP.NET Web Form
之間傳遞資料、
ASP.NET MVC
偵錯技巧,以及程式碼產生器入門。雖然善用工具能有效提升開發
效率,但還是要記得擁有正確的觀念與紮實的技巧才是開發效率提升的不二法門。
第
11
章:安裝部署
以往在部署網站時,都有許多手動的步驟需介入,對於許多不大熟悉
IIS/SQL
的新
手來說,部署網站變成一件困難的事。
Visual Studio 2010
提升了
ASP.NET
網站部署
的能力,透過
Microsoft Web Deployment Tool (MSDeploy)
簡化了許多繁複的流程。
此外,還整理了幾個部署
ASP.NET MVC
的常見問題,當遇到問題時可供讀者參
考。
第
12
章:單元測試
ASP.NET MVC
的一大特色在於有比
ASP.NET Web Form
更好的可測試性,本章將
Chapter 03
本章將介紹如何利用
Visual Studio 2010
開始一個
ASP.NET MVC
專案,並瞭解
ASP.NET MVC
專案有哪些基本的目錄架構與需要注意的事項。
03-01
認識
Visual Studio 2010
開發工具
要能發揮
ASP.NET MVC
開發架構的強大威力,絕對不能小看開發工具的重要性,
因此,熟悉
Visual Studio 2010
開發環境將對於未來開發
ASP.NET MVC
專案有著舉
足輕重的影響,以下將簡短介紹幾個常用的功能與視窗。
3-1-1
方案總管窗格
❙
所有專案項目與程式檔案都統一會在方案總管
(Solution Explorer)
進行統一管理,
包括:專案屬性設定、檔案屬性設定、加入參考、檔案管理等。
3-1:
3-1-2
伺服器總管窗格
❙
所有與伺服器相關的資訊都可以統一在伺服器總管
(Server Explorer)
管理,例
如:
SQL Server
資料庫管理、
Oracle
資料庫管理、電腦管理等,本書之後的範例也
CHAPTER 03 新手上路初體驗 33
01
02
03
04
05
03-01
認
識V
isu
a
l St
u
d
io
2
0
1
0
開
發
工
具
06
3-2:
3-1-3
工具箱窗格
❙
在
ASP.NET MVC
的世界裡,幾乎很少有機會用到工具箱
(Toolbox)
的項目,因為
所有伺服器控制項大多派不上用場。不過,當在開發
ASP.NET MVC
與
ASP.NET
Web Form
混合的網站時,還是挺有用的。
另外,工具箱還能拿來當作基本的程式碼片段
(Code Snippet)
書籤之用,你可以
將常用的程式碼片段選取後,拖曳至該區域即可儲存。
3-4: 程式碼
3-1-4
輸出窗格
❙
在建置專案時如果發生任何異常,你可以開啟輸出
(Output)
窗格查看詳細的錯誤
訊息,除此之外,在開發應用程式時也可以多加利用
System.Diagnostics
命名空間
將除錯訊息輸出到此視窗,以利分析網站運作過程不易發現的細節。
3-5: 看
3-1-5
錯誤清單窗格
❙
錯誤清單
(Error List)
視窗會顯示三種不同程度的訊息:
CHAPTER 03 新手上路初體驗 35
01
02
03
04
05
03-01
認
識V
isu
a
l St
u
d
io
2
0
1
0
開
發
工
具
06
:
顯示該專案程式碼中包含的一些警告資訊,建議開發人員應該要養
成習慣閱讀這些訊息。
資
:
提供一些參考用的資訊,通常不會對專案造成什麼影響。
3-6:
3-1-6
擴充管理員
❙
Visual Studio 2010
提供了一個非常方便的擴充管理員
(Extension Manager)
工具,
讓你隨時可以下載成千上百的
Visual Studio
擴充外掛,安裝適當的擴充外掛對日常
的開發工作幫助非常大。
3-1-7
程式碼片段管理員
❙
經常在開發程式的人一定不會忘記這個好用的工具,
Visual Studio 2010
提供程式
碼片段管理員
(Code Snippets Manager)
,方便管理
Visual Studio 2010
中所有的程式
碼片段。
3-8:程式碼
03-02
建立第一個
ASP.NET MVC
專案
接下來,我們會用一個非常簡單的留言板程式概要說明
ASP.NET MVC
網站的開發
過程,讓首次接觸
ASP.NET MVC
的開發人員能對
ASP.NET MVC
開發有個大致的
輪廓,此專案將不會說明過多與資料庫存取相關的技術,若有需要的讀者建議參
考其他書籍。
本章的核心在於體驗
ASP.NET MVC
開發過程,若遇到看不懂的詞彙或技術,建議
CHAPTER 03 新手上路初體驗 37
01
02
03
04
05
03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
3-2-1
利用
ASP.NET MVC 2
專案範本建立專案
❙
Step
01
:
開啟
Visual Studio 2008
或
Visual Studio 2010
,選取「檔案」→「專
案」。
3-9:
Step
02
:
選取「
Web
」→「
ASP.NET MVC 2 Web
應用程式」。
TIP
Visual Studio 2008 ASP.NET MVC 2 ASP.NET MVC 2 for
VS2008 ASP.NET MVC 2 RTM :
http://go.microsoft.com/fwlink/?LinkID=157074
Step
03
:
新增專案時會先詢問你是否要建立「單元測試專案」,此時我們先選
「否」,待後續的章節會再進一步說明。
3-11:建立 ,
Step
04
:
執行「偵錯」→「開始偵錯」(或按下【
F5
】功能鍵)執行網站,即
可啟動一個預設的
ASP.NET MVC
網站。
CHAPTER 03 新手上路初體驗 39
01
02
03
04
05
03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
此網站具有非常基本的功能,包括兩頁簡單的頁面與會員機制,這些頁
面都有套用
MasterPage
、有使用
ASP.NET
內建的
Membership
功能,可以
進行會員註冊、登入、登出等。
3-13:建立 的ASP.NET MVC
TIP
的ASP.NET 的App_Data 建立ASPNETDB.MDF aspnetdb_
log.ldf
Step
05
:
在
ASP.NET MVC
專案新增完成後,會自動建立幾個標準的目錄結構,
: CSS
ASP.NET MVC
ASP.NET MVC Models 的程式 碼, :EDMX, DBML,
JavaScript, VBScript
ASP.NET MVC
HomeController 的
的 ,
MasterPage UserControls
(Routing)
3-14: 建立的
TIP
2 的 習 , ,
若要以顯示在瀏覽器的網址來比較
ASP.NET MVC
與
ASP.NET Web Form
的差別,
請參考表
3-1
所列的
ASP.NET Web Form
與
ASP.NET MVC
之間在找程式碼位置時的
CHAPTER 03 新手上路初體驗 41 01 02 03 04 05 03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06 技術
ASP.NET Web Form http://localhost/
/Index.aspx /Index.aspx.cs
ASP.NET MVC http://localhost/
/Controller/HomeController.cs /Views/Home/Index.aspx
ASP.NET Web Form http://localhost/ About.aspx
/About.aspx( ) /About.aspx.cs(程式碼)
ASP.NET MVC http://localhost/
Home/About
/Controller/HomeController.cs (程式碼)
/Views/Home/About.aspx( )
3-1:ASP.NET Web Form ASP.NET MVC 程式
對於
ASP.NET Web Form
來說,「網址路徑」等同於「檔案路徑」,此網址路徑與
檔案的對應相當直覺,一般人應該對此不會感到困惑才對。
但
ASP.NET MVC
若要透過「網址路徑」來要找檔案就必須配合
ASP.NET MVC
的
結構來找尋檔案,但事實上,
ASP.NET MVC
的「網址路徑」與「檔案路徑」對應
關係是透過「網址路由
(Routing)
」來定義的,我們可以從專案內的
Global.asax.cs
檔案看到一個
RegisterRoutes
方法定義如下:
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute(
"Default", // "{controller}/{action}/{id}", // URL new { // controller = "Home",
action = "Index",
id = UrlParameter.Optional }
MVC
3-15:
這裡定義兩個預設的網址路由
(Routing)
:
IgnoreRoute
設定
*.axd
等格式的網址路徑不要透過
ASP.NET MVC
執行。
例如:
ASP.NET
內建的
Trace.axd
或其他預設的
HttpHandler
都不要透過
ASP.NET MVC
處理。
MapRoute
透過
MapRoute
方法是定義
ASP.NET MVC
網址路由最主要的方式。
每一個路由定義了三個參數:
1.
路由名稱。
2.
設定網址路徑如何對應到控制器、動作與路由值。
3.
控制器、動作,以及其他路由值
(RouteValue)
的預設值。
若以這個預設的
MapRoute
可以得知,在瀏覽器輸入
http://localhost/Home/About
時,透過
Routing
的對應之下,由於
路
的部分為
Home/About
,所以會對應
CHAPTER 03 新手上路初體驗 43 01 02 03 04 05 03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
到這個控制器內的
About
公開方法
(Public Method)
,這個公開方法就是
MVC
的動
作
(Action)
,也是實際執行網頁主要程式的入口點。
當瀏覽器輸入
http://localhost/
想要取得首頁時,透過
Routing
的對應之下,由於網
址路徑的部分沒有任何內容,所以會使用
MapRoute
的第三個參數所設定的預設
值來替代,因此,網站首頁的網址就會先進入
Controllers
目錄找到
Home
這個控制
器,然後再找到
Index
這個公開方法,進一步執行
ASP.NET MVC
所有過程。
TIP
Routing , { } , 就
, 的就 {controller} {action} ,
,就 , ASP.NET MVC
ASP.NET MVC , 給System.Web.Mvc.MvcHandler ,
再 給DefaultControllerFactory 建立 (Controller) , 的
(Action), 的 , 的 (Action)
我們先來看一下預設的
HomeController
的內容:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MvcApplication1.Controllers { [HandleError]
public class HomeController : Controller {
public ActionResult Index() {
ViewData["Message"] = " ASP.NET MVC!"; return View();
}
public ActionResult About() {
return View(); }
控制器
(Controller)
類別在開發的時候必須符合以下規範:
類別名稱一定要有
Controller
結尾。例如:
GuestbookController
就代表
Guestbook
控制器。
類別繼承於
Controller
基底類別(或實作
IController
介面的類別)。
類別中須包含數個回傳值為
ActionResult
的公開方法,這些方法在
ASP.NET
MVC
中稱為動作
(Action)
。
在預設首頁
Index
動作中,第一行的
ViewData
是一個
Dictionary
物件,可以在檢視
(View)
中讀取被設定的資料。
ViewData["Message"] = " ASP.NET MVC!";
第二行的
View()
事實上是來自於
Controller
基底類別的一個輔助方法
(Helper
Method)
,它會回傳一個
ViewResult
物件,
ViewResult
是繼承自
ActionResult
類別,
主要用途是告知
ASP.NET MVC
框架我要回應一個檢視
(View)
,而該檢視就來自於
ASP.NET MVC
框架所設定的「預設路徑」。以
Home
控制器與此
Index
動作為例,
透過
View()
輔助方法就會去告知
ASP.NET MVC
框架:「我要顯示
Views\Home\
Index.aspx
這張網頁的執行結果」。
接著,利用
Visual Studio
的功能新增切換至該動作的檢視,先將游標移至動作方法
的定義處,然後按下滑鼠右鍵,選取「移至檢視」。
CHAPTER 03 新手上路初體驗 45
01
02
03
04
05
03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
從該檢視的網頁內容可以發現,頁面中都有套用
~/Views/Shared/Site.Master
這個
MasterPage
,還有
<asp:Content>
控制項等,這些都與我們之前開發
ASP.NET Web
Form
時的技術一模一樣,甚至於還可以使用
UserControl (
使用者控制項
)
等,
不過,其他內建的控制項因為架構不同的關係就不建議在檢視中使用了,在
ASP.NET MVC
中,會使用
HTML Helper
的方式協助我們顯示較為複雜的網頁。
3-17:ASP.NET MVC 2 Web 程式 的
在上一頁,我們有看到
ViewData["Message"]
被設定了一個字串內容,到了此檢視
(View)
就可以透過以下語法將資料讀出,並顯示於網頁內容中。
<%: ViewData["Message"] %>
TIP
的 <%: ViewData["Message"] %> ASP.NET 4.0 的 , 的 ,
3-2-2
建立資料模型
❙
Step
01
:
在「方案總管」視窗中點選
Models
目錄,按下滑鼠右鍵,並點選「加
入」→「新增項目」。
3-18:
Step
02
:
選取「資料」→「
ADO.NET
實體資料模型」。
CHAPTER 03 新手上路初體驗 47
01
02
03
04
05
03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
Step
03
:
在實體資料模型精靈視窗中,選取「從資料庫產生」,再按「下一步」。
3-20:
Step
04
:
新增連接,並連至
MvcGuestbook
資料庫(該資料庫可從本書範例找到)。
Step
05
:
接著選擇資料庫物件,請勾選「資料表」。
3-22:
Step
06
:
此時就會建立完成我們
ASP.NET MVC
專案所需的資料模型
(Model)
,可
CHAPTER 03 新手上路初體驗 49
01
02
03
04
05
03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06 TIP
ASP.NET MVC的 (Model) , 的 式 ,
:ADO.NET LINQ to SQL NHibernate Entity Framework , 的 Models
只 , 的 習 的程式
Models , 的 , ,
Models 立的
3-2-3
建立控制器與動作
❙
Step
01
:
在「方案總管」視窗中點選
Controllers
目錄,按下滑鼠右鍵,並點選
「加入」→「控制器」。
3-24: Controllers ,
Step
02
:
請 輸 入 控 制 器 名
稱為「
Guestbook-Controller
」,如圖
3 - 2 5
所示,然後按
下「加入」按鈕。
Step
03
:
此時,透過
Visual Studio 2010
會建立一個新的
Controller
類別檔,名為
GuestbookController.cs
,此類別會預設新增一個名為
Index
的動作。
using System;
using System.Collections.Generic; using System.Linq;
using System.Web; using System.Web.Mvc;
namespace MvcApplication1.Controllers {
public class GuestbookController : Controller {
//
// GET: /Guestbook/
public ActionResult Index() {
return View(); }
} }
這一頁我預計用來顯示所有留言,但此動作我們留到後續的小節再進一步說明。
3-2-4
建立檢視
❙
接著,利用
Visual Studio
的功能新增預設檢視
(View)
,將游標移至方法定義處,然
後按下滑鼠右鍵,並選取「加入檢視」。
CHAPTER 03 新手上路初體驗 51
01
02
03
04
05
03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
在預設的情況下,檢視名稱不太需要修改,且此名稱預設會與動作方法的名稱一
致,我們直接點選「加入」建立該檢視:
3-27: Index, 的
在「方案總管」中會看到
Views
目錄下自動建立了
Guestbook
目錄,以及新增一個
Index.aspx
檔案,此檔案就是該動作
(Action)
的檢視
(View)
,所有畫面的顯示資料
與基本的邏輯都會寫在這裡。
TIP
程式 , 的 , 部 的
, 的 , ASP 的
Views 建立
Controller 的
建立 (Action)
的 (View)
3-28:Views 建立Guestbook , Index.aspx
開啟
Views\Guestbook\Index.aspx
,我們先修改網頁標題與加上一個「留下足跡」
的連結,剩下的內容稍後再寫。
<%@ Page Title="" Language="C#"
MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> </asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> </h2>
<a href="/Guestbook/Write"> </a> <hr />
CHAPTER 03 新手上路初體驗 53
01
02
03
04
05
03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
此時按下【
F5
】或【
Ctrl+F5
】,在瀏覽器輸入以下網址即可預覽此檢視的輸出網
頁:
http://localhost:52514/Guestbook
3-29:按 F5 的
TIP
的 部 只 Guestbook , {controller} Guestbook,
{action} , 的Index,ASP.NET MVC就 先 Controllers
Guestbook ( 就 GuestbookController.cs 的GuestbookController
), 再 的Index (public method), View(), 就
的ViewResult , ,ASP.NET MVC 得Views\Guestbook\Index.aspx
, 給
3-2-5
在檢視中建立表單
❙
建立「留下足跡」的表單,必須先到
GuestbookController
新增一個新的
Write
動作
(Action)
如下:
public ActionResult Write() {
再新增一個
Write
檢視,讓使用者能夠輸入一些資料,輸入欄位的地方可利用
ASP.NET MVC
內建的
Html
輔助方法來產生欄位,顯示標題的地方可用
Html.Label
方法,顯示文字方塊欄位的地方則用
Html.TextBox
方法,其第一個參數要輸入欄
位名稱,表單內容如下:
<form method="post" action="/Guestbook/Save">
<%=Html.Label(" ")%> <%=Html.TextBox(" ")%> <br />
<%=Html.Label("Email")%> <%=Html.TextBox("Email")%> <br />
<%=Html.Label(" ")%> <%=Html. TextArea(" ")%> <br />
<input type="submit" /> </form>
以上程式最後輸出的
HTML
如下:
<form action="/Guestbook/Save" method="post"><label for=" "> </label> <input name=" " type="text" value="" />
<br />
<label for="Email">Email</label>
<input id="Email" name="Email" type="text" value="" /> <br />
<label for=" "> </label>
<textarea cols="20" name=" " rows="2"></textarea> <br />
CHAPTER 03 新手上路初體驗 55 01 02 03 04 05 03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
在 上 述
< f o r m >
會 看 到 在
a c t i o n
屬 性 中 的 路 徑 目 前 是 寫 死 的 , 也 就 是
/Guestbook/Save
這個
URL
,意思是這個表單在送出資料時,會將表單資料發送
到
Guestbook
控制器的
Save
動作,但將網址寫死在檢視裡不是件好事,因為在
ASP.NET MVC
之中,網址路徑是可以透過
Global.asax.cs
中的
Routing
自訂與隨時修
改的,如果哪天你修改
Routing
後,還要連帶修改數十個檢視中的表單發送路徑,
那就不那麼聰明了!
在
ASP.NET MVC
可以利用
Html.BeginForm
輔助方法達成自動輸出表單標籤,語法
如下:
<% using (Html.BeginForm("Save", "Guestbook", FormMethod.Post)) { %>
<% } %>
或是省略第三個參數,因為表單預設的
FormMethod
就是
Post
:
<% using (Html.BeginForm("Save", "Guestbook")) { %>
<% } %>
NOTE
的 (Action), :
<% using (Html.BeginForm()) { %> <% } %>
因為送出表單的對象與目前的檢視所在的控制器
(Controller)
相同,只是動作
(Action)
不同,你可以運用以下技巧,透過檢視
(View)
的
RouteData.Values
物件取
得當下的所有路由值
(RouteValue)
,並動態載入路由值中的
Controller
的名稱,如
下語法:
<% using (Html.BeginForm("Save", RouteData.Values["controller"].ToString())) { %>
NOTE
ASP.NET MVC的 (RouteValue) 的 , 的
ASP.NET MVC 2只 建的, controller action area, area 只
Area , 的 , :id 的
Global.asax.cs 的RegisterRoutes
3-2-6
從動作接收表單資料
❙
從上述得知表單資料會發送給
Guestbook
控制器中的
Save
動作,而且表單中會有三
個欄位一起被送出,分別是:
姓名
內容
此時,我們必須回到
Guestbook
控制器新增一個
Save
動作,但請注意動作
(Action)
必須為公開方法。
TIP
的 ,再 :
回到
Guestbook
控制器之後,你可以利用
Visual Studio 2010
插入程式碼片段的功能
CHAPTER 03 新手上路初體驗 57
01
02
03
04
05
03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
3-31: ASP.NET MVC 2的程式碼
完成之後程式碼如下:
[HttpPost]
public ActionResult Save(string , string Email, string ) {
ViewData[" "] = ; ViewData["Email"] = Email; ViewData[" "] = ; return View();
}
從
Save
方法所傳入的參數來看,此
Save
方法傳入了三個參數,其參數名稱與
在
Index
檢視中所使用的表單欄位名稱一模一樣。你可能會想問,為什麼透過
QueryString
或
Form
傳來的資料會變成
Save
方法的參數呢?在
ASP.NET MVC
有個
機制稱為資料模型繫結
(Model Binder)
,透過這個機制會自動將用戶端傳來的資
料轉換成
.NET
的型別,也因為這樣,你才能直接在透過
Save
方法的參數取得相關
資料,非常的方便。
NOTE
<input id="Email" name="Email" type="text" value="" /> 的 name
Save
動作的三個參數欄位型態都是
string
型別,代表傳入的資料是字串型態,如果
你的表單是讓使用者輸入「數字」的話,也可以將參數的型別改成
int
型別,雖
ASP.NET MVC
也會自動幫你轉型成
int
型別,讓你在
Save
動作中用精準的型別開發
程式,但如果使用者輸入「非數值」的資料,就會導致無法將資料轉換為
int
的
例外發生,這點就必須做好前端的欄位格式驗證。
另外值得一提的是,在
Save
方法的上方套用了一個
[HttpPost]
屬性,這個屬性
告知
ASP.NET MVC
此動作
(Action)
只會接受
HTTP POST
過來的資料,這個屬
性又有另一個專有名稱稱為
(Action Filter)
或稱為
(Action
Selector)
。
我們先不將資料寫入資料庫,看看由
Save
動作是否正常接收到由
Index
檢視中的表
單傳送過來資料,依照上一小節的說明再新增一個
Save
檢視,用來顯示傳入的資
料,檢視的內容如下:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> </asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> </h2>
<hr />
<br />
<%: ViewData[" "] %> <br /><br />
Email<br />
<%: ViewData["Email"] %>
<br /><br /> <br />
<%= Html.Encode(ViewData[" "].ToString()).Replace("\r\n", "<br/>\r\n") %> </asp:Content>
這時按下【
F5
】或【
Ctrl+F5
】並在瀏覽器輸入以下網址,並輸入留言的訊息:
CHAPTER 03 新手上路初體驗 59
01
02
03
04
05
03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
3-32:
按下「送出查詢」後即可發現資料確實傳遞成功,且資料也正常顯示在頁面上。
3-33:
確認表單資料的確能透過
Action
來接收之後,再將資料寫入資料庫,我們之前有
透過
Entity Framework
建立一個資料模型,就透過該模型來將資料寫入資料庫,因
此,將
Save
動作撰寫完成後的程式碼表列如下:
[HttpPost]
public ActionResult Save(string , string Email, string ) {
db.AddTo (new Models. () {
= , Email = Email, = ,
建立 = DateTime.Now });
db.SaveChanges(); ViewData[" "] = ; ViewData["Email"] = Email; ViewData[" "] = ; return View();
}
3-2-7
實作顯示留言
❙
最後,我們要完成在
Guestbook/Index
尚未完成的「顯示留言」功能,首先修改
Guestbook
類別中的
Index
方法如下,將留言資料從資料庫讀出,並將資料傳給檢
視
(View)
:
Public ActionResult Index() {
Models.MvcGuestbookEntities db = new Models.MvcGuestbookEntities(); var data = db. ;
return View(data); // View()的 就 給View 的model }
NOTE
model的 , String View Name
但為了能夠利用
Visual Studio 2010
幫我們自動建立「強型別」的檢視,我選擇將
CHAPTER 03 新手上路初體驗 61
01
02
03
04
05
03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
3-34:
建立
Entity Framework
建立的
List
3-35: 的
TIP
的 建 , 3-35 的 ,
的Entity Framework LINQ to SQL , 得 先建 (Build) 再
的 , 看得 的
新增完成後,會有完整的表格呈現清單頁面自動被建立完成,在此只有稍微調整
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcApplication1.Models. >>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> </asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2> </h2> <table> <tr> <th> </th> <th> Email </th> <th> </th> <th> 建立 </th> </tr>
<% foreach (var item in Model) { %>
<tr> <td>
<%: item. %> </td>
<td>
<%: item.Email %> </td>
<td>
<%= Html.Encode(item. ).Replace("\r\n", "<br/>\r\n") %> </td>
<td>
<%: String.Format("{0:g}", item.建立 ) %> </td>
</tr>
<% } %> </table> <p>
CHAPTER 03 新手上路初體驗 63
01
02
03
04
05
03-02
建
立
第
一
個ASP
.N
ET
MVC
專
案
06
這個檢視
(View)
有幾個非常重要的地方需要說明。首先是第一行的
Inherits
屬 性 , 原 本 的 型 別 都 是
S y s t e m . We b . M v c . Vi e w P a g e
或
S y s t e m . We b . M v c .
ViewPage<dynamic>
,由於我們這次傳入檢視的是強型別的資料模型,因此,開
發工具幫我們把
System.Web.Mvc.ViewPage
加上「留言板」的型別,我們取得的
是多筆資料,所以預設傳入的型別是
IEnumerable<MvcApplication1.Models.
留言
板
>
。
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcApplication1.Models. >>" %>
第二個重點的部分在於如何在檢視
(View)
中讀取傳入的強型別資料?答案就是:
Model (
ViewData.Model )
。
如下程式片段,
Model
即代表由控制器傳入的資料,而
Visual Studio 2010
開發工具
會因為
<%@ Page
…
%>
的定義,知道
Model
就是
IEnumerable<MvcApplication1.
Models.
留言板
>
型別,因此,可以透過
foreach
依序讀取這些資料一筆一筆的內
容,而每筆都是一個
MvcApplication1.Models.
留言板型別的資料。
<% foreach (var item in Model) { %>
由於
Visual Studio 2010
知道
Model
的型別,因此,在
Visual Studio 2010
中就可以善
用
Intellisense
的威力來進行開發,再也不用特別記憶該型別有哪些欄位可用。如
圖
3-36
:
3-36: 的 Intellisense