轉(zhuǎn)子 http://www.yanjinnan.com/archives/category/tech/efmvc
發(fā)表于 2013 年 8 月 12 日 由 顏晉南
本系類教程將要構(gòu)建ASP.NET MVC 5 Web 應(yīng)用程序,使用的工具是VS2013 ?,F(xiàn)在有預(yù)覽版可以下載了, 點擊下載VS2013 FOR WEB ISO文件 。VS2012 還沒用幾天呢,2013就要出來,據(jù)說數(shù)據(jù)庫有SQL2014的版本了。不帶這么玩的!?。?/p>
Go
安裝完VS2013 for Web 后,打開在起始頁(start page)選擇新建項目。
可以發(fā)現(xiàn)和VS2012最大的不同,WEB里面只有一個選擇,確定后接下來才開始選擇其他的:
VS2012 還有MVC3 MVC4選擇,在VS2013沒得選。好了,創(chuàng)建項目后,我們直接按下F5運行。
好了,一個網(wǎng)站OK了。擁有 首頁、關(guān)于、聯(lián)系方式等頁面。更NB的是注冊登錄也有了。
查看了下網(wǎng)頁源代碼,前端用的是大名鼎鼎的 bootstrap。有時間會專門寫這個系類的文章。
發(fā)表于 2013 年 8 月 13 日 由 顏晉南
什么是MVC?MVC就是 Models 模型,Views 視圖,Controllers 控制器。MVC雖然分為3個部分,但是和三層沒有關(guān)系,是一種用來開發(fā)應(yīng)用程序的模式具有良好的架構(gòu),易于維護和測試。
下面讓我們添加一個控制器類,在資源管理器 項目里面的Controllers 右擊。
接下來去個名字吧,第一個實例一般都喜歡用 helloworld 。
我們把代碼改成如下,直接返回string字符串在瀏覽器窗口。
123456789101112131415161718192021222324 | using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc; namespace MVC5DEMO.Controllers{ public class HelloWorldController : Controller { // // GET: /HelloWorld/ public string Index() { return "這是HelloWorld默認(rèn)的一個動作(action)"; } //GET:/HelloWorld/Welcome/ public string Welcome() { return "這是Welcome的 action 方法"; } }} |
按下F5,在默認(rèn)的網(wǎng)頁地址后面加上Helloworld,如下圖:
一回車,就會看到我們剛才寫的字符串顯示在頁面上。
ASP.NET MVC 會根據(jù)傳入的URL調(diào)用不同的控制器類(上面例子的HelloWorld)以及里面不同的方法(上面例子的Index、Welcome)。具體依據(jù)什么來判斷調(diào)用的是哪個控制器,哪個方法在App_Start/RouteConfig.cs 文件里面設(shè)定。
如果直接訪問域名,會默認(rèn)調(diào)用 defaults里面的 Home控制器下面的Index方法,后面的ID是傳入的參數(shù)等數(shù)據(jù)后面會介紹。
所以剛才我們?yōu)g覽的地址:MVC默認(rèn)的映射來解析的話控制器是 HelloWorld ,調(diào)用的方法是:Welcome 沒有ID這個參數(shù)。接下來我們修改為以下代碼:
12345 | //GET:/HelloWorld/Welcome/ public string Welcome(string name , int age = 18) { return HttpUtility.HtmlEncode( "歡迎"+name+",您的年齡是:"+age) ; } |
給Welcome 方法傳入2個參數(shù),年齡默認(rèn)是18 。接下來我們看看運行結(jié)果。
以前要獲得GET方法傳入的參數(shù),需要寫一句代碼(request),現(xiàn)在MVC自動的幫我們綁定了,多方便!接下來我們把上面的那個代碼中的age改成ID,瀏覽器地址后面添加 /3?name=yan
這次的Welcome后面加上了/3 剛好匹配到了ID,剩下的就匹配到了name這個參數(shù)。按照這個思路,是不是有辦法讓地址欄直接匹配到name,這樣url里面就沒有 ? 這個符號。
我們在App_start\RouteConfig.cs里面添加一個試試:
當(dāng)然,默認(rèn)的路由規(guī)則大多數(shù)情況下是很合適的,不需要去修改。接下來會介紹模型綁定,這樣就不需要修改路由規(guī)則了。
下一步學(xué)習(xí): 添加視圖(View)
發(fā)表于 2013 年 8 月 16 日 由 顏晉南
在上一篇《 ASP.NET MVC5 添加控制器 》里面我們都是直接返回string 字符串或者h(yuǎn)tml 。這樣的話控制器不僅僅做了控制器的工作還做了VIEW(視圖)的工作。通常我們不希望控制器直接返回HTML,因為那樣子復(fù)雜的頁面就會非常繁瑣,所以我們通常會用一個單獨的視圖模板文件來輔助生產(chǎn)對應(yīng)的html響應(yīng)報文返回客戶端。
接下來我們就來看看如何添加視圖,先修改上篇博客的那個例子,我們來修改HelloWorldController類,這樣才能讓view的模板文件來封裝要返回的html響應(yīng)報文。
首先,創(chuàng)建一個視圖文件夾 HelloWorld 。右鍵單擊(view)——》添加——》新建文件夾。
注意名字一定要是 HelloWorld 因為控制器名字是 HelloWorldController 控制器必須是Controller結(jié)尾,視圖文件夾的名字必須和控制器除了結(jié)尾的部分一樣。也就是“約定優(yōu)于配置”的理念。
接下來添加一個支架,選擇 MVC5 視圖—空 不帶模型
點擊添加,彈出的對話框把視圖名字(View name)改為 Index 。其他保持默認(rèn)然后確定。
可以看到多了一個 Index.cshtml的文件。在上面的</h2>后面添加如下的html代碼:
<p>這是一個View模板,來自于:HelloWorld下面的Index視圖!</p>
然后在index.cshtml文件上面右鍵,選擇在頁面檢查器中查看。當(dāng)然也可以按下F5進行運行,在瀏覽器地址欄輸入地址進行查看。
但瀏覽器的地址發(fā)到服務(wù)器的時候,服務(wù)器解析給控制器,然后控制器里面只有一句 return View()語句,指定返回一個視圖模板文件給瀏覽器,我們沒有寫指定什么名字的視圖,默認(rèn)就是Index。
首先,上一個頁面我們需要修改標(biāo)題,顯示我們自己的信息。頁面頂部在一個網(wǎng)站之中的每一頁一般都是一樣的所以我們來修改布局的頁面也叫母版頁。在解決方案資源管理器里面,打開/views/shared 里面的_Layout.cshtml文件。
可以看到,有很多@開頭的內(nèi)容,比如你能在body里面找到 @RenderBody() 這一行。這個什么意思呢?其實說白了就是一個占位符,到時候可以用具體的視圖來填補這個信息。好比剛才那個Index.cshtml就是用來填補這里的。下面我們來修改標(biāo)題,通過這個了解占位符,以及母版頁(布局頁)的作用。
在_Layout.cshtml 的頭部,有個 <title>@ViewBag.Title – My ASP.NET Application</title> 我們修改為<title>@ViewBag.Title – 我的ASP.NET MVC5示例網(wǎng)站</title> 。body 里面的@Html.ActionLink(“Application name”, “Index”, “Home”, null, new { @class = “brand” }) 修改為 @Html.ActionLink(“MVC5示例網(wǎng)站”, “Index”, “Home”, null, new { @class = “brand” })
回到剛才的Index.cshtml ,修改成如下:
我們?nèi)bout頁面也能看到標(biāo)題都變化了。這就是母版頁的作用,我們能夠在布局頁面中修改一次,網(wǎng)站上的所有頁面都顯示新的標(biāo)題。如果看不到效果的話可以CTRL+F5強制刷新看看。
上一篇的博文直接從M(模型)傳HTML回去,這次貌似直接用V(視圖),模型倒是沒怎么用。接下來我們就創(chuàng)建一個數(shù)據(jù)庫,通過M 模型 傳遞給 V 視圖 來顯示相應(yīng)信息。
在我們建立數(shù)據(jù)庫和模型之前,簡單說下數(shù)據(jù)從控制器傳遞到視圖。當(dāng)服務(wù)器接收到瀏覽器一個url的請求,某個控制器的某個方法會來響應(yīng)這次請求。控制器類就是那個我們寫代碼來解析瀏覽器傳入的請求、分析業(yè)務(wù)、從數(shù)據(jù)檢索出數(shù)據(jù)經(jīng)過處理后最終決定返回什么樣的數(shù)據(jù)給瀏覽器。然后視圖VIEW就可以獲得控制器傳入的數(shù)據(jù),進行整理封裝成HTML返回給瀏覽器??刂破魈峁┮晥D返回給瀏覽器需要的數(shù)據(jù)或者對象。所以,最好讓視圖不執(zhí)行業(yè)務(wù)邏輯不與數(shù)據(jù)打交道,需要的數(shù)據(jù)就從控制器拿。這樣才能保證“關(guān)注點分離”(SOC)。
回到我們昨天寫的另外一個方法 Welcome 它需要2個參數(shù),一個是name一個是ID。代碼如下:
ViewBage 是個動態(tài)的對象,意味著我們可以隨時添加需要的屬性。再添加之前ViewBag 并沒有那個屬性。借助于上個博客說的ASP.NET MVC的自動綁定模型,可以直接賦值給剛才動態(tài)創(chuàng)建的屬性 Message 和 tiems。接下來我們按照之前的步驟在添加一個視圖:Welcome 。
代碼如下:
非常的簡單,循環(huán)輸出消息。F5運行在地址欄輸入
當(dāng)我們輸入上面地址欄的那個地址時候,服務(wù)器傳遞給相應(yīng)的控制器處理,控制器獲得參數(shù),把數(shù)據(jù)打包成一個ViewBag對象,并將該對象傳遞給視圖,視圖獲得對象后取到需要的數(shù)據(jù),組織好HTML語句然后返回給客戶的瀏覽器。
接下來的教程,將會介紹使用視圖模型來將數(shù)據(jù)從控制器傳遞到視圖。利用視圖模型的方法會比一般的方法好(強類型)。
下一步: 添加模型 額,M(model)的一種模型,不是數(shù)據(jù)庫的那種 。
發(fā)表于 2013 年 8 月 19 日 由 顏晉南
在本節(jié)中,我們將要添加一些類來管理數(shù)據(jù)庫中的信息。MVC入門系類的文章打算建立一個電影網(wǎng)站的示例。在前幾篇的博客《 Entity Framework學(xué)習(xí)——了解 》,我介紹了新的編程方式 Code First 。所以我們應(yīng)該添加一些類來作為MVC中的“模型”部分。
在解決方案資源管理器中,右鍵單擊 Models 文件夾,選擇添加,然后選擇類:
輸入類名“Movie”。
向類“Movie”添加以下5個屬性:
12345678910111213141516 | using System;using System.Collections.Generic;using System.Linq;using System.Web; namespace MVC5DEMO.Models{ public class Movie { public int ID { get; set; } public string Title { get; set; } public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } }} |
從上面的代碼可以看出,這個就是用類(class)來表示數(shù)據(jù)庫中的電影(電影數(shù)據(jù)信息)。類的每個實例對應(yīng)著數(shù)據(jù)庫中的每行,類的屬性對應(yīng)著數(shù)據(jù)庫中的每列。
在Movie中繼續(xù)添加代碼,我們添加一個 MovieDBContext 類:
可以看出,MovieDBContext 繼承至 DbContext 。我們需要應(yīng)用Entity,可以手動加入以下的using System.Data.Entity;語句或者像上圖那樣,在紅色錯誤處右鍵選擇解析,然后自動添加引用。我們也會發(fā)現(xiàn),有些應(yīng)用我們不需要,按照下圖方式清除未使用的using語句:
12345678910111213141516171819 | using System;using System.Data.Entity; namespace MVC5DEMO.Models{ public class Movie { public int ID { get; set; } public string Title { get; set; } public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } } public class MovieDBContext:DbContext { public DbSet Movies { get; set; } }} |
上面就是最終的代碼,清爽許多。這也是我喜歡.NET 勝過JAVA的原因,有個強大的IDE。非常方便,使用起來容易上手。對于中小企業(yè),快速的開發(fā)出合格產(chǎn)品才是王道!
下一節(jié): 添加數(shù)據(jù)庫連接字符串和LocalDB 。
發(fā)表于 2013 年 8 月 20 日 由 顏晉南
在上一篇博文《 ASP.NET MVC5 入門四——添加模型 》中,我們創(chuàng)建了M模型對應(yīng)的模型類。最終我們還是要在數(shù)據(jù)庫中創(chuàng)建真實的數(shù)據(jù)庫和表,字段等。對于開發(fā)人員,數(shù)據(jù)庫在開發(fā)過程中只是需要一些簡單的功能,為了開發(fā)而安裝一個企業(yè)版的SQL SERVER太浪費了。還好微軟在SQL2012中提供了LocalDB這個新特性,LocalDB也是VS2013默認(rèn)就安裝的。
簡單說就是 SQL免費版的SQL Server Express 的輕量級版本。專門為開發(fā)人員創(chuàng)立的,易于安裝,無需管理,編程語言和T-SQL語言都和正常的數(shù)據(jù)庫一樣。同時不耗費系統(tǒng)支援,沒有服務(wù),需要時自動啟動停止。其他更高級的功能就不說了,夠用,免費,好用才是王道。同時LocalDB數(shù)據(jù)庫也能方便的移植到SQL Server。
默認(rèn)情況下,實體框架會查找和對象同名的上下文里面的連接字符串。在項目的根目錄下面打開Web.config文件:
默認(rèn)的連接字符串:
我們在<connectionStrings>里面添加一個新的連接字符串:
<add name=”MovieDBContext” connectionString=”Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|Movies.mdf;Integrated Security=True” providerName=”System.Data.SqlClient” />
可以看出2個連接字符串都很相似。第一個名字是 DefaultConnection 用來控制可以訪問該應(yīng)用程序的成員資格數(shù)據(jù)庫。我們添加自己的Movie.mdf數(shù)據(jù)庫,不使用成員資格數(shù)據(jù)庫。連接字符串的名字必須和DbContext類的名稱相匹配。
添加好了之后,就是 下一步:從控制器訪問模型中的數(shù)據(jù) 。
發(fā)表于 2013 年 8 月 22 日 由 顏晉南
首先,我們要添加一個新的控制器,在解決方案資源管理器的Controllers文件夾右鍵單擊,添加,支架。
在對話框中,我們選擇下圖這個: MVC5 控制器帶有 讀/寫 和 視圖。
名字就叫做:MoviesController 。model class 選擇 MVC5DEMO.Models里面的 Movie。
數(shù)據(jù)上下文選擇 我們的MovieDBContext。然后點擊ADD。
恩,悲劇了。我們重新修改Models\Movie.cs文件,把Movies 改成Movie。
然后ASP.NET MVC5將會自動創(chuàng)建增刪查改(CRUD)的方法(action)和視圖(views)。是的,一個完整功能的網(wǎng)站就OK了。我們F5運行看看。
當(dāng)然,沒有數(shù)據(jù),因為我們沒有添加任何數(shù)據(jù)。接下來我們點擊 Create New 添加新的電影條目。
我們剛才添加一個新的controller的那個操作,系統(tǒng)自動添加了哪些文件?
顯然,視圖(movies)里面的那些個 cshtml 文件對應(yīng)著增刪改查和首頁等的頁面。我們先來看看 MoviesController.cs里面有什么?
上面的14行,定義了一個私有的電影數(shù)據(jù)上下文,可以用它來進行查詢,編輯,刪除等。
第18行的Index()方法返回的是 數(shù)據(jù)上下文中 所有的電影列表。
前幾篇的博文,我們要返回一些到前臺是用 ViewBag 來封裝一些數(shù)據(jù)。當(dāng)時說了 ViewBag 是動態(tài)對象,你可以隨意添加。我們這次演示的是強類型,除了性能上的優(yōu)點還有如下優(yōu)點:在編寫代碼時候有智能提示;編譯時候也能檢查代碼是否有問題。
在上面代碼25行的 Details 方法,它有個ID的參數(shù)。ID在我們前面也說過:類似于這里面的那個1就是ID。用來表示電影的序號。當(dāng)然也可以用 ?id=1 這樣來表示。如果找到了對應(yīng)id的“電影”(27行的代碼)就返回 視圖(view)同時把movie傳進去也就是返回一個強類型的實例。我們看看對應(yīng)的view(Details.cshtml)里面的代碼:
第一行就是一句 @model 指令。這個指令的作用是告訴視圖模板,這次傳過來的對象是什么類型的,上圖例子就是傳過來一個 models 里面的movie 對象。這樣在details.cshtml里面我們就能通過model.titile拿到movie的標(biāo)題。
我們再來看看index視圖的代碼:
這次的 model 是一個實現(xiàn)了IEnumerable 接口的對象。所以我們可以用foreach遍歷它:
這又是強類型的一個好處,可以用循環(huán)遍歷!
我們在web.config里面添加了一串連接字符串,指定Movies的數(shù)據(jù)庫是LocalDB數(shù)據(jù)庫里面的Movies.mdf。我們可以在資源管理器里面查看如下圖:如果看不見請單擊 顯示所有文件 按鈕:
雙擊 Movies.mdf 文件,會打開 服務(wù)器資源管理器,然后我們展開 表 看看:
能看到就像以前安裝 SQL SERVER一樣操作數(shù)據(jù)庫。
簡單的介紹就到這里,明顯可以看出,開發(fā)工具的進步是越來越振奮人心了!
下一步: 優(yōu)化系統(tǒng)生成的代碼 。
發(fā)表于 2013 年 8 月 23 日 由 顏晉南
本節(jié)中,我們來修改上一篇博文里面系統(tǒng)自動生成的一些代碼,下圖是運行后的截圖:
可以看到有很多不足比如:英文太多,日期格式太長等。
我們回到 Models\Movie.cs 添加幾句代碼:
紅色框起來的就是增加的部分,using 語句里面的那個 DataAnnotations 我們下載在說。Display 屬性指定要顯示的字段的名稱。原來沒有寫的話,就是數(shù)據(jù)庫字段的名稱,現(xiàn)在我們寫上中文了。DataType 指定字段顯示的格式,改為日期這樣的話時間就不會顯示出來,更美觀了。
在上圖左下角,能看到編輯的鏈接。這個鏈接是由 index.cshtml 里面的 Html.ActionLink 方法生成的:
Html是個Help 類,調(diào)用 ActionLink方法來動態(tài)生成HTML超鏈接。ActionLink方法第一個參數(shù)指定顯示的字符串,第二個參數(shù)是 要調(diào)用的Action的名稱,第三個參數(shù)是一個匿名對象。
按照前幾篇講的 /Movies/Edit/3 和 /Movies/Edit?id=3 是等價的。這2個url都是傳遞給Movies的Edit方法來去執(zhí)行,同時給出ID。我們?nèi)タ纯催@個方法:
第一個方法是接受GET請求,第二個是接受HttpPost ??梢钥吹降诙€有個屬性【HttpPost】而第一個沒有,因為默認(rèn)就是GET請求。我們注意到第二個Edit方法前面還有一個【ValidateAntiForgeryToken】這個主要是用來防止跨站請求偽造(CSRF)。這個需要和視圖里面@Html.AntiForgerToken() 配合使用,會生成一個隱藏的防偽標(biāo)記。下次寫個文章介紹一下。
在上面的GET的Edit 方法,調(diào)用實體框架的FIND方法查找時候存在對應(yīng)id的電影,如果存在就返回給視圖,不存在就返回404。下面是視圖里面的代碼:
第一行代碼,綁定了一個強類型對象。然后接下來利用這個對象,生成 <label> <input>等代碼。Html.LabelFor 這個幫助類的方法顯示對應(yīng)的標(biāo)題,Html.EditorFor 用來生成<input>標(biāo)簽,Html.ValidationMessageFor 就是用來進行驗證的。
生成這么優(yōu)美的控件,居然一句代碼都不用寫,真好!
這是表單的源文件,可以看到有個隱藏域,存放著上文的那個 RequestVerificationToken 等信息。從這句話可以看出<form action=”/Movies/Edit/2″ method=”post”>當(dāng)我們點擊save后,表單的所有數(shù)據(jù)都將用post請求發(fā)送到 /movies/edit/2 這個url。
回過頭來看POST請求的EDIT方法:
第一步,判斷表單中的模型所有屬性時候都可以修改或者更新。如果是有效的,就把實體框架狀態(tài)改為修改,然后更新到數(shù)據(jù)庫。保存之后,重定向到Index 這個方法,我們就會看到修改后的效果。
發(fā)表于 2013 年 9 月 10 日 由 顏晉南
接下來我們添加搜索功能,可以根據(jù)電影的標(biāo)題搜索。
在最開始MVC入門說過,MVC一個好處就是關(guān)注點分離。當(dāng)我們需要修改和數(shù)據(jù)有關(guān)的東西,只要去修改Controller 就可以?,F(xiàn)在我們?nèi)バ薷腗oviesController的Index方法:
第一行的LINQ查詢用來選擇Movies。僅僅是定義了movies代表數(shù)據(jù)庫中的哪些,還沒有開始查詢。接下來判斷查詢的字符串是否為空,如果不為空就開始查詢標(biāo)題一樣的電影。
s => s.Title 這是一個Lambda 表達式。一般用在基于方法的LINQ查詢中,比如上面的Where。
我們現(xiàn)在F5運行一下看看,在地址欄后面加上?searchString=中國
當(dāng)然,我們不能讓用戶一直在地址欄加上那么一串來搜索,普遍做法是,在頁面頂部加一個搜索框??吹竭@個就知道需要改動View部分。我們打開Views\Movies\Index.cshtml 文件,在Create New后面加上如下代碼:
可以發(fā)現(xiàn),我們并沒有添加控制器中Index的POST請求,也能正常查詢。我們現(xiàn)在添加HttpPost方法
我們會發(fā)現(xiàn),GET和POST請求的url都是一樣的,都是 localhost:xxx/Movies/Index 。假如我們想要把鏈接發(fā)給朋友,讓他知道我想看哪些電影,但是這些查詢信息卻沒有在url里面體現(xiàn),這樣不肯能發(fā)送給朋友。
解決方法是利用 BeginForm 的重載,有個指定POST請求添加搜索信息到url中。
@using (Html.BeginForm(“Index”,”Movies”,FormMethod.Get))
改成如上的代碼,就可以指定用GET方法提交,哪怕你已經(jīng)有了HttpPost 的方法。
把剛才測試的Index HttpPost 方法刪除,我們接下來添加一個功能,讓用戶可以按照類型來搜索電影。同樣是修改Index的方法。代碼如下:
1234567891011121314151617181920 | public ActionResult Index(string movieGenre,string searchString) { var GenreLst = new List(); var GenreQry = from d in db.Movie orderby d.Genre select d.Genre; GenreLst.AddRange(GenreQry.Distinct()); ViewBag.movieGenre = new SelectList(GenreLst); var movies = from m in db.Movie select m; if (!String.IsNullOrEmpty(searchString)) { movies = movies.Where(s =>; s.Title.Contains(searchString)); } if (!string .IsNullOrEmpty(movieGenre)) { movies = movies.Where(x =>; x.Genre == movieGenre); } return View(movies); } |
第三行的代碼,我們添加了一個List對象來保存從數(shù)據(jù)庫取出的電影類型數(shù)據(jù)。第四行代碼是一個LINQ查詢。第五行代碼我們把獲得查詢結(jié)果存到LIST里面,用了 Distinct 方法,過濾重復(fù)對象。
控制器的代碼搞定后,就是修改View,在添加一個搜索框。
添加的 @Html.DropDownList(“movieGenre”,”All”) 其中的參數(shù) moiveGenre 會去 ViewBag 里面查詢時候存在 IEnumerable<SelectListItem>的參數(shù)。在控制器的代碼中,我們給ViewBag添加了SelectList參數(shù)。
我們運行看看:
可以看出,利用MVC開發(fā)網(wǎng)站是非常的方便,快捷。
下一節(jié),添加新的屬性(字段)到Model(數(shù)據(jù)庫模型)中。
發(fā)表于 2013 年 9 月 17 日 由 顏晉南
在Code First開發(fā)中,不可能一開始創(chuàng)建的數(shù)據(jù)庫類就一直不變可能隨著需求或者其他原因要做調(diào)整。假設(shè)我們在原有的Movies里面添加一個評級屬性。
然后我們運行下看看。
異常了!注釋掉剛才添加的代碼,在運行看看:
發(fā)現(xiàn)可以訪問,這是因為當(dāng)EF CodeFirst的數(shù)據(jù)模型發(fā)生異動時,默認(rèn)會引發(fā)一個 InvalidOperationException異常。有個解決方法是,在Global.asax 里面的Application_Start方法加上 一個 SetInitializer方法,這個方法會讓數(shù)據(jù)庫刪除在重新創(chuàng)建。就是因為如此,有了大量的測試數(shù)據(jù)顯然不能用這個方法!
首先,我們刪除系統(tǒng)自動創(chuàng)建的Movies.mdf文件。如下圖,如果在App_Data 里面沒有看見,請單擊顯示所有文件圖標(biāo)。
然后進入(PM)軟件包管理控制臺 (視圖——》其他窗口——》程序包管理控制臺)輸入以下指令:Enable-Migrations
出現(xiàn)錯誤那是因為項目中有多個數(shù)據(jù)類別,所以需要選擇一個。重新輸入命令:Enable-Migrations –ContextTypeName MVC5DEMO.Models.MovieDBContext 來指定需要遷移的數(shù)據(jù)庫上下文。
好了,我們會發(fā)現(xiàn)項目中多了一個文件夾(Migrations)和Configuration.cs文件。
然后我們根據(jù)注釋的提示,修改下Seed方法的內(nèi)容為如下:
1234567891011121314151617181920 | protected override void Seed(MVC5DEMO.Models.MovieDBContext context) { context.Movie.AddOrUpdate(i =>; i.Title, new Movie { Title = "虎膽龍威", ReleaseDate=DateTime.Parse("2013-03-16"), Genre="動作", Price=120}, new Movie {Title = "致青春", ReleaseDate=DateTime.Parse("2013-04-26"), Genre="愛情", Price=60} ,new Movie {Title = "中國合伙人", ReleaseDate=DateTime.Parse("2013-05-18"), Genre="劇情", Price=90} ,new Movie {Title = "小時代", ReleaseDate=DateTime.Parse("2013-06-27"), Genre="腦殘", Price=30} ); } |
添加完成后請按下 CTRL-SHIFT-B 生成解決方案
然后我們創(chuàng)建一個數(shù)據(jù)庫遷移的版本,就是初始版本。在管理控制臺輸入 add-migration Initial 其中Initial可以隨便取名。
接著我們在PM(程序包管理控制臺)輸入 Update-Database 指令。
這個指令會檢測剛才那個cs文件,里面包含數(shù)據(jù)庫的結(jié)構(gòu)的說明,然后運行 Seed里面的方法填充數(shù)據(jù)。然后我們F5運行看看。
一切正常!
接下來我們給電影模型添加一個分級功能,類似《小時代》少兒不宜!把我們剛剛注釋掉的再反注釋,然后重新生成下。生成完后還需要修改幾個地方,如果你有自己設(shè)定Bind屬性,還要把新的字段添加進去,同時要去視圖修改下。我們?nèi)ndex.cshtml修改下:
紅色框框就是新增加的2處。同樣的,Create.cshtml也需要添加。
好了之后我們運行看看。
出現(xiàn)錯誤了!那是因為現(xiàn)在的模型已經(jīng)多了一個字段,而數(shù)據(jù)庫還沒有變化。可以用上文提到的讓系統(tǒng)自動把數(shù)據(jù)庫砍掉在重新生成,或者自己手動修改數(shù)據(jù)庫。不過這些都不是最優(yōu)的,最好的是使用Code First 的數(shù)據(jù)庫遷移。第一步,更改Seed文件,在默認(rèn)的那些測試數(shù)據(jù)中添加分級信息。
然后再PM里面輸入 add-migration addRating (名字: addRating 可以隨意,最好有意義)
會發(fā)現(xiàn)多了一個up和down方法,記錄著數(shù)據(jù)庫的變動。接著我們生產(chǎn)解決方案,然后再PM輸入:Update-database 命令。然后運行看看:
評級出現(xiàn)了,我們點擊 Create New 看看:
一切正常,都能添加。但是這樣還不夠智能,接下來我們設(shè)置自動數(shù)據(jù)庫遷移。
在Global.asax里面的 Application_Start方法加上以下代碼:
這樣以后一旦數(shù)據(jù)庫模型變化,就能自動進行升級。
下一步: 添加驗證 。
發(fā)表于 2013 年 11 月 24 日 由 顏晉南
在本教程:將要在Movie 模型添加驗證邏輯確保用戶添加或者編輯時數(shù)據(jù)無誤。
ASP.NET MVC 的核心設(shè)計原則之一就是DRY(Don’t Repeat Yourself)。ASP.NET MVC 鼓勵你為一個功能或者行為編碼一次,在以后需要用到的地方一直復(fù)用就可以。這樣可以減少編寫代碼的數(shù)量,同時易于維護。
在ASP.NET MVC 和 EF code first 中提供的驗證支持就是DRY的好例子??梢灾宦暶饕淮?,然后在任何需要的地方中執(zhí)行規(guī)則。
打開 Movies.cs 文件,然后我們來更新Movie類。利用內(nèi)置的 Required、StringLength、RegularExpression 和 Range Validation 特性添加以下內(nèi)容:
弄完后,我們看看數(shù)據(jù)庫的設(shè)計:
顯然和規(guī)格不符,我們來修改它。先生成解決方案,接下來就是利用數(shù)據(jù)庫遷移功能自動生成。命令如下:在軟件包管理器控制臺輸入
命令完成時,VS會自動打開一個類文件,我們可以看到其中的Up方法。
123456 | public override void Up() { AlterColumn("dbo.Movies", "Title", c =>; c.String(maxLength: 60)); AlterColumn("dbo.Movies", "Genre", c =>; c.String(nullable: false, maxLength: 30)); AlterColumn("dbo.Movies", "Rating", c =>; c.String(maxLength: 5)); } |
Genre 字段不再是可空的,標(biāo)題和分級都添加了驗證條件。我們重新看看數(shù)據(jù)庫的設(shè)計:
已經(jīng)改過來了。相關(guān)限制條件在源碼里面很清楚了,不在細(xì)說。
接下來我們看看效果: 進入 localhost:****/Movies/Create
很明顯了,如果沒有通過本地客戶端的驗證,點擊Create是不會向服務(wù)器提交表單的。
接來下我們看看實現(xiàn)的過程看看在創(chuàng)建視圖和創(chuàng)建Action方法時發(fā)生了什么
先看看 MoviesController 類中的Create方法:
會發(fā)現(xiàn)和以前完全一樣,沒有任何代碼上的變化。第一個Create (GET方法)是用來顯示初始創(chuàng)建的窗體。第二個(POST版本的)方法先驗證是否有錯誤(ModelStateIsValid)如果存在錯誤,則重新顯示窗體,否則就在數(shù)據(jù)庫中保存新的電影信息。客戶端實現(xiàn)校驗是通過 javascript 假如我們禁用它看看會發(fā)生什么。禁用方法不同瀏覽器有不同的選項,搜索一下就可以。
禁用 chrome 后,刷新重新輸入:
沒錯誤提示,我們點擊Create
很明顯,還是有驗證,接下來我們輸入正確的看看。
成功添加進去了,感興趣的話,在movie.cs 的 POST Create請求添加斷點,會發(fā)現(xiàn)輸入錯誤的信息,IsValid 是false ,輸入正確是True。
如果你添加了斷點測試 啟用/禁用 JavaScript 2種情況下Create方法的調(diào)用會發(fā)現(xiàn),在啟用JS的情況下,如果客戶端檢測到錯誤是不會調(diào)用Action里面POST的Create方法。如果禁用了JS功能,到表單提交到服務(wù)器,會通過 ModelState.IsValid 來驗證是否數(shù)據(jù)存在錯誤。
下一部分:這次改進了 Create 方法的數(shù)據(jù)驗證,下一次就是 Details 和 Delete 方法了。
感謝作者,祝作者早日創(chuàng)業(yè)成功!