【转】不用到处找资料,2天掌握Asp.net Mvc 3
【http://www.cnblogs.com/by1990/archive/2011/02/04/1949146.html】
最快的学习方法:找到官方的教程,最好是类似Msdn演练或者冠以Step By Step的,跟着做一遍,做的过程中可以拷贝少量教程中的代码,确保每个步骤、每行代码含义都能够明白,中途随手记录一下,每个步骤完成后停下来在脑子里回顾一下。教程做完,基本上该掌握的也就掌握了,当然,也有人简单的了解一些后就希望在小型的项目中开始使用,忽略了学习过程,这实际上更为浪费时间。先系统的学习一下,将会大幅减少开发过程中碰到问题解决问题所需要的时间。
Asp.net Mvc 3当然也不会例外,官网上两篇教程,看看ASP.NET MVC Music Store就行。已经有人翻译为中文版,不过建议还是看原文,翻译质量不高,原文每篇课程下都有讨论。先简单浏览一下,大体上覆盖范围比较合适,16个小时以内应能够做完。以下是我本人实作过程中的零星笔记。
第一课 创建项目 开始时间2月4日14:00 预期30分钟 14:23结束。
这一课主要讲两个问题,项目要做什么:一个音乐商店,换句话说是卖唱片之类的网上商店。功能方面,网民可以按类别或按照演员是谁来查看唱片,加入购物车,并实现模拟的支付。管理员能够添加新的唱片。That's all,这基本上是做典型的小型网上商店的主要需求。
创建项目的过程很简单,注意这里创建的是一个“空的”Asp.net Mvc3的项目,创建完之后可以看看,除了Content目录下有网站的一些默认的样式和图片之外,神马都没有。之所以创建这样空的项目而不是使用项目模版,让VS帮助我们实现基本的首页、登录、注册、注销之类的功能,大约是为了让我们从最底层了解代码和编程方式。
这里要注意的要点只有一个:Asp.net Mvc的默认目录,这些目录下即使没有任何东西,也需要创建,一个Mvc应用会在Controller目录下寻找控制器、会在Views目录下寻找View,不需要在编程的时候写完整的路径。所以这是Asp.net Mvc开发Web应用的约定,简单的说,这些目录非有不可。
第二课 控制器 开始时间14:23 预期60分钟 15:06分结束 中断4分钟
这一课主要讲怎样为应用添加控制器、在浏览器中如何访问相应的控制器里的相关方法。
1、控制器是什么?实际上是Url,举例来说,http://localhost:1826/Home/Index,对应HomeController的Index方法,我们在浏览器中输入这个地址,则该方法会执行。看看自动生成的代码,这里一般是返回一个视图,本课则用一个返回字符串的方法取代,这样执行的时候,网页上就会显示这个字符串。当然,如果只输入http://localhost:1826/Home/,则默认的使用Index方法,如果连Home也省略掉输入http://localhost:1826,则默认的使用Home控制器。这些同样是约定,没什么道理可说,只是为了方便。
2、控制器的方法名称约定:只问方法名称,不问方法的参数和返回值。上面可以看到,系统生成的index是返回一个View,改成返回字符串的Index,运行时照样能够找到这个方法。
3、方法的参数:另外一个控制器StoreController包括三个方法,分别是Index、Browse和Detail,在浏览器中输入http://localhost:1826/Store/Browse?Genre=Disco,为StoreController的Browse方法提供了一个参数:Disco。在浏览器中输入http://localhost:1826/Store/Details/5,则为Details方法的Id提供了一个参数5.不过,你若是http://localhost:1826/Store/Browse/Disco,这样参数是不能传到的,原因见4.
4、返回字符串的时候,Browse方法使用了HttpUtility.HtmlEncode,防止js注入攻击。http://localhost:1826/Store/Browse/Disco这种情况下将不能获得参数。
string message = HttpUtility.HtmlEncode("Store.Browse, Genre = " + genre);
所以总结一下:控制器和Action、参数三者,是构成网站Url的三个部分,其中若不提供控制器名称,则默认的使用HomeController,不提供方法名称则默认的使用Index方法。参数有两种形式,当接受的参数为字符串的时候,要使用HttpUtility.HtmlEncode防范Js注入攻击。
这里,可以看看本课最后的总结。
第三课 View和ViewModels 15:15分开始 预期100分钟 16.40结束
本课讲解如何添加视图和ViewModels
1、视图和控制器的关系:控制器一般推送一个视图给浏览器。前面的Controller中,我们每个Action返回一个字符串,浏览器显示该字符串。但我们最终仍然还是要自行的生成Html,这就是View的任务。我们并非是在手写htm,而是夹杂着Razor脚本,用来访问服务器资源。从这个角度来说,博客园的DUDU版主提及的没有必要使用Mvc,其理由是站不住脚的。
2、如何添加控制器:在Controller目录,右键,添加控制器即可。
3、如何添加View:我们先将Home的Index方法恢复原状,即返回ActionResult,同时Return View(),然后在这个方法的代码上,右键,添加视图。一个名为Index.cshtml的视图就会创建。
请注意,这里Return View()的View构造方法有多个重载,使用默认的构造方法,将导致该控制器在Views\Home\下面寻找与Action也就是这个方法同名的视图,也就是我们刚刚生成的Index.cshtml。这就是前面提到的目录路径和文件名的约定,只是约定而已,目的是让我们的编程更简单些。
index.cshtml这样的文件和以前的Aspx没什么不同,是夹杂脚本的文件,服务器未来将依据其得到htm、css和js,浏览器呈现。
生成的视图代码很简单,前面的三行是Razor语法的说明,用来指定该视图在浏览器里显示时的标题。后面一行则简单的htm语法,显示一行文本。
4、修改_Layout.cshtml ,这个是站点公用的模版。在Views\Shared目录下面。实际上要关注的是,使用@RenderBody(),来呈现各个视图。我们需要在网站的顶部显示两个链接,一个到首页一个到Store,那么,先直接在Body这里Render之前加入
5、调整样式:直接从http://mvcmusicstore.codeplex.com下载MvcMusicStore-Assets.zip,打开压缩包,将包里的Content目录拖放到解决方案中。这里只是覆盖了site.css并加入了几个图标,样式已经由这个项目组先制作好了。现在的站点看起来像模像样的了。
6、使用Model传送信息给View:先在Model里增加两个类,Genre用来表达商品的类型,现在我们只需要一个Name属性。Album类,包括包括一个标题和它属于那个类型,两个属性。
然后,编译这个项目,让开发环境知道增加了这两个类,我们再为StoreController的三个方法增加视图。
7、最后,Store的index视图必须能够转到Browse视图,这个通过修改index的Views很容易做到。
到目前为止,我们在顶部有两个链接,其中Store的index方法包含一个类型列表,点击这个列表中的每个成员,都进入相应的Browse页面。
总结一下:如何为控制器的某个Action创建视图?如何为视图指定Models?如何在视图中呈现某个对象或某个集合?
第四课 Models和数据访问 22:08分开始 预期30分钟 23:35分结束,中断16+6+3分钟。其中数据库问题浪费了一点时间。
这一课的主题很简单,如何访问数据库。
准备工作:
1、创建数据库:当然,数据库包括示例数据,已经准备好,在我们上一课中下载的MvcMusicStore-Assets.zip文件里。我们找到Data目录下的MvcMusicStore-Create.sql,使用它创建数据库。
2、安装EFCodeFirst包:安装Asp.net mvc3同时也安装了Nuget,可以使用Nuget找到EFCodeFirst包,并安装。通过这个包,我们可以先写代码然后再生成数据库,当然,现在我们使用的是已存在的数据库。另外一篇向导讲解了如何先写实体类再生成数据库。
接下来:
1、在Web.Config里添加连接字符串:这个是常规工作,和教程里不同,是用Sql server,所以连接字符串为
<configuration>
<connectionStrings>
<add name="MusicStoreEntities"
connectionString="Data Source=.;Initial Catalog=MvcMusicStore;Integrated Security=True"
providerName="System.Data.SqlServer" />
</connectionStrings>
2、在Models中添加一个Context类MusicStoreEntities.cs,这个类继承于DbContext,包含两个DbSet属性分别处理前面的Albums和Genres表格。
只需要这个类无需其他配置,则我们能够正常的处理数据访问操作了。
3、修改前面的Album和Genre类,前面只是简单的描述,现在这两个类的属性要和表格对应起来。
4、然后在StoreController中增加一个成员MusicStoreEntities storeDB = new MusicStoreEntities(); 用来访问数据库
5、现在试试,修改Store的index方法,返回数据库中的Genres表格的内容:
var genres = storeDB.Genres.ToList();
return View(genres);
遇到问题:数据库访问异常。找到原因MvcMusicStore-Assets.zip中的脚本文件不对,直接附加里面的b数据库即可。
6、其它的也就简单了,修改Store的Browse、Details改从数据库获取数据,当然,也要修改Browse的视图
这样,我们现在在首页点击Store,能看到类别列表(Index)。点击任一类别,能看到该类别的所有商品了(Browse)。
总结:这一节讲解我们的Controller如何透过Modes从数据库中获取主从数据,当然,用Ado.net等方式也是相同的,和上一课没什么不同,区别是数据来源不一而已。
第五课 CRUD操作 11:08分开始 预期60分钟 13:19分结束 中断12+9分钟
本课讲解:如何增加新的记录、修改记录和删除记录
1、首先要创建一个StoreManagerController,当然,此时要勾上“为创建、更新、删除和详细信息添加操作方法”。由于详细信息这个对我们没用,可删除该方法。
2、此时要加入唱片的“演员”信息,这包括创建一个演员类Artist,为每张唱片增加Artist属性,同时在前面的Context中增加一个Artist的DbSet,当然我们也要为StoreController增加一个MusicStoreEntities对象用于访问数据。
数据库已经建好,所以只要Context中的DbSet名称与表格名相同、属性名称与字段名相同,我们不需要做其他的事情,根据命名约定EF会自动处理这些。我们现在为唱片类增加了一个Genre对象、一个Artist对象,表示该唱片属于哪个类别和演员是谁,注意这两个使用Vitual修饰的属性,它不是对应表格中实际的字段。我们也为该类增加了一个链接字段,用于存放唱片的图片的链接。
3、实现Index方法,并创建视图,这个要显示各个唱片,所以Model选择Album类,视图要选择List,VS将帮我们生成列表的代码,注意自动的将Model设为IEnumerable<MvcMusicStore.Models.Album>。我们修改一下,只显示唱片的标题、类别和演员,并去掉Detail按钮。
运行一下,在浏览器地址栏输入http://localhost:1826/StoreManager,可以看到列表。
4、自己创建HtmlHelper方法,防止字段过长影响Table的布局:我们可以创建一个新目录Helper,创建一个静态类,在其中为HtmlHelpers类增加一个扩展方法。
5、如何使用扩展方法:在视图中引用命名空间即可
6、实现Edit:应该看到Controller中生成了两个Edit方法,前者是用来显示该对象的,后者是用来提交编辑结果的。我们实现了Edit的Get方法后,为其创建Edit视图。
两种方法:一种是使用添加视图由Vs自动创建,一种是使用Heml.EditorFor,我们创建好视图之后修改一下,使用后面一种方法。这样是为了这个视图可以重用于Create。
7、模版的命名约定:我们使用HtmlEditFor来编辑某个Model的时候,系统会首先在Views下面寻找EditorTemplates目录,看下面是否有与Model同名的模版,如果有则使用这个模版,否则创建默认的视图。
所以文件夹的名称和文件的名称都是有强制性的约定的。这当然是Asp.net Mvc强调约定大于配置的理念。
8、创建共享的模版:我们在Views的Shared目录下创建文件夹EditorTemplates,然后在这个文件夹添加一个名为AlBum的视图,并勾上“创建局部视图”。
将模版中的Form相关的信息删除掉,包括提交按钮等,窗体和提交由使用该模版的视图处理,这里的编辑视图仅仅处理对每个字段的编辑。
9、现在我们要修改模版,比如类别和演员,这个通过选择而非输入来处理。这就意味着我们必须使用ViewBag将所有演员的列表和所有类别的列表传入。
10、然后实现HttpPost方法,这里要注意的,是如果提交不成功,两个下拉框用的列表应重新载入。当然,实际项目开发过程中,至少应在服务端缓存这两个列表。
现在就已经能够编辑并保存数据了。
接下来:实现Create方法,这里要重用刚刚创建的编辑模版。实现Create的Get方法,添加视图、改用重用的Edit模版、实现Post方法,这些都照本宣科的做就行了。
12、处理删除:
这个过程包括Get方法,这实际上是一个确认过程。包括Post方法,这里需要一个非强类型的视图告知已经被删除。
总结一下,这一课重点是以下内容:
1、增删改的Get、Post方法和相应的视图。
2、如何创建自定义的HtmlHelpers方法,如何使用?
3、如何重用视图
4、如何处理下拉框,如何使用ViewBag传送数据?
这一课真的头昏脑胀,时间太长,签入代码的时候竟然有舒了一口气的感觉,教程内容安排太不均衡。
第六课 验证 13:35分开始 预期15分钟 13:43分结束
对用户的输入进行验证,包括客户端和服务端两种情形。本课内容很简单,直接在Model里定义验证规则,不用做任何其他的事情,就能解决基本验证问题。
第七课 Membership 15:30开始 预期40分钟 16:19分结束
1、创建一个新的Asp.net mvc 3应用,这次是创建Internet应用而非空程序。将这个项目中与Membership相关的Controller、Views和Model都拷贝到MvcMusicStore,同时改变命名空间。
2、使用项目|Asp.net配置,增加一个管理员用户
因为使用Sql Server,这里需要配置一下,教程里没涉及到。
1、首先为我们的数据库创建Membership相关的表格,运行以下命令即可:
"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\"aspnet_regsql.exe
2、我们已经在Web.config的<configuration>节点中添加了连接字符串
<configuration>
<connectionStrings>
<add name="MusicStoreEntities"
connectionString="Data Source=.;Initial Catalog=MusicStore;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
3、将如下内容加入System.Web节点:这些同样是从internet应用中抄袭过来的
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
<membership>
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="MusicStoreEntities"
enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
applicationName="/" />
</providers>
</membership>
<profile>
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="MusicStoreEntities" applicationName="/" />
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear/>
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="MusicStoreEntities" applicationName="/" />
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
3、然后点击解决方案浏览器第一行最右边的Asp.net配置图标,先启用角色、创建Administrator角色,再创建admin用户,密码也设为123456,同时将其角色设为Administrator。
4、检查一下:
我们在StoreManagerController类前加属性[Authorize(Roles = "Administrator")]
表示只有管理员角色的用户才能访问。
此时再运行,将会出现登录页面。
总结一下,本课讲述如何配置Membership、如何使用角色控制权限。
第八课 购物车和Ajax 16:26分开始 预期80分钟 17:12分结束。
本课讲解如何创建购物车,内容虽多但相对比较简单。
1、现增加购物车、订单、订单明细的实体类,并修改Context类。
2、然后增加一个类ShoppingCart用于处理购物车的业务逻辑,包括加入商品、去掉商品等。
3、添加两个ViewModel类,分别处理购物车的维护和删除,这是业务逻辑和视图沟通的桥梁,我们显然不愿意让Model迁就View。这实际上也是Wpf和SL中很常见的MVVM模式。View仅与ViewModel打交道,不会理会Model类。一般来说,视图的每个元素都对应ViewModel相应的属性。
4、然后继续Controller-View的过程
5、注意购物车的删除功能,我们使用Ajax,这样会直接删除,也不需要另外的视图来处理确认删除的过程。
6、修改Store的Details视图,我们就能够一直从类别到商品到明细,然后添加到购物车,同时也能测试一下购物车的删除功能。
第九课 支付和注册 17:12分开始 预期30分钟 17:46分结束
匿名用户也能将商品放进购物车,但如果要支付并确认订单,则必须登录。
1、购物车和用户信息应该关联起来:在AcountController增加一个私有方法,Logon方法和Register的post方法也要处理
2、增加CheckOutController,为其加上[Authorize],表示用户必须登录才能访问。
3、下一步是增加AddressAndPayment视图
4、为订单增加验证功能,这个在Models里处理
5、增加支付完成的视图,注意这里的Models设为int
6、修改Shared里的Error视图
到目前为止,基本功能已经完成,从第六课之后因为逐步熟悉了,每课所需时间大幅减少,只是对不太清晰的地方看明白就行了。
第十课 最后的完善工作 17:47分开始 预期20分钟 18:15分结束
1、首先是CartSummary,我们定义了Action但没有定义视图。这里我们不用定义强类型的视图,创建局部视图,这样@Html.RenderAction("CartSummary", "ShoppingCart")就能够在任意地方呈现。
2、然后创建类型列表,在StoreController中增加一个Action,用[ChildActionOnly]修饰,这种情形下我们通常都是呈现局部视图。
3、然后修改_Layout.cshtml,加入顶部的链接,并加入类别列表。
4、最后修改一下Store的Browse视图,用图片而非列表的形式显示
5、当然,我们需要在首页显示销售量最大的商品,用户可以快捷的购买
6、终于完成,最后的结果:
最后的结论:
1、整个教程耗时536分钟,接近10个小时。教程中有2到3处问题,不过教程的讨论里基本上都有人解答了。
2、从最终结果来看,开发一般小型应用,所需要的知识本教程基本覆盖。
3、重用:局部视图、HtmlHelper扩展方法。
4、数据访问:EFCodeFirst很简洁,仿佛继承了Asp.net mvc的约定大于配置的想法。
5、没有覆盖的内容包括:如何上传文件并使用无刷新的方式显示进度?Chart如何使用?如何处理缓存?如何分页?等等,这些都不是太复杂的问题。
6、节后开始的一个小型营销数据挖掘项目,使用Asp.net mvc3,已无大碍。参与开发的成员可以使用本教程快速学习。