各種語言方面初級(jí)不能再-aspnetmvc入門_第1頁
各種語言方面初級(jí)不能再-aspnetmvc入門_第2頁
各種語言方面初級(jí)不能再-aspnetmvc入門_第3頁
各種語言方面初級(jí)不能再-aspnetmvc入門_第4頁
各種語言方面初級(jí)不能再-aspnetmvc入門_第5頁
已閱讀5頁,還剩136頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

檢查NerdDinner項(xiàng)目 運(yùn)行NerdDinner應(yīng)用程 測試NerdDinner應(yīng)用程 LINQto 控制器Controller使用視圖 實(shí)現(xiàn)NotFound視圖模 結(jié) 實(shí)現(xiàn)HTTP-GET編輯Action方 Html.BeginForm()和Html.TextBox()HTML輔助方 實(shí)現(xiàn)HTTP-POST的EditAction方 理解ModelState和驗(yàn)證HTML輔助方 Html輔助方法和ModelState集 完成EditAction方法的實(shí) 實(shí)現(xiàn)HTTP-GET的CreateAction方 實(shí)現(xiàn)HTTP-POST的CreateAction方 實(shí)現(xiàn)HTTP-GET的DeleteAction方 實(shí)現(xiàn)HTTP-POSTDeleteAction方 CRUD封 ViewData和 使用ViewData字 Partials和Master頁 使用Partial視圖模 使用Partial視圖模板簡化代 Master頁 分 認(rèn)證和理解認(rèn)證和91 AJAX實(shí)現(xiàn)RSVP響 添加jQuery動(dòng) 簡化-重構(gòu)RSVPPartial視 集成AJAX地 創(chuàng)建MapPartial視 創(chuàng)建一個(gè)Map.js工具類 實(shí)現(xiàn)基于JSON的AJAX搜索Action方 使用jQuery調(diào)用基于JSON的AJAX方 運(yùn) 創(chuàng)建DinnersController單元測 創(chuàng)建FakeDinnerRepository 創(chuàng)建EditAction方法的單元測 測試 MVCWebASP.NETMVC1.0ASP.NETMVCWebApplication了。FileNewProject創(chuàng)建MVCWebApplication,如下圖所示。項(xiàng)目名稱設(shè)置為NerdDinner。點(diǎn)擊確定按鈕后,VisualStudio將彈出一個(gè)創(chuàng)建單元測試項(xiàng)目(CreateUnitTestProject)的框,如下OK按鈕。VisualStuidoSolution2MVCWeb應(yīng)用程序,另一個(gè)是單元測試項(xiàng)NerdDinner項(xiàng)目的VisualStudio創(chuàng)建ASP.NETMVC應(yīng)用程序時(shí),它會(huì)自動(dòng)增加一些文件和到項(xiàng)目中,如下圖所默認(rèn)情況下,ASP.NETMVC項(xiàng)目有6個(gè)頂級(jí) Controls–放置Controller類,處理URL請求。Models–放置業(yè)務(wù)實(shí)體類,表示和操作數(shù)據(jù)。Views–放置UI模板文件,負(fù)責(zé)展示輸出結(jié)果。Scripts–放置Javascript類庫文件和.js文件。App_DataASP.NETMVC應(yīng)用程序不是必須要求這樣的結(jié)構(gòu)。事實(shí)上,大型系統(tǒng)的開發(fā)通常會(huì)將應(yīng)用程序分為多個(gè)項(xiàng)目文件,這樣是項(xiàng)目更易于管理(Model類通常在一個(gè)單獨(dú)的類庫項(xiàng)目中。默認(rèn)的項(xiàng)目結(jié)構(gòu)提供了常規(guī)的結(jié)構(gòu),用來保存應(yīng)用程序更加清晰。當(dāng)我們展開 時(shí),可以發(fā)現(xiàn)默認(rèn)情況下,VisualStudio自動(dòng)增加了2個(gè)Controller類HomeControllerAccountController ,分別為:/Home,/Account和/Shard。同時(shí),也添當(dāng)展開/Content/ScriptsSite.cssJavascriptSite.css文件用來對站點(diǎn)的HTML進(jìn)行格式定義Javascript文件則使Web應(yīng)用程序支持ASP.NETAJAXjQuery面、登錄/logout/等等頁面,以及一個(gè)unhandled錯(cuò)誤頁面。NerdDinner下是NerdDinner應(yīng)用程序的首頁:點(diǎn)擊About,顯示about頁面,如下圖所示Acctegte上述主頁、about頁面、Logout/RegisterMVC項(xiàng)目時(shí)默認(rèn)添加的,NerdDinnerVisualStudio2008VisualStudioIDE測VS2008中打開TestResults27pass/fail狀態(tài),這些創(chuàng)建數(shù)據(jù)2008NerdDinner2Dinners數(shù)據(jù),另一個(gè)用來RSVP。設(shè)置表之間的外鍵關(guān)或者多條RSVP打開RSVP表,DinnerID字段,選擇“關(guān)系…”菜單項(xiàng),如下圖所示表中的每一條記錄關(guān)聯(lián)到Dinners表的一條記錄。SQLServer將負(fù)責(zé)數(shù)據(jù)的一致性,用戶增加沒有對應(yīng)Dinner記錄的新RSVP行,也用戶刪除還存在RSVP行關(guān)聯(lián)的Dinner記錄。DinnersModelModel-View-Controller框架中,model表示應(yīng)用程序的數(shù)據(jù)對象,以及相應(yīng)的業(yè)務(wù)領(lǐng)域邏輯,包括數(shù)據(jù)驗(yàn)證和業(yè)務(wù)規(guī)則。model是MVC應(yīng)用程序的部分,下面我們會(huì)看到model的作用。LINQtoEntities、LINQtoSQL、NHibernaLBLGenPro、SubSonic、WilsonORMADO.NETDataReaders、DataSets等等。對于本范例程序NerdDinner,采用LINQtoSQL創(chuàng)建一個(gè)簡單的業(yè)務(wù)領(lǐng)域模型,非常接近于數(shù)據(jù)repository類,幫助抽象化數(shù)據(jù)LINQtoLINQtoSQL是.NET3.5ORM(ObjectRelationalMapper)部分。LINQtoSQL提供了一個(gè)簡單的方式映射數(shù)據(jù)表到.NET類。對于我們的NerdDinner范例程序,Dinners和RSVP數(shù)據(jù)表到Dinner和RSVP模型類。Dinners和RSVP數(shù)據(jù)表中的列將為Dinner和RSVP模型類的屬性。每一個(gè)Dinner和RSVP對象將表示Dinners或RSVP數(shù)據(jù)表中的一條單獨(dú)的數(shù)據(jù)記錄。LINQtoSQL避免讓我們手動(dòng)創(chuàng)建SQL從數(shù)據(jù)庫中檢索和更新Dinner和RSVP對象。在或更新數(shù)據(jù)庫記錄時(shí),LINQtoSQLSQLVBC#LINQ語言寫查詢表達(dá)式,檢索Dinner和RSVP對象。這樣可以大量減少代碼行,構(gòu)建清晰的應(yīng)用程序。增LINQtoSQL類到項(xiàng)目程序現(xiàn)在終于可以回到我們的NerdDinner應(yīng)用程序了!Models文件夾,選擇Add->NewItem菜Add按鈕。VisualStudio將添加NerdDinner.dbml文件到\ModelsLINQtoSQL使LINQtoSQL創(chuàng)DataModelLINQtoSQLServerExplorerNerdDinner表自動(dòng)產(chǎn)生Dinner類。這一類名有助于我們的模型類符合.NET命名規(guī)范。但是,如果你不喜歡設(shè)另外,默認(rèn)情況下,LINQtoSQL設(shè)計(jì)器也會(huì)自動(dòng)監(jiān)視主鍵/外鍵關(guān)系,并基于這些關(guān)系,創(chuàng)建不同模型DinnersRSVPLINQtoSQL設(shè)計(jì)器上時(shí),自動(dòng)創(chuàng)建1對多的關(guān)聯(lián)關(guān)系,圖中通過一個(gè)箭頭進(jìn)行表示。上述關(guān)聯(lián)關(guān)系將讓LINQtoSQL增加一個(gè)強(qiáng)類型的Dinner屬性到RSVP類中,開發(fā)可以使用指定RSVP的Dinner屬性關(guān)聯(lián)的實(shí)體。也會(huì)讓Dinner類有一個(gè)強(qiáng)類型的RSVP集合屬性,允許開發(fā)檢索和更新Dinner關(guān)聯(lián)的RSVP對象集合。以進(jìn)行重命名、刪除或者更改。對于NerdDinner應(yīng)用程序,使用默認(rèn)的設(shè)置。NerdDinnerDontexttoSQLLINQtoSQLDontextLINQtoSQL類為NerdDinner,創(chuàng)建DontextNerdDinnerDontext,NerdDinnerDontext類將是我們與數(shù)據(jù)庫交互的NerdDinnerDontext2個(gè)屬性-DinnersRSVPs2個(gè)數(shù)據(jù)表。我們使用C#寫LINQ查詢語句這些屬性,從數(shù)據(jù)庫去查詢和檢索Dinner和RSVP對象。如下的代碼演示如何實(shí)例化NerdDinnerDontextLINQDinners對象。NerdDinnerDontext對象對Dinner和RSVP對象的所有變更,允許我們輕松保存變更到數(shù)據(jù)庫中。LINQDinner2個(gè)屬性,接著//RetrieveDinnerobjectthatreprentsrowwithDinnerIDof1Dinnerdinner=db.Dinners.Single(d=>d.DinnerID==1);//UpdatetwopropertiesonDinnerdinner.Title="ChangedTitle";dinner.Description="Thisdinnerwillbefun";//Persistchangestodatabase代碼中的NerdDinnerDontext對象自動(dòng)對Dinner對象的所有屬性變更。當(dāng)我們調(diào))創(chuàng)DinnerRepository對于一個(gè)小應(yīng)用程序而言,有時(shí)讓ConrollersLINQtoSQLDontextLINQ查詢語LINQ查詢在多個(gè)地方出現(xiàn)。讓和測試更方便的方法是使用Repository模式。Repository類幫助封裝數(shù)據(jù)查詢和邏輯,從應(yīng)用程序中抽象具體的數(shù)據(jù)實(shí)現(xiàn)。除了是應(yīng)用程序代碼更加簡潔外,使用Repository模式使將來//QuerypublicIQueryable<Dinner> publicDinner GetDinner(intid);//publicvoidAdd(Dinnerdinner);publicvoidDelete(Dinnerdinner);//PersistencepublicvoidSave();}Injection為了實(shí)現(xiàn)這個(gè)類,Models文件夾,選擇Add->NewItem菜單項(xiàng)。在AddNewItem框,我們選擇Class模板,并命名文件為DinnerRepository.cs。呵呵,終于又回到NerdDinner應(yīng)用程序了。//Query{return} {returnfromdinnerinwheredinner.EventDate>DateTime.Noworderbydinner.EventDateselect}publicDinnerGetDinner(intid)}//Insert/DeletepublicvoidAdd(Dinner{}publicvoidDelete(Dinner}//publicvoid{}}//RetrievespecificdinnerbyitsDinnerIDDinnerdinnerdinnerRepository.GetDinner(5);下面的代碼用來檢索所有將來的dinners,并遍歷://Retrieve ing ingDinners= //Loopovereach ingDinnerandprintoutitsTitleforeach(Dinnerdinnerin ingDinners){}//CreateFirstDinnernewDinner1=newDinner();newDinner1.Title="DinnerwithScott";newDinner1.HostedBy="ScotGu";newDinner1.ContactPhone=" //CreateSecondDinnernewDinner2=newDinner();newDinner2.Title="DinnerwithBill";newDinner2.HostedBy="BillG";newDinner2.ContactPhone=" //AddDinnerstoRepository//PersistChanges//RetrievespecificdinnerbyitsDinnerIDDinnerdinner=dinnerRepository.GetDinner(5);//UpdateDinnerpropertiesdinner.Title="UpdateTitle";dinner.HostedBy="NewOwner";//Persistchanges//RetrievespecificdinnerbyitsDinnerIDDinnerdinner=dinnerRepository.GetDinner(5);//CreateanewRSVPobjectRSVPmyRSVP=newRSVP();//AddRSVPtoDinner'sRSVPCollection//PersistchangesDinnerRepository對象的Delete方法,標(biāo)記該條記錄刪除。最后,在調(diào)用Repository對象的Save()方法時(shí),從數(shù)據(jù)庫表中刪除該記錄。DinnerRepositorydinnerRepository=newDinnerRepository();//RetrievespecificdinnerbyitsDinnerIDDinnerdinner=dinnerRepository.GetDinner(5);//Markdinnertobedeleted//PersistchangesModel類集成驗(yàn)證和業(yè)務(wù)規(guī)則邏SchemaLINQtoSQLModel類時(shí),數(shù)據(jù)模型類的屬性類型和數(shù)據(jù)表的字段類型相關(guān)。例如,DinnersEventDatedatetime類型LINQtoSQLDateTime類型(這是內(nèi)置的.NET數(shù)據(jù)類型。這意味著,如果你試圖賦值整型或布爾型,將產(chǎn)生編譯錯(cuò)誤。當(dāng)使用字符串時(shí),LINQtoSQL將自動(dòng)避開SQL值,因此你不必?fù)?dān)心SQL注入。在NerdDinner范例程序中,采用相對簡單和直接的模式,對Dinner模型類公開IsValid屬性和GetRuleViolations方法,IsValidtruefalse,GetRuleViolations()則返回PartialclassIsValidGetRuleViolations()方法。Partial類用來增加方法/AddDinner.cs文件到項(xiàng)目中,并默認(rèn)打開。接著,我們使用如下的代碼來實(shí)現(xiàn)基本的publicpartialclassDinnerpublicboolIsValidget{return(GetRuleViolations().Count()==0);}{yield}{if}}publicstringErrorMessage{get;privateset;}publicstringPropertyName{get;privateset;{ErrorMessage=errorMessage;PropertyName=propertyName;}}publicIEnumerable<RuleViolation>GetRuleViolations()ififififififif(!PhoneValidator.IsValidNumber(ContactPhone,yieldreturnnewRuleViolation("Phone#doesnotmatchcountry",yield}C#yieldreturn特性,返回有序的RuleViolation6個(gè)檢查確保Dinner的字符串屬性不能是null或空,最后一個(gè)規(guī)則比較有趣,調(diào)用PhoneValidator.IsValidNumberContactPhone數(shù)字格式符合相應(yīng)的我們使用.NET的正則表達(dá)式來實(shí)現(xiàn)的驗(yàn)證,下面是我們添加到項(xiàng)目中的一個(gè)簡{"UK",newRegex("(^1300\\d{6}$)|(^1800|1900|1902\\d{6}$)|{"Netherlands",newRegex("(^\\+[0-9]{2}|^\\+[0-|^\\(\\+[0-9]{2}\\)\\(0\\)|^00[0-9]{2}|^0)([0-9]{9}$|[0-9\\-publicstaticboolIsValidNumber(stringphoneNumber,string{if(country!=null&&countryRegex.ContainsKey(country))returncountryRegex[country].IsMatch(phoneNumber);return}{getreturn}}}Dinnerdinner=dinner.Country="USA";if(!dinner.IsValid)varerrors=//dosomethingtofixthe}()這是因?yàn)镈inner對象存在的業(yè)務(wù)規(guī)則,Dinner.OnValidate()分部方法(PartialMethod)拋出異常。我Dinnerdinner=dinnerRepository.GetDinner(5);try{dinner.Country="USA";}catchvarerrors=//dosomethingtofix}UI層,這些可以應(yīng)用在應(yīng)用程序的所控制器和視圖(ControllersandURL地址,像/Products.aspx或/Products.php,由Products.aspxProducts.php文件負(fù)責(zé)處理。基于Web的MVC框架URL地址到服務(wù)器端代碼有點(diǎn)不同,不是URL地址到特定文件,而是映和保存數(shù)據(jù),并返回結(jié)果給客戶端(顯示HTML、文件、或重定向到不同的URL等等。現(xiàn)在,我們已經(jīng)創(chuàng)建一個(gè)基本的model,下一步將添加控制器類到項(xiàng)目中,為Dinners用戶提供數(shù)DinnersController添Index()Details()方法DinnersController的信息。應(yīng)用程序?qū)l(fā)布如下的URL地址:/Dinners]例如,/Dinners/Details/2將在HTML頁面顯示DinnerID=2的詳細(xì)信息。publicclassDinnersController:Controller//HTTP-GET:publicvoidIndex()Response.Write("<h1>ComingSoon:}//HTTP-GET:publicvoidDetails(intid)Response.Write("<h1>DetailsDinnerID:"+id+}}()你可能想知道-ASP.NETMVCDinnersControllerMVC路ASP.NETMVCcontroller類,調(diào)用哪一個(gè)方法,以及從URL/Querystring中自動(dòng)解析變量值,并作為參數(shù)傳遞給方法。ASP.NETMVCSEO(SearchEngineOptimization)優(yōu)化的序,而不需要配置任何東西??梢栽陧?xiàng)目中的Application類中看到默認(rèn)的路由規(guī)則。在范例項(xiàng)目的根,雙擊Global.asax文件。publicvoidRegisterRoutes(RouteCollection //Route //URLw/paramsnew{controller="Home",action="Index",id=""}//Paramdefaults}URL格式為:/{controller}/{actionid}controller是指需要實(shí)例化的類名,action是將調(diào)用的公()Id=。modelIndex()Details()action方法的實(shí)現(xiàn)。我們使用之前創(chuàng)建的DinnerRepository類來實(shí)現(xiàn)這些方法。類的成員變量。在本章的后面部分,引入依賴注入(DependencyInjection)的概念,演示另外一usingusingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Web;usingSystem.Web.Mvc;usingNerdDinner.Models;publicclassDinnersController:Controller//GET:publicvoidIndex()vardinners= }//GET:publicvoidDetails(intid)Dinnerdinner=}}}actionHTMLResponse.Write()方法返回給客戶端,但是這種方法DinnersControlleraction方法中僅僅出來業(yè)務(wù)和數(shù)據(jù)邏輯,并將相關(guān)的數(shù)據(jù)傳遞給單獨(dú)的視圖(view)模板,view負(fù)責(zé)生成HTML展示。隨后我們會(huì)看到,view模板就是一個(gè)簡單的文本文件,通常包含HTML標(biāo)識(shí)和嵌入的。將控制器controller邏輯和視圖view展示分開帶來很多好處,尤其是它幫助清晰了應(yīng)用程序代碼和用戶界面展示的。這可以非常方便地對應(yīng)用程序邏輯進(jìn)行單元測試,而不需要UI展示邏輯,也可以方便修改UI,而不會(huì)更改應(yīng)用程序的代碼,當(dāng)然也有助于開發(fā)和用戶界面設(shè)計(jì)在項(xiàng)目下面,我們更新DinnersController類,通過更新2個(gè)action方法原型(將返回類型從void更新為ActionResult來返回ViewResult對象。publicclassDinnersController:Controller//GET:vardinners= }//GET:public etails(intid)Dinnerdinner=dinnerRepository.GetDinner(id);if(dinner==null)returnView("NotFound");}}上面代碼中,我們使用的View()View(viewHTMLmodel對象,包含了view模板生成HTML響應(yīng)所需要的數(shù)據(jù)。在Index()action方法中,我們調(diào)用View()輔助方法,表示使用Index視圖模板來生成HTML形式的宴會(huì)(dinners)列表。我們傳遞一組Dinner對象給view模板,用來生成。DetailsDinnerDinnerNotFoundDinner對象不存在(View()方法僅僅需要傳入視圖模板名稱–View(“NotFound”)。NotFound我們開始實(shí)行NotFound視圖模板–顯示一條友好的錯(cuò)誤信息,說明請求的宴會(huì)(dinner)沒有找到。AddViewNotFound,如下圖所示。默認(rèn)情況下,框中的視圖名稱就與光標(biāo)actionDetailsNotFound視圖模板,因此點(diǎn)擊Add按鈕,VisualStudio將在\Views\Dinners content<asp:ContentID="Content1"ContentPlaceHolderID="TitleContent"runat="server">DinnerNotFound<asp:ContentID="Content2"ContentPlaceHolderID="MainContent"<h2>DinnerNot<p>Sorry-butthedinneryourequesteddoesn'texistorwasNerdDinner范例程序,并在瀏覽器地址欄輸入:/Dinners/Details/9999dinner在數(shù)據(jù)庫中根本不存在,因此DinnersController.Details()action方法將呈現(xiàn)NotFound視圖模板,如下圖所示:MasterPage模板,在整個(gè)站點(diǎn)實(shí)現(xiàn)一致的布局效果。在本章后續(xù)部分,我們會(huì)介紹關(guān)于MasterPage的技術(shù)。Createastrongly-typedView(創(chuàng)建強(qiáng)類型視圖)復(fù)選框,并從下拉列表框中選擇從Controller傳遞到View的Model模型類型。針對正在創(chuàng)建的Details視圖,傳遞Dinner對象(該NerdDinne.Models.DinnerDetailsDinnerdetails視圖模板生成一個(gè)原始的Add按鈕之后,VisualStudio自動(dòng)在\Views\DinnersDetails.aspx<asp:ContentID="Title"ContentPlaceHolderID="TitleContent"runat="server"><asp:ContentID="Main"ContentPlaceHolderID="MainContent" <%=Html.Encode(String.Format("{0:g}",Model.EventDate)) Html.Encode(String.Format("{0:F}",Model.Latitude)) Html.Encode(String.Format("{0:F}",Model.Longitude))就這么簡單和快速,Details.aspx頁面提供了一個(gè)初始的實(shí)現(xiàn)。下面,根據(jù)需要,進(jìn)一步定制用戶Details.aspxHTML和嵌入展示代碼。在視圖模板呈現(xiàn)時(shí),<%%>代碼塊就會(huì)執(zhí)行,<%=%>代碼塊執(zhí)行其中的代碼,并呈現(xiàn)結(jié)果到視圖的輸出中<asp:ContentID="Title"ContentPlaceHolderID="TitleContent"runat="server">Details:<%=Html.Encode(Model.Title)%><asp:ContentID="Main"ContentPlaceHolderID="MainContent" <%=Html.Encode(Model.HostedBy)%>(<%=Html.Encode(Model.ContactPhone)%>)Index視圖?,F(xiàn)在我們開始實(shí)行IndexDinners列表。首先,將光標(biāo)定位在Indexaction方法(當(dāng)然是在DinnersController類中接著,選擇彈出菜單中的AddView菜單項(xiàng)。我們選擇NerdDinner.Models.Dinner為模型類型,ViewContentList,用來生成初始的列表腳Add按鈕,VisualStudio自動(dòng)在\Views\DinnersIndex.aspx視圖模板,且自動(dòng)實(shí)現(xiàn)一個(gè)初始的實(shí)現(xiàn),將傳入到視圖的數(shù)據(jù)以HTML表格的形式呈現(xiàn)。當(dāng)我們運(yùn)行范例程序時(shí),/Dinners/DinnersIndex.aspx視圖模板,展示較少的列,并使用<ul>元素來呈現(xiàn)列表,而不是使用表格。示例代碼如下:<asp:ContentID="Main"ContentPlaceHolderID="MainContent" ing<%foreach(vardinnerinModel){<%=Html.Encode(dinner.Title)%><%}上述代碼使用varforeachModeldinnerC3.0不熟悉的人可能認(rèn)為使用vardinnerlate-boundModel(類型為IEnumerable<Dinner>)dinnerdinnerDinner類型,同時(shí)提供代碼智使用HTML超指向DinnersController控制器的Detailsaction方法,來實(shí)現(xiàn)這一點(diǎn)。嵌在HTML<a>元素中,如下所示:ASP.NETMVCHtml.ActionLink()的action方法名稱(示例代碼是Details方法第三個(gè)參數(shù)是一組傳入給action方法的參數(shù)(以類型的名稱/值對的方式來實(shí)現(xiàn)。上述代碼中,指定的dinner的id參數(shù)。因?yàn)锳SP.NETMVC默認(rèn)的URL路由規(guī)則是{Controller}/{Action}/{id},Html.ActionLink()輔助方法將生成如下的輸出:<ahref="/Dinners/Details/1">.NET<asp:ContentID="Main"ContentPlaceHolderID="MainContent" ing<%foreach(vardinnerinModel){<%=Html.ActionLink(dinner.Title,"Details",new{id=dinner.DinnerID})%><%} 結(jié) 控制器中視圖時(shí),不必指定完整的路徑。ASP.NETMVC將自動(dòng)尋找應(yīng)用程序\Views\[ControllerName]\例如,我們創(chuàng)建的DinnersController類–直接3個(gè)視圖模板:Index/Details/NotFound。ASP.NETMVC默認(rèn)到應(yīng)用程序的\Views\Dinners AccounCoolle,其中后面2個(gè)控制器是在創(chuàng)建項(xiàng)目時(shí)默認(rèn)添加的,另外在\Views 中有3個(gè)子,分別對應(yīng)Controller類。Home和Accounts控制器的視圖會(huì)自動(dòng)到相應(yīng)的\Views\Home和 \Views\Shared子則用來存放共享的視圖模板,可供多個(gè)控制器使用。ASP.NETMVC在解析一個(gè)視圖模板時(shí),首先檢查\Views\[Controller]特定,如果找不到,則繼續(xù)到\Views\Shared子中尋找。Index視圖來呈現(xiàn)視圖結(jié)果,DetailsactionDetails視圖來呈現(xiàn)結(jié)果。這樣,有助于很快知道哪一個(gè)視圖模板和哪一個(gè)action方法關(guān)聯(lián)。當(dāng)視圖模板和控制器調(diào)用的action方法有相同的名稱時(shí),開發(fā)可以不必顯式指定視圖模板的名稱。View輔助方法(不需要制定視圖名稱,AS.NETMVC將自動(dòng)推斷出我們使用的視圖\Views\[controllerName]\[ActionName],并展示結(jié)果。publicclassDinnersController:Controller//GET:vardinners= return}//GET:public etails(intid)Dinnerdinner=if(dinner==return}}創(chuàng)建、更新、刪除記2actionDinnersController2URL:/Dinners同時(shí)支持HTTPGET和HTTPPOST方法這些新的URL地址。HTTPGET對這些URL地址的請求將顯示初始的HTML視圖(editDinner數(shù)據(jù);create將顯示一個(gè)空白的窗口;delete則顯示一個(gè)確認(rèn)框。HTTPPOST對這些URL的請求將保存/更新/刪除DinnerRepository的Dinner數(shù)據(jù)。下面開始實(shí)行editHTTP-GETAction我們首先實(shí)現(xiàn)editaction方法的HTTPGET動(dòng)作。在/Dinners/Edit/[id]地址時(shí),該方法將被調(diào)用。實(shí)//GET:publicActionResultEdit(intid)Dinnerdinner=return}在View()輔助方法中沒有顯式傳入視圖的名稱,因此它將基于慣例,使用默認(rèn)的視圖模板:DinnersControllerEditaction方法中點(diǎn)擊鼠標(biāo)右鍵,選擇AddView菜單項(xiàng)。在彈出的AddView框,設(shè)置Viewdlass為NerdDinner.Models.DinnerDinner對象(Model)Viewcontent為在點(diǎn)擊Add按鈕后,VisualStudio自動(dòng)在\Views\Dinners 中創(chuàng)建一個(gè)新的Edit.aspx視圖模板文件,并自動(dòng)在VS編輯器中打開,提供一個(gè)初始的Edit模板的實(shí)現(xiàn)。<asp:ContentID="Content2"ContentPlaceHolderID="MainContent"<h2>Edit=Html.ValidationSummary("Pleasecorrecttheerrorsandtryagain.")%>using(Html.BeginForm()){%>=Html.TextBox("Title")=Html.ValidationMessage("Title","*")<label <%=Html.ValidationMessage("EventDate","*")<label=Html.TextArea("Description") <label=Html.TextBox("Address")=Html.ValidationMessage("Address","*")<label=Html.TextBox("Country")=Html.ValidationMessage("Country","*")<labelfor="ContactPhone">ContactPhone =Html.ValidationMessage("ContactPhone","*")<label=Html.TextBox("Latitude")=Html.ValidationMessage("Latitude","*")<label=Html.TextBox("Longitude")<%}/Dinners/Edit/2HTTPPOSTHTML-<inputtype=”text/>元素用來展示可編Html.BeginForm()Html.TextBoxHTMLttaytBgmtt和Html.ValidationMessage()等等。處理生成HTML外,這些輔助方法還提供了內(nèi)置的錯(cuò)誤處理和驗(yàn)Html.BeginForm()輔助方()<C#using語句。左括號(hào){表示開始<form>}表示結(jié)束</form><%using(Html.BeginForm()){<!--FieldsOmittedforBrevity--<%}usingHtml.BeginFormHtml.EndForm()組合,示例代<% <!--FieldsOmittedforBrevity--Edit<formaction="/Dinners/Edit/1"method="post元素。當(dāng)然,如果需要提交到不同的URL地址,我們可以傳入顯式的參數(shù)給Html.BeginForm()方法。Html.TextBox()輔助方()"/>Html.TextBox(“Title”)方法將輸出<inputid="Titlename="Title"type="text"value=".NETFutures"/>。Html.TextBoxid/name屬性值,并顯式給第二個(gè)參如果需要對輸出結(jié)果進(jìn)行格式化輸出,則可以使用.NETString.Format靜態(tài)方法。Edit.aspx視圖模板使用這一方法來對EventDate值進(jìn)行格式化(DateTime類型<%=Html.TextBox("EventDate",String.Format("{0:g}",Model.EventDate))%>()字Class,采用@前綴。HTTP-POSTEditAction點(diǎn)擊Save保存按鈕,將觸單提交到/Dinners/Edit/2,并通過HTTPPOST提交<input>表單中的值。下面,我們開始實(shí)現(xiàn)HTTPPOST的Editaction方法–負(fù)責(zé)處理保存操作。責(zé)處理HTTPPOST動(dòng)作。//POST:}action方法添加[AcceptVerbs]屬性后,ASP.NETMVCHTTP動(dòng)作,自動(dòng)分發(fā)請求action方法。HTTPPOST請求/Dinners/Edit/[id]將有上述Edit方法負(fù)責(zé)處理,然而所有其他的HTTP請求/Dinners/Edit/[id]將有之前定義的Edit方法負(fù)責(zé)(該方法沒有[AcceptVerbs]屬性。獲取表單提交的HTTPPOSTEditController基類的Request屬性來form集合,并直接獲取提交的參數(shù)值://POST://RetrieveexistingDinnerdinner=//Updatedinnerwithformpostedvaluesdinner.Title=Request.Form["Title"];dinner.EventDate=DateTime.Parse(Request.Form["EventDate"]);dinner.Address=Request.Form["Address"];dinner.Country=Request.Form["Country"];dinner.ContactPhone=Request.Form["ContactPhone"];//Persistchangesbacktodatabase//PerformHTTPredirecttodetailspageforthesavedDinnerreturnRedirectToAction("Details",new{id=dinner.DinnerID});}()publicActionResultEdit(intid,FormCollection{Dinnerdinner=returnRedirectToAction("Details",new{id=dinner.DinnerID}SaveEdit方法的調(diào)用,并將更新的值持久化到數(shù)據(jù)庫。接著,重定向到詳細(xì)頁面–Details視圖(顯示保存的數(shù)據(jù)。處理編輯異ASP.NETMVC包括一些友好的內(nèi)置功能,使異常處理和重新顯示表單更容易。為了演示這些功能,下面我們再次更新EditAction方法,代碼如下://POST:publicActionResultEdit(intid,FormCollection{Dinnerdinner=dinnerRepository.GetDinner(id);try{}catchforeach(varissuein}return}}try/catchUpdateModel()方法出現(xiàn)異常,或者保存DinnerRepository時(shí)出現(xiàn)異常(如果我們試圖保存一個(gè)無效的對象-規(guī)則,并添加到ModelState對象中,接著重新顯示視圖。下面為了模擬異常信息,重新運(yùn)行應(yīng)用程序,編輯Dinner,并將TitleEventDate設(shè)置為“BOGUS”,格式等等,然后點(diǎn)擊Save保存按鈕,現(xiàn)在HTTPPOST觸發(fā)Edit方法,但不能成功保存Dinner信息(因?yàn)橛挟惓C吹哪??這是因?yàn)槲覀兪褂昧艘恍﹥?nèi)置的ASP.NETMVC功能,使輸入驗(yàn)證和異常處理更加容易。ModelStateHTMLUpdateModel()modelModelState()EventDate,UpdateModel()ModelState集合,說明在給該屬性賦理異常塊中,根據(jù)Dinner對象中的RuleVilations(規(guī)則)信息,添加到ModelState集合中。publicActionResultEdit(intid,FormCollection{Dinnerdinner=dinnerRepository.GetDinner(id);try{}catchforeach(varissuein}return}}Html輔助方法ModelState錯(cuò)誤,將呈現(xiàn)用戶輸入的內(nèi)容和CSS錯(cuò)誤類。<%=Html.TextBox("EventDate",String.Format("{0:g}",Model.EventDate))當(dāng)有錯(cuò)的時(shí)候呈現(xiàn)視圖時(shí),Html.TextBox()方法檢查ModelStateDinner對textbox”/>元素添加CSS錯(cuò)誤類,如下所示:<inputclass="input-validation-error"id="EventDate"name="EventDate"type="text".input-validation-{border:1pxsolid#ff0000;background-color:#ffeeee;}()()<%=<%=Html.ValidationMessage("EventDate","*")Html.ValidationSummary()輔()()添加到controller的ModelState集合:catchforeach(varissuein}return}擴(kuò)展方法,添加了一個(gè)對ASP.NETMVCModelStateDictionary類的輔助方法。該擴(kuò)展方法封裝了使用RuleViolation錯(cuò)誤信息填充ModelStateDictionary集合類的邏輯: IEnumerable<RuleViolation>errors){foreach(RuleViolationissuein}}}EditAction//GET:publicActionResultEdit(intid)Dinnerdinner=dinnerRepository.GetDinner(id);returnView(dinner);}//POST:/Dinners/Edit/2publicActionResultEdit(intid,FormCollection{Dinnerdinner=dinnerRepository.GetDinner(id);try{}catchreturnView(dinner);}}EditControllerViewDinner模型類的特定ModelController和View更改代碼。這樣,我們可以根據(jù)需求,以最小的更改代碼量,靈活改進(jìn)應(yīng)用程序。HTTP-GETCreateActionpublicActionResult{Dinnerdinner=new{EventDate=return}對象呈現(xiàn)視圖。因?yàn)槲覀儧]有顯式傳入名稱給View()輔助方法,因此它將基于慣例和默認(rèn)路徑解析視下面創(chuàng)建視圖模板。右鍵在CreateAction方法內(nèi)點(diǎn)擊,并選擇AddView菜單項(xiàng)。在AddView框表示將傳入Dinner對象給視圖模板,并選擇Create模板。如下圖所示:當(dāng)點(diǎn)擊Add按鈕,VisualStudio自動(dòng)在\Views\Dinners 建的Create.aspx文件進(jìn)行修改,修改之后的代碼如下:<asp:ContentID="Content2"ContentPlaceHolderID="TitleContent"runat="server">HostaDinner<asp:ContentID="Content3"ContentPlaceHolderID="MainContent"<h2>Hosta=Html.ValidationSummary("Pleasecorrecttheerrorsandtryagain.")%>using(Html.BeginForm()){%><label<label=Html.TextBox("EventDate")=Html.ValidationMessage("EventDate","*")<label=Html.TextArea("Description")=Html.ValidationMessage("Description","*")<label=Html.TextBox("Address")=Html.ValidationMessage("Address","*")<label=Html.TextBox("Country")=Html.ValidationMessage("Country","*")<label =Html.ValidationMessage("ContactPhone","*")<label=Html.TextBox("Latitude")=Html.ValidationMessage("Latitude","*")<label <%=Html.ValidationMessage("Longitude","*")<%現(xiàn)在,我們運(yùn)行NerdDinner應(yīng)用程序,并在瀏覽器中/Dinners/Create,將根據(jù)CreateHTTP-POSTCreateAction到/Dinners/Create地址,并使用HTTPPOSTHTML表單參數(shù)。現(xiàn)在開始實(shí)現(xiàn)HTTPPOST動(dòng)作的CreateAction方法。添加一個(gè)重載的Createaction方法到//POST:/Dinners/CreatepublicActionResultCreate()}DinnerUpdateModel()輔助方法(Edit方法一樣到Detailsaction方法,并顯示新創(chuàng)建的Dinner對象://POST:/Dinners/CreatepublicActionResultCreate()Dinnerdinner=newDinner();try{}catchreturnView(dinner);}}DinnerDinneraction方法,代//POST:/Dinners/Create{if(ModelState.IsValid){try{dinner.HostedBy="SomeUser";}catch}}return}ModelState.IsValidDinner對象是否成功通過表單提交過來的參數(shù)值進(jìn)行賦值了。如果存在輸入無效的數(shù)據(jù),將返回False(如傳入“BOGUS”給EventDate屬性。如果存在任何問題,action方法將重新顯示表單。如果輸入的參數(shù)是有效的,actionDinnerDinnerRepository。代碼塊為了測試錯(cuò)誤處理機(jī)制,我們請求/Dinners/CreateURLDinner詳細(xì)信息。不正確的輸入更新Edit或Createaction方法。Dinner對象將添加到數(shù)據(jù)庫。接著,重定向到/Dinners/Details/[id]DinnerHTTP-GETDeleteAction//HTTPGET:/Dinners/Delete/1publicActionResu elete(intid){Dinnerdinner=dinnerRepository.GetDinner(id);if(dinner==null)}

return創(chuàng)建Delete視圖的方法不重復(fù)了,如下圖所示:點(diǎn)擊Add按鈕后,VisualStudio自動(dòng)在\Views\Dinners 下創(chuàng)建一個(gè)新的Delete.aspx視圖模板文件。<asp:ContentID="Content2"ContentPlaceHolderID="TitleContent"runat="server">DeleteConfirmation:<%=Html.Encode(Model.Title)%><asp:ContentID="Content3"ContentPlaceHolderID="MainContent"Delete<p>Pleaseconfirmyouwanttocancelthedinner <%}]運(yùn)行應(yīng)用程序,/Dinners/Delete/[id],id標(biāo)識(shí)一個(gè)有效的Dinner對象,在瀏覽器中顯示效果如HTTP-POSTDeleteAction//HTTPPOST:/Dinners/Delete/1public elete(intid,string{Dinnerdinner=dinnerRepository.GetDinner(id);if(dinner==null)returnreturn},NotFoundDinnerRepositoryDeleted視圖模板?,F(xiàn)在需要?jiǎng)?chuàng)建Deleted視圖模板,在AddView框中,不需要選擇強(qiáng)類型的Model類型,代碼如下:<asp:ContentID="Content2"ContentPlaceHolderID="TitleContent"runat="server">DinnerDeleted<asp:ContentID="Content3"ContentPlaceHolderID="MainContent"<p>Yourdinnerwassuccessfully ing再次運(yùn)行范例程序,/Dinners/Delete/[id]URL地址,在確認(rèn)刪除窗口中,點(diǎn)擊刪除Delete按鈕,執(zhí)HTTP-POST操作到/Dinners/Delete/[idDinnersController中的DeletePost版本,從數(shù)據(jù)庫中刪除指定的Dinner記錄,并顯示已刪除Deleted視圖模板:模型綁定的安全我們已經(jīng)討論了2中不同的方法使用ASP.NETMVC內(nèi)置的模型綁定功能。第一個(gè)方法是使用UpdateModel()action方法所有用戶輸入值,避免HTML和Javascript注入(備注:我們的范例應(yīng)用程序使用LINQtoSQL,可以自動(dòng)編碼所有參數(shù),避免這些類型的。不能僅僅依賴于客戶端的驗(yàn)證,總是要采用服務(wù)端的驗(yàn)?zāi)J(rèn)情況下,UpdateModel()方法試圖根據(jù)匹配的表單參數(shù)值,更新所有的屬性。同樣地,作為參數(shù)傳遞給action方法的模型對象,基于表單參數(shù)設(shè)置全部模型對象的屬性?;谟猛緛礞i定綁組參數(shù)給UpdateModel()方法:string[]allowedProperties=new[]{"EventDate","Latitude",UpdateModel(dinner,Action[Bind]includelist或者允許的屬性列//POST:}基于類型來鎖定綁ControllersAction方法中應(yīng)用了,包括UpdateModel方法和Action方法的參數(shù)。通過添加[Bind]Global.asax文件中(如果類型不是我們自己定義的我們的NerdDinner應(yīng)用程序?qū)⑹褂眠@一技術(shù),添加[Bind]屬性,顯示可綁定的屬性:publicpartialclassDinner}RSVPs集合、DinnerIDHostedBy屬性都不允許通過綁定來設(shè)置?;诎踩脑?,這些屬性只能在action方法中使用顯式的代碼進(jìn)行設(shè)置。CRUDASP.NETMVCDinnerRepository類中使用了大量這些功能提供CRUD的支持。publicclassDinnersController:Controller//GET:vardinners=dinnerRe returnView(dinners);}//GET:public etails(intid)Dinnerdinner=if(dinner==return}//GET:publicActionResultEdit(intid)Dinnerdinner=dinnerRepository.GetDinner(id);returnView(dinner);}//POST:/Dinners/Edit/2publicActionResultEdit(intid,FormCollection{Dinnerdinner=try}catchreturn}}//GET:/Dinners/CreatepublicActionResultCreate(){Dinnerdinner=newDinner()EventDate=return}//POST:/Dinners/Create{if(ModelState.IsValid){try{dinner.HostedBy=returnRedirectToAction("Details",}catch}}return}//HTTPGET:/Dinners/Delete/1publicActionResuelete(intid){Dinnerdinner=if(dinner==return}//HTTPPOST:/Dinners/Delete/1public elete(intid,string{Dinnerdinner=dinnerRepository.GetDinner(id);if(dinner==null)returnreturn}}ViewData現(xiàn)在進(jìn)一步擴(kuò)展DinnersController,實(shí)現(xiàn)豐富表單編輯功能。這里我們討論2種方法,用來將數(shù)據(jù)從Controller傳遞到View:ViewData和ViewModel。ControllerViewMVC模式一個(gè)典型的特征是嚴(yán)格的功能。Model模型、Controller控制器和View視圖各自定義了作從不執(zhí)行任何數(shù)據(jù)查詢或應(yīng)用程序邏輯–僅僅負(fù)責(zé)呈現(xiàn)ModelController傳遞過來的數(shù)據(jù)。目前,DinnersControllerViewModelIndex()方法是Dinner對象列表,Details()Edit()Create()和Delete()方法則是傳遞一個(gè)Dinner對象。當(dāng)增加UI特性時(shí),我們經(jīng)常需要傳遞數(shù)據(jù),在視圖模板中展示HTML響應(yīng)。例如,我們需要改變Edit和Create視圖中Country字段(從HTML文本框到下拉列表框。生成一個(gè)動(dòng)態(tài)的、支持的國家列表,而給View模板。下面看看通過2種方式來實(shí)現(xiàn)。ViewDataEditCountryEdit()Action方法,傳SelectList對象(Dinner對象外CountryModel類。publicActionResultEdit(intid)Dinnerdinner=ViewData["Countries"]=newSelectList(PhoneValidator.AllCountries,dinner.Country);returnView(dinner);}下面更新Edit.aspx視圖模板,使用Html.DropDownList()輔助方法代碼Html.TextBox()輔助方法:()ViewDataSelectListC#asdictionarySelectList。,//POST:/Dinners/Edit/5publicActionResultEdit(intid,FormCollection{Dinnerdinner=dinnerRepository.GetDinner(id);try{}catchViewData["countries"]=newSelectList(PhoneValidator.AllCountries,return}}ViewData字典方法的優(yōu)點(diǎn)是非常快和容易實(shí)現(xiàn)。部分開發(fā)不喜歡使用基于字符串的字dictionaries圖模板中使用強(qiáng)類型時(shí),非強(qiáng)類型的ViewData字典也需要使用as操作符或類型轉(zhuǎn)換。View模板需要的動(dòng)態(tài)參數(shù)值或內(nèi)容。ControllerView模板去使用。這//publicDinner {get;privateset;}publicSelectListCountries{get;privateset;}//{Dinner=}}//GET:publicActionResultEdit(intid)Dinnerdinner=returnView(new} 一旦完成上述操作后,ViewModelDinnerFormViewModel對象<%=Html.ValidationMessage("Title","*")<label=Html.ValidationMessage("Country","*")//POST:publicActionResultEdit(intid,FormCollection{Dinnerdinner=dinnerRepository.GetDinner(id);try{}catchreturnView(new}}表框。下面是HTTP-GET的實(shí)現(xiàn)代碼://GET:/Dinners/CreatepublicActionResultCreate(){Dinnerdinner=newDinner()EventDate=returnView(new}//POST:{if(ModelState.IsValid){try{dinner.HostedBy=}catch}}returnView(new}ViewModel類(Custom-shapedViewModel對象模型可能完全不同于底層的業(yè)務(wù)模型對象(ModelObjectViewModel類有可能公開不同的屬性或者從多個(gè)Model對象中匯總的屬性。Controlleraction方法的數(shù)據(jù)。針對后一種情況,你可以讓Action方法根據(jù)表單提交回來的數(shù)據(jù)更新ViewModel對象,接著使用ViewModel實(shí)例來或者獲取時(shí)間的業(yè)務(wù)模型對象(ModelObject和View視圖中的用戶界面元素不一致,一個(gè)中介的定制ViewModel類就可以發(fā)揮作用了。PartialsMaster頁ASP.NETMVC的一個(gè)設(shè)計(jì)理念是“DoNotRepeatYourself”原則(DRY。DRY設(shè)計(jì)幫助排除重DRYNerdDinnerModel層實(shí)現(xiàn),在Controller的編輯和創(chuàng)建方法中均可執(zhí)行;我們也Edit、Details和Delete方法重用NotFound視圖模ViewView()Edit和CreateAction方法中重用DinnerFormViewModel類?;仡橢dit和Create視圖模板Edit.aspxCreate.aspx2個(gè)頁面包含相同的表單布局和輸入控件代碼。這Partial為了消除Edit.aspx和Create.aspx視圖模板的重復(fù),我們創(chuàng)建一個(gè)PartialView模板,命名為Add->View明將傳入DinnerFormViewModel類:在點(diǎn)擊Add按鈕后,VisualStudio自動(dòng)在\Views\Dinners 下創(chuàng)建一個(gè)新的DinnerForm.ascx視圖模<%using(Html.BeginForm()){=Html.ValidationMessage("Title","*")<label=Html.TextArea("Description",Model.Dinner.Description)<label<label=Html.TextBox("ContactPhone",Model.Dinner.ContactPhone)<%}接著,我們更新EditCreate視圖模板,調(diào)用DinnerFormpartial模板,消除表單的重復(fù)內(nèi)容。通過在視圖模板中調(diào)用Html.RenderPartial(“DinnerForm”)來實(shí)現(xiàn):<asp:ContentID="Content2"ContentPlaceHolderID="TitleContent"runat="server">HostaDinner<asp:ContentID="Create"ContentPlaceHolderID="MainContent"<h2>Hosta<%Html.RenderPartial("DinnerForm");Edit.aspx<asp:ContentID="Content2"ContentPlaceHolderID="TitleContent"runat="server">Edit:<%=Html.Encode(Model.Dinner.Title)%><asp:ContentID="Edit"ContentPlaceHolderID="MainContent"<h2>Edit<%Html.RenderPartial("DinnerForm");Html.RenderPartial()partial~Views/Dinners/DinnerForm.ascx。在上述代碼中,我們利用ASP

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論