畢業(yè)設(shè)計(jì)外文文獻(xiàn)-創(chuàng)建控制器_第1頁(yè)
畢業(yè)設(shè)計(jì)外文文獻(xiàn)-創(chuàng)建控制器_第2頁(yè)
畢業(yè)設(shè)計(jì)外文文獻(xiàn)-創(chuàng)建控制器_第3頁(yè)
畢業(yè)設(shè)計(jì)外文文獻(xiàn)-創(chuàng)建控制器_第4頁(yè)
畢業(yè)設(shè)計(jì)外文文獻(xiàn)-創(chuàng)建控制器_第5頁(yè)
已閱讀5頁(yè),還剩22頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

附錄A外文翻譯—原文部分文章來(lái)源:NateBarbettiniTheLittleASP.NETCoreBook[Z]ADDINCNKISM.UserStyleCreateacontrollerTherearealreadyafewcontrollersintheproject'sControllersdirectory,includingtheHomeControllerthatrendersthedefaultwelcomescreenyouseewhenyouvisithttp://localhost:5000.Youcanignorethesecontrollersfornow.Createanewcontrollerfortheto-dolistfunctionality,calledTodoController,andaddthefollowingcode:Controllers/TodoController.csusingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Threading.Tasks;usingMicrosoft.AspNetCore.Mvc;namespaceAspNetCoreTodo.Controllers{publicclassTodoController:Controller{//Actionsgohere}}Routesthatarehandledbycontrollersarecalledactions,andarerepresentedbymethodsinthecontrollerclass.Forexample,theHomeControllerincludesthreeactionmethods(Index,About,andContact)whicharemappedbyASP.NETCoretotheserouteURLs:localhost:5000/Home->Index()localhost:5000/Home/About->About()localhost:5000/Home/Contact->Contact()Thereareanumberofconventions(commonpatterns)usedbyASP.NETCore,suchasthepatternthatFooControllerbecomes/Foo,andtheIndexactionnamecanbeleftoutoftheURL.Youcancustomizethisbehaviorifyou'dlike,butfornow,we'llsticktothedefaultconventions.AddanewactioncalledIndextotheTodoController,replacingthe//Actionsgoherecomment:publicclassTodoController:Controller{publicIActionResultIndex(){//Getto-doitemsfromdatabase//Putitemsintoamodel//Renderviewusingthemodel}}Actionmethodscanreturnviews,JSONdata,orHTTPstatuscodeslike200OKand404NotFound.TheIActionResultreturntypegivesyoutheflexibilitytoreturnanyofthesefromtheaction.It'sabestpracticetokeepcontrollersaslightweightaspossible.Inthiscase,thecontrollerwillberesponsibleforgettingtheto-doitemsfromthedatabase,puttingthoseitemsintoamodeltheviewcanunderstand,andsendingtheviewbacktotheuser'sbrowser.Beforeyoucanwritetherestofthecontrollercode,youneedtocreateamodelandaview.CreatemodelsTherearetwoseparatemodelclassesthatneedtobecreated:amodelthatrepresentsato-doitemstoredinthedatabase(sometimescalledanentity),andthemodelthatwillbecombinedwithaview(theMVinMVC)andsentbacktotheuser'sbrowser.Becausebothofthemcanbereferredtoas"models",I'llrefertothelatterasaviewmodel.First,createaclasscalledTodoItemintheModelsdirectory:Models/TodoItem.csusingSystem;usingSystem.ComponentModel.DataAnnotations;namespaceAspNetCoreTodo.Models{publicclassTodoItem{publicGuidId{get;set;}publicboolIsDone{get;set;}[Required]publicstringTitle{get;set;}publicDateTimeOffset?DueAt{get;set;}}}Thisclassdefineswhatthedatabasewillneedtostoreforeachto-doitem:anID,atitleorname,whethertheitemiscomplete,andwhattheduedateis.Eachlinedefinesapropertyoftheclass:TheIdpropertyisaguid,oragloballyuniqueidentifier.Guids(orGUIDs)arelongstringsoflettersandnumbers,like43ec09f2-7f70-4f4b-9559-65011d5781bb.Becauseguidsarerandomandareextremelyunlikelytobeaccidentallyduplicated,theyarecommonlyusedasuniqueIDs.Youcouldalsouseanumber(integer)asadatabaseentityID,butyou'dneedtoconfigureyourdatabasetoalwaysincrementthenumberwhennewrowsareaddedtothedatabase.Guidsaregeneratedrandomly,soyoudon'thavetoworryaboutauto-incrementing.TheIsDonepropertyisaboolean(true/falsevalue).Bydefault,itwillbefalseforallnewitems.Lateryou'llusewritecodetoswitchthispropertytotruewhentheuserclicksanitem'scheckboxintheview.TheTitlepropertyisastring(textvalue).Thiswillholdthenameordescriptionoftheto-doitem.The[Required]attributetellsASP.NETCorethatthisstringcan'tbenullorempty.TheDueAtpropertyisaDateTimeOffset,whichisaC#typethatstoresadate/timestampalongwithatimezoneoffsetfromUTC.Storingthedate,time,andtimezoneoffsettogethermakesiteasytorenderdatesaccuratelyonsystemsindifferenttimezones.Noticethe?questionmarkaftertheDateTimeOffsettype?ThatmarkstheDueAtpropertyasnullable,oroptional.Ifthe?wasn'tincluded,everyto-doitemwouldneedtohaveaduedate.TheIdandIsDonepropertiesaren'tmarkedasnullable,sotheyarerequiredandwillalwayshaveavalue(oradefaultvalue).StringsinC#arealwaysnullable,sothere'snoneedtomarktheTitlepropertyasnullable.C#stringscanbenull,empty,orcontaintext.Eachpropertyisfollowedbyget;set;,whichisashorthandwayofsayingthepropertyisread/write(or,moretechnically,ithasagetterandsettermethods).Atthispoint,itdoesn'tmatterwhattheunderlyingdatabasetechnologyis.ItcouldbeSQLServer,MySQL,MongoDB,Redis,orsomethingmoreexotic.ThismodeldefineswhatthedatabaseroworentrywilllooklikeinC#soyoudon'thavetoworryaboutthelow-leveldatabasestuffinyourcode.Thissimplestyleofmodelissometimescalleda"plainoldC#object"orPOCO.TheviewmodelOften,themodel(entity)youstoreinthedatabaseissimilarbutnotexactlythesameasthemodelyouwanttouseinMVC(theviewmodel).Inthiscase,theTodoItemmodelrepresentsasingleiteminthedatabase,buttheviewmightneedtodisplaytwo,ten,orahundredto-doitems(dependingonhowbadlytheuserisprocrastinating).Becauseofthis,theviewmodelshouldbeaseparateclassthatholdsanarrayofTodoItems:Models/TodoViewModel.csnamespaceAspNetCoreTodo.Models{publicclassTodoViewModel{publicTodoItem[]Items{get;set;}}}Nowthatyouhavesomemodels,it'stimetocreateaviewthatwilltakeaTodoViewModelandrendertherightHTMLtoshowtheusertheirto-dolist.CreateaviewViewsinASP.NETCorearebuiltusingtheRazortemplatinglanguage,whichcombinesHTMLandC#code.(Ifyou'vewrittenpagesusingHandlebarsmoustaches,ERBinRubyonRails,orThymeleafinJava,you'vealreadygotthebasicidea.)MostviewcodeisjustHTML,withtheoccasionalC#statementaddedintopulldataoutoftheviewmodelandturnitintotextorHTML.TheC#statementsareprefixedwiththe@symbol.TheviewrenderedbytheIndexactionoftheTodoControllerneedstotakethedataintheviewmodel(asequenceofto-doitems)anddisplayitinanicetablefortheuser.Byconvention,viewsareplacedintheViewsdirectory,inasubdirectorycorrespondingtothecontrollername.Thefilenameoftheviewisthenameoftheactionwitha.cshtmlextension.CreateaTododirectoryinsidetheViewsdirectory,andaddthisfile:Views/Todo/Index.cshtml@modelTodoViewModel@{ViewData["Title"]="Manageyourtodolist";}<divclass="panelpanel-defaulttodo-panel"><divclass="panel-heading">@ViewData["Title"]</div><tableclass="tabletable-hover"><thead><tr><td>✔</td><td>Item</td><td>Due</td></tr></thead>@foreach(variteminModel.Items){<tr><td><inputtype="checkbox"class="done-checkbox"></td><td>@item.Title</td><td>@item.DueAt</td></tr>}</table><divclass="panel-footeradd-item-form"><!--TODO:Additemform--></div></div>Attheverytopofthefile,the@modeldirectivetellsRazorwhichmodeltoexpectthisviewtobeboundto.ThemodelisaccessedthroughtheModelproperty.Assumingthereareanyto-doitemsinModel.Items,theforeachstatementwillloopovereachto-doitemandrenderatablerow(<tr>element)containingtheitem'snameandduedate.Acheckboxisalsorenderedthatwilllettheusermarktheitemascomplete.ThelayoutfileYoumightbewonderingwheretherestoftheHTMLis:whataboutthe<body>tag,ortheheaderandfooterofthepage?ASP.NETCoreusesalayoutviewthatdefinesthebasestructurethateveryotherviewisrenderedinsideof.It'sstoredinViews/Shared/_Layout.cshtml.ThedefaultASP.NETCoretemplateincludesBootstrapandjQueryinthislayoutfile,soyoucanquicklycreateawebapplication.Ofcourse,youcanuseyourownCSSandJavaScriptlibrariesifyou'dlike.CustomizingthestylesheetThedefaulttemplatealsoincludesastylesheetwithsomebasicCSSrules.Thestylesheetisstoredinthewwwroot/cssdirectory.AddafewnewCSSstylerulestothebottomofthesite.cssfile:wwwroot/css/site.cssdiv.todo-panel{margin-top:15px;}tabletr.done{text-decoration:line-through;color:#888;}YoucanuseCSSruleslikethesetocompletelycustomizehowyourpageslookandfeel.ASP.NETCoreandRazorcandomuchmore,suchaspartialviewsandserver-renderedviewcomponents,butasimplelayoutandviewisallyouneedfornow.TheofficialASP.NETCoredocumentation(at)containsanumberofexamplesifyou'dliketolearnmore.AddaserviceclassYou'vecreatedamodel,aview,andacontroller.Beforeyouusethemodelandviewinthecontroller,youalsoneedtowritecodethatwillgettheuser'sto-doitemsfromadatabase.Youcouldwritethisdatabasecodedirectlyinthecontroller,butit'sabetterpracticetokeepyourcodeseparate.Why?Inabig,real-worldapplication,you'llhavetojugglemanyconcerns:Renderingviewsandhandlingincomingdata:thisiswhatyourcontrolleralreadydoes.Performingbusinesslogic,orcodeandlogicthat'srelatedtothepurposeand"business"ofyourapplication.Inato-dolistapplication,businesslogicmeansdecisionslikesettingadefaultduedateonnewtasks,oronlydisplayingtasksthatareincomplete.Otherexamplesofbusinesslogicincludecalculatingatotalcostbasedonproductpricesandtaxrates,orcheckingwhetheraplayerhasenoughpointstolevelupinagame.Savingandretrievingitemsfromadatabase.Again,it'spossibletodoallofthesethingsinasingle,massivecontroller,butthatquicklybecomestoohardtomanageandtest.Instead,it'scommontoseeapplicationssplitupintotwo,three,ormore"layers"ortiersthateachhandleone(andonlyone)concern.Thishelpskeepthecontrollersassimpleaspossible,andmakesiteasiertotestandchangethebusinesslogicanddatabasecodelater.Separatingyourapplicationthiswayissometimescalledamulti-tierorn-tierarchitecture.Insomecases,thetiers(layers)areisolatedincompletelyseparateprojects,butothertimesitjustreferstohowtheclassesareorganizedandused.Theimportantthingisthinkingabouthowtosplityourapplicationintomanageablepieces,andavoidhavingcontrollersorbloatedclassesthattrytodoeverything.Forthisproject,you'llusetwoapplicationlayers:apresentationlayermadeupofthecontrollersandviewsthatinteractwiththeuser,andaservicelayerthatcontainsbusinesslogicanddatabasecode.Thepresentationlayeralreadyexists,sothenextstepistobuildaservicethathandlesto-dobusinesslogicandsavesto-doitemstoadatabase.Mostlargerprojectsusea3-tierarchitecture:apresentationlayer,aservicelogiclayer,andadatarepositorylayer.Arepositoryisaclassthat'sonlyfocusedondatabasecode(nobusinesslogic).Inthisapplication,you'llcombinetheseintoasingleservicelayerforsimplicity,butfeelfreetoexperimentwithdifferentwaysofarchitectingthecode.CreateaninterfaceTheC#languageincludestheconceptofinterfaces,wherethedefinitionofanobject'smethodsandpropertiesisseparatefromtheclassthatactuallycontainsthecodeforthosemethodsandproperties.Interfacesmakeiteasytokeepyourclassesdecoupledandeasytotest,asyou'llseehere(andlaterintheAutomatedtestingchapter).You'lluseaninterfacetorepresenttheservicethatcaninteractwithto-doitemsinthedatabase.Byconvention,interfacesareprefixedwith"I".CreateanewfileintheServicesdirectory:Services/ITodoItemService.csusingSystem;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingAspNetCoreTodo.Models;namespaceAspNetCoreTodo.Services{publicinterfaceITodoItemService{Task<TodoItem[]>GetIncompleteItemsAsync();}}NotethatthenamespaceofthisfileisAspNetCoreTodo.Services.Namespacesareawaytoorganize.NETcodefiles,andit'scustomaryforthenamespacetofollowthedirectorythefileisstoredin(AspNetCoreTodo.ServicesforfilesintheServicesdirectory,andsoon).Becausethisfile(intheAspNetCoreTodo.Servicesnamespace)referencestheTodoItemclass(intheAspNetCoreTodo.Modelsnamespace),itneedstoincludeausingstatementatthetopofthefiletoimportthatnamespace.Withouttheusingstatement,you'llseeanerrorlike:Thetypeornamespacename'TodoItem'couldnotbefound(areyoumissingausingdirectiveoranassemblyreference?)Sincethisisaninterface,thereisn'tanyactualcodehere,justthedefinition(ormethodsignature)oftheGetIncompleteItemsAsyncmethod.ThismethodrequiresnoparametersandreturnsaTask<TodoItem[]>.Ifthissyntaxlooksconfusing,think:"aTaskthatcontainsanarrayofTodoItems".TheTasktypeissimilartoafutureorapromise,andit'susedherebecausethismethodwillbeasynchronous.Inotherwords,themethodmaynotbeabletoreturnthelistofto-doitemsrightawaybecauseitneedstogotalktothedatabasefirst.(Moreonthislater.)CreatetheserviceclassNowthattheinterfaceisdefined,you'rereadytocreatetheactualserviceclass.I'llcoverdatabasecodeindepthintheUseadatabasechapter,sofornowyou'lljustfakeitandalwaysreturntwohard-codeditems:Services/FakeTodoItemService.csusingSystem;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;usingAspNetCoreTodo.Models;namespaceAspNetCoreTodo.Services{publicclassFakeTodoItemService:ITodoItemService{publicTask<TodoItem[]>GetIncompleteItemsAsync(){varitem1=newTodoItem{Title="LearnASP.NETCore",DueAt=DateTimeOffset.Now.AddDays(1)};varitem2=newTodoItem{Title="Buildawesomeapps",DueAt=DateTimeOffset.Now.AddDays(2)};returnTask.FromResult(new[]{item1,item2});}}}ThisFakeTodoItemServiceimplementstheITodoItemServiceinterfacebutalwaysreturnsthesamearrayoftwoTodoItems.You'llusethistotestthecontrollerandview,andthenaddrealdatabasecodeinUseadatabase.UsedependencyinjectionBackintheTodoController,addsomecodetoworkwiththeITodoItemService:publicclassTodoController:Controller{privatereadonlyITodoItemService_todoItemService;publicTodoController(ITodoItemServicetodoItemService){_todoItemService=todoItemService;}publicIActionResultIndex(){//Getto-doitemsfromdatabase//Putitemsintoamodel//Passtheviewtoamodelandrender}}SinceITodoItemServiceisintheServicesnamespace,you'llalsoneedtoaddausingstatementatthetop:usingAspNetCoreTodo.Services;ThefirstlineoftheclassdeclaresaprivatevariabletoholdareferencetotheITodoItemService.ThisvariableletsyouusetheservicefromtheIndexactionmethodlater(you'llseehowinaminute).ThepublicTodoController(ITodoItemServicetodoItemService)linedefinesaconstructorfortheclass.Theconstructorisaspecialmethodthatiscalledwhenyouwanttocreateanewinstanceofaclass(theTodoControllerclass,inthiscase).ByaddinganITodoItemServiceparametertotheconstructor,you'vedeclaredthatinordertocreatetheTodoController,you'llneedtoprovideanobjectthatmatchestheITodoItemServiceinterface.Interfacesareawesomebecausetheyhelpdecouple(separate)thelogicofyourapplication.SincethecontrollerdependsontheITodoItemServiceinterface,andnotonanyspecificclass,itdoesn'tknoworcarewhichclassit'sactuallygiven.ItcouldbetheFakeTodoItemService,adifferentonethattalkstoalivedatabase,orsomethingelse!Aslongasitmatchestheinterface,thecontrollercanuseit.Thismakesitreallyeasytotestpartsofyourapplicationseparately.I'llcovertestingindetailintheAutomatedtestingchapter.NowyoucanfinallyusetheITodoItemService(viatheprivatevariableyoudeclared)inyouractionmethodtogetto-doitemsfromtheservicelayer:publicIActionResultIndex(){varitems=await_todoItemService.GetIncompleteItemsAsync();//...}RememberthattheGetIncompleteItemsAsyncmethodreturnedaTask<TodoItem[]>?ReturningaTaskmeansthatthemethodwon'tnecessarilyhavearesultrightaway,butyoucanusetheawaitkeywordtomakesureyourcodewaitsuntiltheresultisreadybeforecontinuingon.TheTaskpatterniscommonwhenyourcodecallsouttoadatabaseoranAPIservice,becauseitwon'tbeabletoreturnarealresultuntilthedatabase(ornetwork)responds.Ifyou'veusedpromisesorcallbacksinJavaScriptorotherlanguages,Taskisthesameidea:thepromisethattherewillbearesult-sometimeinthefuture.Ifyou'vehadtodealwith"callbackhell"inolderJavaScriptcode,you'reinluck.Dealingwithasynchronouscodein.NETismucheasierthankstothemagicoftheawaitkeyword!awaitletsyourcodepauseonanasyncoperation,andthenpickupwhereitleftoffwhentheunderlyingdatabaseornetworkrequestfinishes.Inthemeantime,yourapplicationisn'tblocked,becauseitcanprocessotherrequestsasneeded.Thispatternissimplebuttakesalittlegettingusedto,sodon'tworryifthisdoesn'tmakesenserightaway.Justkeepfollowingalong!TheonlycatchisthatyouneedtoupdatetheIndexmethodsignaturetoreturnaTask<IActionResult>insteadofjustIActionResult,andmarkitasasync:publicasyncTask<IActionResult>Index(){varitems=await_todoItemService.GetIncompleteItemsAsync();//Putitemsintoamodel//Passtheviewtoamodelandrender}You'realmostthere!You'vemadetheTodoControllerdependontheITodoItemServiceinterface,butyouhaven'tyettoldASP.NETCorethatyouwanttheFakeTodoItemServicetobetheactualservicethat'susedunderthehood.ItmightseemobviousrightnowsinceyouonlyhaveoneclassthatimplementsITodoItemService,butlateryou'llhavemultipleclassesthatimplementthesameinterface,sobeingexplicitisnecessary.Declaring(or"wiringup")whichconcreteclasstouseforeachinterfaceisdoneintheConfigureServicesmethodoftheStartupclass.Rightnow,itlookssomethinglikethis:Startup.cspublicvoidConfigureServices(IServiceCollectionservices){//(...somecode)services.AddMvc();}ThejoboftheConfigureServicesmethodisaddingthingstotheservicecontainer,orthecollectionofservicesthatASP.NETCoreknowsabout.Theservices.AddMvclineaddstheservicesthattheinternalASP.NETCoresystemsneed(asanexperiment,trycommentingoutthisline).AnyotherservicesyouwanttouseinyourapplicationmustbeaddedtotheservicecontainerhereinConfigureServices.AddthefollowinglineanywhereinsidetheConfigureServicesmethod:services.AddSingleton<ITodoItemService,FakeTodoItemService>();ThislinetellsASP.NETCoretousetheFakeTodoItemServicewhenevertheITodoItemServiceinterfaceisrequestedinaconstructor(oranywhereelse).AddSingletonaddsyourservicetotheservicecontainerasasingleton.ThismeansthatonlyonecopyoftheFakeTodoItemServiceiscreated,andit'sreusedwhenevertheserviceisrequested.Later,whenyouwriteadifferentserviceclassthattalkstoadatabase,you'lluseadifferentapproach(calledscoped)instead.I'llexplainwhyintheUseadatabasechapter.That'sit!WhenarequestcomesinandisroutedtotheTodoController,ASP.NETCorewilllookattheavailableservicesandautomaticallysupplytheFakeTodoItemServicewhenthecontrollerasksforanITodoItemService.Becausetheservicesare"injected"fromtheservicecontainer,thispatterniscalleddependencyinjection.FinishthecontrollerThelaststepistofinishthecontrollercode.Thecontrollernowhasalistofto-doitemsfromtheservicelayer,anditneedstoputthoseitemsintoaTodoViewModelandbindthatmodeltotheviewyoucreatedearlier:Controllers/TodoController.cspublicasyncTask<IActionResult>Index(){varitems=await_todoItemService.GetIncompleteItemsAsync();varmodel=newTodoViewModel(){Items=items};returnView(model);}Ifyouhaven'talready,makesuretheseusingstatementsareatthetopofthefile:usingAspNetCoreTodo.Services;usingAspNetCoreTodo.Models;Ifyou'reusingVisualStudioorVisualStudioCode,theeditorwillsuggesttheseusingstatementswhenyouputyourcursoronaredsquigglyline.TestitoutTostarttheapplication,pressF5(ifyou'reusingVisualStudioorVisualStudioCode),orjusttypedotnetrunintheterminal.Ifthecodecompileswithouterrors,theserverwillstartuponport5000bydefault.Ifyourwebbrowserdidn'topenautomatically,openitandnavigatetohttp://localhost:5000/todo.You'llseetheviewyoucreated,withthedatapulledfromyourfakedatabase(fornow).Althoughit'spossibletogodirectlytohttp://localhost:5000/todo,itwouldbenicertoaddanitemcalledMyto-dostothenavbar.Todothis,youcaneditthesharedlayoutfile.UpdatethelayoutThelayoutfileatViews/Shared/_Layout.cshtmlcontainsthe"base"HTMLforeachview.Thisincludesthenavbar,whichisrenderedatthetopofeachpage.Toaddanewitemtothenavbar,findtheHTMLcodefortheexistingnavbaritems:Views/Shared/_Layout.cshtml<ulclass="navnavbar-nav"><li><aasp-area=""asp-controller="Home"asp-action="Index">Home</a></li><li><aasp-area=""asp-controller="Home"asp-action="About">About</a></li><li><aasp-area=""asp-controller="Home"asp-action="Contact">Contact</a></li></ul>AddyourownitemthatpointstotheTodocontrollerinsteadofHome:<li><aasp-controller="Todo"asp-action="Index">Myto-dos</a></li>Theasp-controllerandasp-actionattributesonthe<a>elementarecalledtaghelpers.Beforetheviewisrendered,ASP.NETCorereplacesthesetaghelperswithrealHTMLattributes.Inthiscase,aURLtothe/Todo/Indexrouteisgeneratedandaddedtothe<a>elementasanhrefattribute.Thismeansyoudon'thavetohard-codetheroutetotheTodoController.Instead,ASP.NETCoregeneratesitforyouautomatically.Ifyou'veusedRazorinASP.NET4.x,you'llnoticesomesyntaxchanges.Insteadofusing@Html.ActionLink()togeneratealinktoanaction,taghelpersarenowtherecommendedwaytocreatelinksinyourviews.Taghelpersareusefulforforms,too(you'llseewhyinalaterchapter).Youcanlearnaboutothertaghelpersinthedocumentationat.附錄B外文翻譯—譯文部分創(chuàng)建控制器在項(xiàng)目的Controllers目錄里,已經(jīng)預(yù)置了幾個(gè)控制器,其中有渲染默認(rèn)歡迎頁(yè)的HomeController,就是你訪問(wèn)http://localhost:5000看到的那個(gè)頁(yè)面。暫時(shí)不用管這些控制器。給待辦清單功能創(chuàng)建一個(gè)新的控制器,取名叫TodoController,并添加如下代碼:Controllers/TodoController.csusingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Threading.Tasks;usingMicrosoft.AspNetCore.Mvc;namespaceAspNetCoreTodo.Controllers{publicclassTodoController:Controller{//在這里添加Actions}}由控制器本身處理的路由叫action,在控制器類里用方法表示。比如,HomeController包含三個(gè)action方法(Index,About,和Contact),由ASP.NETCore分別映射到如下的URL:localhost:5000/Home->Index()localhost:5000/Home/About->About()localhost:5000/Home/Contact->Contact()ASP.NETCore中有幾個(gè)慣例(常見(jiàn)的模式),比如這個(gè)FooController映射到/Foo的模式,還有Index的action名可以在URL里省略。如果你有需要,可以自定義這些行為,不過(guò)就目前的情況,讓我們暫且遵循這些慣例。在TodoController里,添加一個(gè)名為Index的action,把那句//Actionsgohere注釋替換掉:publicclassTodoController:Controller{publicIActionResultIndex(){//從數(shù)據(jù)庫(kù)獲取to-do條目//把條目置于model中//使用model渲染視圖}}一個(gè)action方法可以返回視圖、JSON數(shù)據(jù),或者200OK和404NotFound之類的狀態(tài)碼。返回類型IActionResult給了你足夠的靈活性,以返回上面提到的任意一個(gè)。使控制器盡可能保持輕量化,是一個(gè)良好的習(xí)慣。在當(dāng)前的情形里,這個(gè)控制器應(yīng)該僅僅完成這些事情:從數(shù)據(jù)庫(kù)取出待辦事項(xiàng)的記錄,把這些事項(xiàng)包裝在一個(gè)可用于視圖的模型中,并把這個(gè)視圖發(fā)送到用戶的瀏覽器。繼續(xù)編碼這個(gè)控制器之前,你需要?jiǎng)?chuàng)建模型和視圖。創(chuàng)建模型我們需要?jiǎng)?chuàng)建兩個(gè)獨(dú)立的模型類:一個(gè)模型表示保存在數(shù)據(jù)庫(kù)里的條目(有時(shí)候也稱為一個(gè)記錄(entity)),另一個(gè)模型將與視圖結(jié)合(MVC里的MV)發(fā)送到用戶的瀏覽器。因?yàn)樗麄兌伎梢员环Q為模型,我將稱后者為視圖模型(viewmodel)。首先,在Models目錄下,創(chuàng)建一個(gè)名為TodoItem的類:Models/TodoItem.csusingSystem;namespaceAspNetCoreTodo.Models{publicclassTodoItem{publicGuidId{get;set;}publicboolIsDone{get;set;}publicstringTitle{get;set;}publicDateTimeOffset?DueAt{get;set;}}}這個(gè)類定義了每個(gè)待辦事項(xiàng)都要保存的內(nèi)容:一個(gè)ID、一個(gè)標(biāo)題或者名稱、該事項(xiàng)是否已經(jīng)完成,以及截至日期是什么時(shí)候。每行定義了這個(gè)類的一個(gè)屬性:Id屬性是一個(gè)guid,或者說(shuō)是全局(globally)唯一(unique)標(biāo)識(shí)符(identifier).Guid(或者GUID)是一個(gè)由字母和數(shù)字組成的長(zhǎng)長(zhǎng)的字符串,看起來(lái)是這樣的43ec09f2-7f70-4f4b-9559-65011d5781bb。因?yàn)間uid是隨機(jī)的,并極少會(huì)有重復(fù)值,所以常被用作唯一標(biāo)識(shí)。你也可以用數(shù)字(整形integer)作為數(shù)據(jù)庫(kù)記錄的標(biāo)識(shí),但你需要在數(shù)據(jù)庫(kù)里配置,以便這個(gè)數(shù)字在添加新條目的時(shí)候始終增長(zhǎng)。因?yàn)镚uid是隨機(jī)生產(chǎn)的,所以就你不必再擔(dān)心這個(gè)自增的問(wèn)題了。IsDone屬性是一個(gè)布爾值(值為true/false)。默認(rèn)情況下,所有新建條目的該值為false。你后面會(huì)編寫代碼,在用戶在視圖里點(diǎn)擊某個(gè)條目的復(fù)選框時(shí),修改這個(gè)屬性為true。Title屬性是一個(gè)字符串,用于保存待辦事項(xiàng)的名稱或者簡(jiǎn)述。DueAt屬性是一個(gè)DateTimeOffset,C#用于這種類型保存一個(gè)日期/時(shí)間的戳記和一個(gè)與UTC偏移量表示的時(shí)區(qū)。把時(shí)期、時(shí)間和時(shí)區(qū)一起保存,有助于在不同時(shí)區(qū)的系統(tǒng)上準(zhǔn)確地顯示時(shí)間。看到DateTimeOffset類型后面那個(gè)問(wèn)號(hào)?了嗎?它表示DueAt屬性可空(nullable),或者說(shuō)是可選的。如果不加這個(gè)?,每個(gè)待辦事項(xiàng)都必須帶有一個(gè)截止日期。Id和IsDone屬性沒(méi)有標(biāo)記為可空,所以是必須的,并可以確保始終有值(或者是一個(gè)缺省值)。C#里的字符串總是可空的,所以沒(méi)必要給Title屬性添加可空標(biāo)記。C#字符串可以沒(méi)有值,也可以是空白字符串或者包含任意文本。每個(gè)屬性后面都跟著get;set;,這是個(gè)簡(jiǎn)寫,表示該屬性可讀/可寫(read/write)(或者,更確切地說(shuō),它有g(shù)etter和setter方法各一個(gè))?,F(xiàn)在,暫且不必關(guān)心底層數(shù)據(jù)庫(kù)采用的是哪種實(shí)現(xiàn)。它可以是SQLServer,MySQL,MongoDB,Redis,或者什么其它稀奇古怪的玩意兒。這個(gè)模型定義了數(shù)據(jù)庫(kù)里的行或者記錄在C#里看起來(lái)是什么樣的,所以你無(wú)須在代碼層面擔(dān)心數(shù)據(jù)庫(kù)層面的東西。這種模型簡(jiǎn)單的風(fēng)格被稱為“樸實(shí)可愛(ài)的C#對(duì)象(plainoldC#object)”或者POCO。視圖模型通常,你保存在數(shù)據(jù)庫(kù)里的模型(實(shí)體),跟你在MVC里用的模型(視圖模型)非常相似,但又不盡相同。在現(xiàn)在的情形下,TodoItem模型代表單一的一個(gè)數(shù)據(jù)庫(kù)里的條目,而視圖則需要展示兩個(gè)、十個(gè),甚至是一百個(gè)待辦事項(xiàng)(取決于用戶拖延癥的病情輕重)。因此,視圖模型應(yīng)該是一個(gè)獨(dú)立的類,里面包含著一個(gè)TodoItem的數(shù)組:Models/TodoViewModel.csnamespaceAspNetCoreTodo.Models{publicclassTodoViewModel{publicTodoItem[]Items{get;set;}}}好了,現(xiàn)在模型也有了,是時(shí)候創(chuàng)建一個(gè)接收TodoViewModel并以HTML向用戶展示待辦事項(xiàng)列表的視圖了。創(chuàng)建視圖ASP.NETCore里的視圖使用Razor模板語(yǔ)言編寫,這種模板語(yǔ)言混合了HTML和C#的代碼。(如果你在JavaScript下用Jade、Pug或者Handlebarsmoustaches,在RubyonRails下用ERB,在Java下用Thymeleaf寫過(guò)頁(yè)面,那你就已經(jīng)了解其基本概念了.)絕大多數(shù)視圖代碼就是HTML,偶爾摻雜一點(diǎn)C#語(yǔ)句,用以從視圖模型里抽取數(shù)據(jù)并轉(zhuǎn)換為文本或者HTML。這些C#語(yǔ)句以符號(hào)@作為前綴。由TodoController中的actionIndex生成的視圖,需要從視圖模型(一個(gè)待辦事項(xiàng)的數(shù)組)獲取數(shù)據(jù),并用一個(gè)適當(dāng)?shù)谋砀裾故窘o用戶。按規(guī)定,視圖要置于Views目錄里,在一個(gè)與所屬控制器同名的子目錄下。視圖文件的文件名就是action的名字加上一個(gè).cshtml擴(kuò)展名。Views/Todo/Index.cshtml@modelTodoViewModel@{ViewDa

溫馨提示

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

評(píng)論

0/150

提交評(píng)論