《Pro ASP.NET MVC 3 Framework》学习笔记之三十四 【验证与授权】

使用windows验证(Using Windows Authentication)
在软件术语里面,验证的意思是测定身份。这个跟授权是完全分开的,授权是让合适的人做合适的事情,授权通常在验证之后发生。ASP.NET的验证功能也紧紧围绕识别访问者的身份并且设置决定实际的访问者能够做什么的安全上下文(security context)。最简单的验证方式就是把这个任务委托给IIS(这通常适合内部系统)。在配置文件里启用Windows身份验证,如果我们使用的Intranet应用程序模版,默认会使用这个配置。如下:
<configuration> 
    <system.web> 
        <authentication mode="Windows" /> 
    </system.web> 
</configuration> 
使用windows验证,ASP.NET依赖于IIS来验证用户的请求,并且有如下模式:
①匿名验证:允许任何用户访问,IIS7默认启用
②基本验证:需要用户提供一个经过验证的用户名和密码,验证标识作为文本会从浏览器发送到服务器,这种模式仅仅应该在SSL连接的基础上使用
③摘要验证:需要用户名和密码,验证标识会被加密为hash代码发送到服务器。安全性比基本验证更高,并且需要服务器是一个域控制器。
④windows验证:通过windows域透明地建立用户的身份,不需要提供其他的认证。在企业内部局域网使用广泛,不适合面向Internet的应用。
可以在IIS管理器里面设置验证模式,如下:


如果我们想让所有的请求都经过验证,需要我们禁用匿名验证功能。如果只是部分限制,那么可以启用匿名验证并对actions和controllers使用验证过滤器。在局域网部署程序,那么使用windows验证是非常有用的。如果用户是来自Internet,应用程序倾向于依赖表单验证。

使用表单验证(Using Forms Authentication)
表单验证非常适合面向Internet网的程序,当然建立表单验证也会比windows验证更加复杂,一旦设置都完毕,那么比windows验证将会更加灵活。表单验证的安全性依赖于一加密的cookie——.ASPXAUTH。这个cookie内容类似于:
9CC50274C662470986ADD690704BF652F4DFFC3035FC19013726A22F794B3558778B12F799852B2E84 
D34D79C0A09DA258000762779AF9FCA3AD4B78661800B4119DD72A8A7000935AAF7E309CD81F28
用FormsAuthentication.Decrypt对其进行解密,可以得到一个FormsAuthenticationTicket对象并且具有如下属性:


其中里面一个关键的属性就是Name,这个跟用户请求的相关联的身份标识。系统的安全性的保证来自于cookie数据的机密和使用服务器的machine keys的签名。这些是由IIS自动生成的,并且如果没有这些keys,包含在cookie里的验证信息是不能被读取和修改的。

Tip:当我们把使用了表单验证的程序部署到服务器集群时,必须保证请求总是返回生成cookie的服务器或保证所有的服务器具有相同的machine keys。这些Keys可以使用IIS管理器里面的machine keys选项来生成和配置。

建立表单验证(Setting Up Forms Authentication)
当我们使用互联网应用程序模版创建一个MVC程序时,默认启用了表单身份验证,相关的配置如下:
  <authentication mode="Forms"> 
    <forms loginUrl="~/Account/LogOn" timeout="2880" /> 
  </authentication> 
这个配置能够适合大多数程序,当然也可以定义更多的属性来控制,这些属性如下:

属性名 默认值 描述
name .ASPXAUTH cookie名
timeout 30分钟 超时时间
slidingExpiration true 滑动过去时间
domain None 跨子域共享(www.example.com和a.example.com)
path / 设置验证cookie发送到指定的URL,这个让我们可以在同一个域中寄宿多个应用程序而不会暴露彼此的验证cookie
loginUrl /login.aspx 如果表单需要用户登录,重定向到指定的登录页面
cookieless UserDeviceProfile 启用无cookie验证
requireSSL false 设置为true会建议浏览器仅仅在使用SSL加密的请求中传递cookie





在web.config文件启用表单验证,当没有经过验证的用户访问到任何标记了[Authorize]的controller和action时会跳转到登录页。

使用无cookie的表单验证(Using Cookieless Forms Authentication)
表单验证支持无cookie模式,这种情况下验证的票据存放在URL里,数据仍然是签名和加密的,但是会作为URL的一部分发送到服务器。只要每一个请求包含了验证数据,那么用户接收到同样应用程序的体验跟启用了cookie是一样的。启用无cookie验证的配置如下:
<authentication mode="Forms"> 
  <forms loginUrl="~/Account/LogOn" timeout="2880" cookieless="UseUri"> 
  </forms> 
</authentication> 
当用户登录时,他们会被重定向到一个像如下的URL:
/(F(nMD9DiT464AxL7nlQITYUTT05ECNIJ1EGwN4CaAKKze-9ZJq1QTOK0vhXTx0fWRjAJdgSYojOYyhDil 
HN4SRb4fgGVcn_fnZU0x55I3_Jes1))/Home/ShowPrivateInformation 
仔细观察会发现,URL遵循这样的模式:/(F(authenticationData))/normalUrl 
我们不用特别的步骤和配置,路由系统会仔细转换这些URL以至于我们的路由配置能够适应任何改变并且HTML辅助方法会自动生成这种类型的URL。不推荐使用无cookie的验证,因为这种验证非常脆弱,如果有一个链接没有包含验证信息,那么用户马上就被注销了。无cookie验证也是不安全的,任何一个人复制你的URL并共享给其他人,那么第一个用户的session将会被劫持。而且,如果我们依赖了从第三方服务器获取的内容,那么我们的验证数据会通过浏览器的引用头(Referer header)发送给第三方。最后,这个URL看起非常丑陋,没有可读性和吸引力。

使用Membership,Roles和Profiles
在SportsStroe项目里面,我们在Web.config文件里面存储了用户的证书信息,对于小的程序和用户不会经常改变并且用户数量很小的情况下可以这样使用。ASP.NET提供了一套标准的用户账户系统来支持常用的用户账户管理任务,包含注册,密码管理,个性设置。具有三个关键的功能区域:
Membership:注册用户账户并访问账户详情和授权证书
Roles:把用户放入组里面,对身份验证的典型应用
Profiles:存储每一个用户的基础数据
ASP.NET对上面的三个区域提供了标准的实现,但是我们也可以跟自定义的实现混合使用,通过一个providers系统就可以实现。内置的providers能够以不同的方式存储数据,包括SQL Server和活动目录。

建立和使用Membership
ASP.NET里面已经有了SqlMembershipProvider和ActiveDirectoryMembershipProvider两个提供者。下面会介绍如何最常规的使用:

建立SqlMembershipProvider
当使用互联网应用程序模版创建一个MVC程序时,默认配置了SqlMembershipProvider。配置的Web.config如下:

View Code

SQL Server Express版本的数据库支持一个user实例的数据库,这些数据库是不用在之前配置就可以使用的。付费版的SQL Server不支持用户实例数据库,需要在使用之前准备好该数据库。安装方法:运行aspnet_regsql.exe。安装完了可以去SQL Server management studio里面查看下。

管理Membership
Membership API包含对注册用户的管理方法:添加和移除账户,重置密码等等。对于一些简单的情形,完全可以使用站点管理工具(VS里面有对应的按钮)。如下:


一旦部署了应用程序,我们能够通过IIS .NET用户选项来管理应用程序的用户。使用.NET User选项时,IIS管理工具读取Web.config文件并且视图确保membership提供者是值得信任的。不太走运的是,IIS管理工具是基于.NET2.0并且尚未更新到支持ASP.NET4.当前的IIS版本,微软对使用.NET4的程序禁用了.NET Users选项。下面看看示例的配置文件:

View Code

这是一个精简过的Web.config文件,只包含两个配置节:connection string和membership database,使用时编辑适合自己的环境。

创建一个自定义的Membership提供者
通过从抽象类MembershipProvider派生可以创建自定义的membership提供者,如下所示:

View Code

上面的Provider使用一个静态的用户和密码列表来执行验证,为了简单说明原理,这里忽略了除ValidateUser之外的其他的方法。接着在配置文件注册自定义的Provider:

View Code

下面截取一个在SportsStore里面使用的例子:

View Code

建立并使用角色
前面介绍了验证,还有另外一个常见的安全需求就是授权——决定用户在验证之后能够做什么。ASP.NET使用基于角色的授权机制,这意味着actions是限制在角色里面的,属于角色的用户能够执行相应的action方法。角色通过唯一的字符串值来表示,例如可以定义如下三个角色:ApprovedMember  CommentsModerator  SiteAdministrator。每一个角色都是完全独立的,没有层级关系。ASP.NET平台期望我们通过provider模型来使用角色,提供了常用的API。当然也可以自定义:

建立SqlRoleProvider
SqlRoleProvider类是对SqlMembershipProvider的补足,使用了同样的数据库。使用互联网应用程序模版创建MVC程序,VS会自动添加相应的元素来建立SqlRoleProvider,如下:

View Code

两个Role Provider注册了,默认都没有启用。要建立SqlRoleProvider必须修改roleManager元素
如:<roleManager enabled="true" defaultProvider="AspNetSqlRoleProvider">

管理Roles
可以使用管理members的方法管理roles,可以使用VS里面的ASP.NET图形化的配置工具来操作。下面介绍创建自定义的Roles Provider:

View Code

通过从RoleProvider派生来定义自己的提供者,我只需要实现GetRolesForUser方法就可以使用了。同样,创建以后需要注册:

View Code

建立并使用Profiles
Membership记录我们的用户,roles记录允许用户做什么操作。如果我们想记录用户个性化的一些数据,如会员积分等等信息。那么通常可以使用Profiles,这对于使用SqlMembershipProvider的小应用程序来说是一个非常有吸引力的功能。

建立SqlProfileProvider
使用互联网应用程序模版创建一个新的MVC程序,包含在Web.config里面的元素创建SqlProfileProvider。如下:

View Code

配置/读/写Profile数据
在使用Profile之前,我们必须定义Profile的数据结构,可以在Web.config的profile节里面添加属性元素如下:

View Code

上面定义的属性都是String类型的,但是Profile支持任何能够序列化的.NET类型。在我们使用Web Forms的时候,通过跟profiles属性一致的代理对象来访问profile数据。这个在MVC里是不可行的,但是我们可以使用HttpContext.Profile属性来访问。如:

View Code

ASP.NET框架在我们第一次访问profile数据时,使用profile提供者载入用户的profile属性并且在请求结束时通过profile提供者写回,我们不用显示的保存,这个是自动完成的。
启用匿名的Profiles
默认情况下,profile数据只对经过验证的用户可用,没有登录的用户访问时会抛异常。可以通过启用对你们profile的支持来解决:

View Code

当匿名的身份标识启用时,ASP.NET框架将会通过一个.ASPXANONYMOUS的cookie来记录你们用户,并且cookie的过期时间是10000分钟(70天左右)。启用了匿名profile以后,没有验证的用户也可以读写profile数据,没一个没有验证的用户会自动为他们创建一个账户并保存在profile数据库里面。

创建自定义的Profile提供者(Profile Provider)
通过从ProfileProvider派生来创建自定义的profile provider。如下:

View Code

上面的provider非常简单,仅仅将数据存储在内存。接着需要注册:

View Code

为什么不应该使用基于URL的授权(Why You Shouldn’t Use URL-Based Authorization)
ASP.NET曾经依靠匹配URL到应用程序的目录结构来实现授权,这样的做法非常多以至于在URL模式中定义授权规则有非常重要的意义。很多Webform的程序,例如把所有管理员的aspx页面放在一个Admin的文件夹下,这意味着我们可以使用基于URL的授权来限制登录的用户对/Admin/*的访问。这种方式对MVC框架是没有用的,因为路由系统的存在打破了URL跟文件系统之间的联系。正确做法是在controller上使用Authorize过滤器(前面的章节有介绍)

使用IP地址和域名限制访问(Restricting Access Using IP Addresses and Domains)
首先介绍下这么做的风险:
这种方式应该谨慎使用,有很多潜在的风险。首先这是基于URL的授权,并且不能很完善的跟MVC的路由系统相适应。其次,用这种方式限制访问没有考虑用户怎样跟我们应用程序的可能的交互。举一个例子,亚当今天早上在家第一次上网,后来他在咖啡店连接上网,在朋友家上网,在另一个朋友的办公室上网,最后回到家里上网。在上面的情形里有些是通过VPN连接的,有些是直接连的网。基于用户从哪连接网络来限制访问很容易建立,但是要想得到正确的判断很困难。下面的Web.config使用了IP地址和域名限制来建立:

View Code

我们在ipSecurity元素里面定义策略,可以使用IP地址和域名来限制访问,但是需要显示的启用enableReverseDns=true。建议在启用域名支持时需要谨慎,因为它需要为每一个请求反向查找DNS,这是非常耗时的并且会严重限制服务器的吞吐量。使用clear元素移除任何存在的策略,然后使用add和remove定义我们的新策略。add添加新的限制,如:
<add ipAddress="192.188.100.1"/> 这样阻止处理来自该IP地址的请求,再如:<remove domainName="otherdomain.com"/> ,这样就允许来自该域名的请求。

好了,本章的笔记就到这里,还剩下最后一章的笔记,谢谢大家持续支持。希望路过的朋友留下你们的各种建议或意见:-)


在技术的海洋,做个渔夫;不是牛人,同为凡客

分类: ASP.NET MVC

摘要: 使用windows验证(Using Windows Authentication)在软件术语里面,验证的意思是测定身份。这个跟授权是完全分开的,授权是让合适的人做合适的事情,授权通常在验证之后发生。ASP.NET的验证功能也紧紧围绕识别访问者的身份并且设置决定实际的访问者能够做什么的安全上下文(security context)。最简单的验证方式就是把这个任务委托给IIS(这通常适合内部系统)。在配置文件里启用Windows身份验证,如果我们使用的Intranet应用程序模版,默认会使用这个配置。如下:<configuration> <system.web> <a阅读全文
posted @ 2012-06-15 23:28 Gabriel Zhang 阅读(181) | 评论 (0) 编辑
 
摘要: 本章会简要阐释对用户而言操纵HTTP请求(例如,修改cookies,隐藏或禁用表单字段等)是多么容易的事情,这会让我们在正确的思维框架下清楚地考虑web的安全性。接着会依次介绍常见的避免攻击的指南,并了解它们的工作原理以及它们怎么应用到MVC框架里面。还会描述如果阻止每一种攻击的形式或者是更换的并设计出来。所有的输入都是可以被伪造的(All Input Can Be Forged)有这样一句话:不要相信用户的输入。用户的输入有哪些种类呢?如下所示:①传入的URLs(包括Request.QueryString[]的值)②表单提交的值(Request.Form[]的值,包括隐藏域和禁用的字段值)③阅读全文
posted @ 2012-06-13 23:14 Gabriel Zhang 阅读(844) | 评论 (14) 编辑
 
摘要: Ajax是Asynchronous JavaScript and XML的缩写,正如我们看到的,XML部分已经不再像过去那样重要,但是异步的部分却让Ajax非常有用。它是一种在后台从服务端请求数据的模型,而不用重新加载网页。使用MVC无入侵的Ajax(Using MVC Unobtrusive Ajax)MVC框架包含了对无入侵的Ajax的支持,而且是基于jQuery库的。下面创建示例项目UnobtrusiveAjax,如下:View Code //modelusing System.ComponentModel.DataAnnotations;namespace UnobtrusiveAja阅读全文
posted @ 2012-06-01 23:25 Gabriel Zhang 阅读(851) | 评论 (4) 编辑
 
摘要: 模型验证是确保接收的数据适合绑定到model的这样的一个处理过程,当不适合的时候能够提供一些有用的信息来帮助用户改正他们问题。模型验证可以分为两个部分:1.检查我们接收的数据。2.帮助用户修正问题。非常庆幸的是,MVC框架对模型验证提供可扩展支持,本章会展示基本功能的使用以及阐释一些针对验证过程的高级技术。添加一个ModelValidation项目添加一个视图模型Appointment,如下:View Code using System.Web;using System.ComponentModel.DataAnnotations;namespace ModelValidation.Model阅读全文
posted @ 2012-05-28 08:20 Gabriel Zhang 阅读(1175) | 评论 (8) 编辑
 
摘要: 模型绑定(Model Binding)是使用浏览器发起Http请求时的数据创建.NET对象的过程。我们每一次定义带参数的action方法时就已经依靠了模型绑定——这些参数对象是通过模型绑定创建的。这一章会介绍模型绑定的原理以及针对高级使用必要的定制模型绑定的技术。理解模型绑定(Understanding Model Binding)想象下我们创建了一个控制器如下:View Code using System; using System.Web.Mvc; using MvcApp.Models; namespace MvcApp.Controllers { public class ...阅读全文
posted @ 2012-05-15 18:03 Gabriel Zhang 阅读(955) | 评论 (5) 编辑
 
摘要: 在前面出现过Html.CheckBoxFox和Html.TextBoxFox等HTML helper方法,这些方法用来指定必要的HTML元素编辑数据。MVC框架还支持另一种方法实现,称为模板化视图helper(辅助)方法,在这些方法里面我们可以指定哪一个模型对象或属性被显示或编辑,并且让MVC框架自己判断应该呈现哪一种类型的HTML元素(是TextBox还是CheckBox)。这一章里面,会介绍这些方法并阐释怎样调优和完全替换model模版系统的部件1.使用模板化的视图Helpers(Using Templated View Helpers)模版化视图helpers的创意就是它们更加灵活。我们阅读全文
posted @ 2012-04-23 22:49 Gabriel Zhang 阅读(1124) | 评论 (2) 编辑
 
摘要: 接着上一篇Views的笔记在视图里导入命名空间(Importing Namespaces into a View)Razor视图通过一套常用的命名空间编译,这为我们省去了在使用常用类时指定必要的命名空间的麻烦。如果需要使用我们自己定义的类就必须引入命名空间或者是使用类的完整名称(包含了命名空间),如下所示:View Code @{ ViewBag.Title = "Index"; } Here is some data: @DynamicData.Infrastructure.MyUtility.GetUsefulData()上面的例子使用了MyUtility类,里面有一个阅读全文
posted @ 2012-04-12 00:35 Gabriel Zhang 阅读(657) | 评论 (6) 编辑
 
摘要: 在前面很多的章节里面的,最常用的action result是视图呈现并返回给客户端的ViewResult类型。本章会专注于视图的原理,首先展示MVC框架是如何使用视图引擎处理ViewResults的,包括阐释如何创建一个视图引擎。接着介绍使用Razor视图引擎的一些技术。最后是关于创建和使用部分视图,子actions,以及Razor片段,这些都是涉及高效MVC开发的本质话题。创建一个自定义视图引擎(Creating a Custom View Engine)MVC框架包含了两个内置的,功能完善,容易理解的视图引擎:a.Razor引擎:MVC3里面引入的一个新的视图引擎,具有更加简洁和优雅的语法阅读全文
posted @ 2012-04-06 23:45 Gabriel Zhang 阅读(1081) | 评论 (0) 编辑
 
摘要: 本章内容分为两个部分,第一部分:介绍关于controllers工作原理的高级功能,探究从请求到action方法执行的整个请求处理管道的组成部分并阐释控制这个过程的不同的方式;第二部分:介绍两种特殊的控制器,分别是:无会话(sessionless)控制器,异步(asynchronous)控制器.这些能够增进服务器的处理能力。这部分会阐释如何创建和使用它们,并且会说明在什么情况下使用它们。请求处理管道的组成(Request Processing Pipeline Components)我们的焦点放在第一部分的Controller Factory和Action Invoker上面,其实从命名上看已经阅读全文
posted @ 2012-03-28 19:38 Gabriel Zhang 阅读(1185) | 评论 (10) 编辑
 
摘要: 过滤器(Filters)过滤器(Filters)向请求处理管道注入了额外的逻辑。他们提供了一种简单而优雅的方式实现了横切关注点,这个术语是针对整个应用程序使用的功能,并不能灵活的适用任何一个点,所以这个会打破分解关注点的模式。像日志,验证和缓存都是经典的横切关注点的例子。之所以称为过滤器(Filters),是因为这个术语同样应用于其他web应用程序框架里面,包括Ruby on Rails。然而,MVC框架里面的过滤器完全不同于ASP.NET平台里面的Request.Filters和Response.Filter对象,这两个对象是实现请求和响应流的传输(一种高级的并很少发生的活动)。当然,我们能阅读全文
posted @ 2012-03-20 18:04 Gabriel Zhang 阅读(1241) | 评论 (2) 编辑
 
摘要: 重定向到文本URL(Redirecting to a Literal URL)最基本的重定向浏览器方式就是调用Redirect方法,该方法会返回一个RedirectResult类的实例。例如:public RedirectResult Redirect() {return RedirectPermanent("/Example/Index"); }当然我们可以根据自己的喜好来选择Redirect方法的重载,可以添加一个bool类型的参数指定是否永久重定向(不指定则是暂时重定向)进行单元测试:View Code [TestMethod] public void Redirec阅读全文
posted @ 2012-03-11 01:27 Gabriel Zhang 阅读(932) | 评论 (0) 编辑
 
摘要: 生成输出(Producing Output)在controller完成处理请求之后,通常需要生成一个响应。当我们通过直接实现IController接口创建一个简单的controller时,我们需要对处理请求的每一个方面负责,包括创建对客户端的响应。如果我们想发送一个HTML响应,那我们必须创建并且集合HTML数据,然后使用Response.Write方法将数据发送到客户端。类似地,如果我们想重定向用户到其他的URL,可以使用Response.Redirect方法。下面是具体的实例:View Code using System.Web.Mvc;using System.Web.Routing;n阅读全文
posted @ 2012-03-09 00:42 Gabriel Zhang 阅读(1595) | 评论 (34) 编辑
 
摘要: Controllers入门(Introducing the Controller)每一个针对应用程序的请求都是通过Controller处理的,controller自由地选择合适的方式来处理这些请求,只要它不偏离到View和Model所负责的区域。这样意味着我们不要把业务或数据存储的逻辑放到Controllers里面,也不要创建用户接口。在ASP.NET MVC框架里面,Controllers是包含必要的处理请求的.NET类。前面有解释Controller的角色是封装我们的应用程序逻辑。这意味着Controller是负责处理请求,实行对Model的操作,选择View呈现给用户。本次的笔记会介绍C阅读全文
posted @ 2012-03-06 22:12 Gabriel Zhang 阅读(1108) | 评论 (0) 编辑
 
摘要: 使用AreasMVC框架支持在areas(区域)里面组织一个web应用程序,每一个area呈现应用程序的一个功能段,比如管理,订单,客户支持等等。这对于一个大的项目是非常有用的,因为将所有的controller,model,view都只是放在一套文件夹里面(整个项目所有的Controller都在一个文件夹下)会非常难管理的。这时area就非常有用了,每一个area都有自己的一套文件结构,如Controller,View,Model,通过area就可以保持相对的分离。这样做可以让程序的每一个功能块划分的更加明确,当有很多的开发人员合作开发时也可以避免相互冲突。下面会创建一个实例来说明Area的作阅读全文
posted @ 2012-02-26 23:08 Gabriel Zhang 阅读(1335) | 评论 (2) 编辑
 
摘要: 自定义路由系统通过前面的学习,我们能够感受到路由系统的灵活性和可配置性,如果这些不能满足我们的需求,我们可以自定义行为,下面会介绍如何自定义路由。创建一个对RouteBase类的自定义实现如果我们不喜欢标准Route对象匹配URL的方式,或者想实现一些特别的东西。我们可以从RouteBase派生一个类来替代。派生出来的类可以让我们自己控制URL的匹配,参数的提取,以及Outgoing URL的创建。派生的类需要实现下面两个方法:1.GetRouteData(HttpContextBase httpContext):实现传入的URL的匹配机制。 在每一个RouteTable.Routes进入的时阅读全文
posted @ 2012-02-22 23:49 Gabriel Zhang 阅读(1353) | 评论 (10) 编辑
 
摘要: 创建传出的URL(Outgoing URLs)处理传入的URL(Incoming URLs)仅仅是路由系统的一部分功能。我们也需要使用URL架构来创建Outgoing URLs,我们可以将这些URL嵌入到我们的View里面,并且能够让用户点击URL提交表单给我们的应用程序,并能够命中合适的controller和action。下面会展示用不同的技术来创建Outgoing URLs:最便捷的创建Outgoing URLs就是手动定义如:<a href="/Home/About">About this application</a> 这样的URL。这个UR阅读全文
posted @ 2012-02-18 15:49 Gabriel Zhang 阅读(1528) | 评论 (2) 编辑
 
摘要: 第一部分 ASP.NET MVC3介绍《Pro ASP.NET MVC 3 Framework》学习笔记之一 【MVC的历程,优点,HelloWorld】《Pro ASP.NET MVC 3 Framework》学习笔记之二 【领域模型的概念介绍及MVC模型绑定】《Pro ASP.NET MVC 3 Framework》学习笔记之三 【MVC模式介绍】《Pro ASP.NET MVC 3 Framework》学习笔记之四 【领域模型介绍】《Pro ASP.NET MVC 3 Framework》学习笔记之五 【依赖注入及ninject工具使用】《Pro ASP.NET MVC 3 Frame.阅读全文
posted @ 2012-02-07 16:30 Gabriel Zhang 阅读(2373) | 评论 (12) 编辑
 
摘要: 整个项目范围的依赖注入(Project-Wide Dependency Injection)在书接下来的章节里面,我们会看到MVC框架提供的很多不同的方式来让我们扩展和自定义对请求的处理,每一种方式都会用一个实现的接口或一个派生的基类来定义。在第一部分的SportsStore项目实例里面已经有过引入。我们从DefaultControllerFactory类派生了一个NinjectControllerFactory类,以至于我们能够创建Controller,并使用Ninject来管理DI(依赖注入)。如果使用这种方法针对MVC里面每一个自定义的点,最终会让我们将DI贯彻到整个应用程序,但是这样会阅读全文
posted @ 2012-02-06 23:52 Gabriel Zhang 阅读(1622) | 评论 (5) 编辑
 
摘要: 接下来是关于SportsStore的后台管理功能,也就是通常的CRUD操作。首先添加一个AdminController,代码如下:View Code using System.Web.Mvc; using SportsStore.Domain.Abstract; namespace SportsStore.WebUI.Controllers { public class AdminController : Controller { private IProductRepository repository; public AdminControll...阅读全文
posted @ 2012-01-14 17:30 Gabriel Zhang 阅读(1253) | 评论 (4) 编辑
 
摘要: 提交订单:这是SportsStore项目的最后一个功能了,结算并完成我们的订单。在Entities文件夹里添加一个ShippingDetails.cs,代码如下:View Code public class ShippingDetails { [Required(ErrorMessage = "Please enter a name")] public string Name { get; set; } [Required(ErrorMessage = "Please enter the first address line")] ...阅读全文
posted @ 2012-01-12 00:21 Gabriel Zhang 阅读(1362) | 评论 (0) 编辑
 
摘要: 绑定Shopping Cart定义购物车Cart的实体,购物车是我们程序业务领域的一个部分,所以在我们领域模型(Domain Model)里面添加一个cart的实体是合理的。在SportsStore.Domain的Entities文件夹下添加一个Cart的实体类,如下所示:View Code public class Cart { private List<CartLine> lineCollection = new List<CartLine>(); //添加 public void AddItem(Product product, i...阅读全文
posted @ 2012-01-10 21:08 Gabriel Zhang 阅读(1507) | 评论 (4) 编辑
 
摘要: 前面给SportsStore添加了分页的功能。接着我们添加导航控制,通过左边的菜单来分类显示数据。首先修改SportsStore.WebUI.Models下的ProductsListViewModel.cs,增加一个CurrentCategory属性public string CurrentCategory{get;set;}。接着修改List action方法,能够通过传入的CurrentCategory来过滤查询的产品列表。修改后的List action方法如下所示:public ViewResult List(string category, int page = 1) { Prod..阅读全文
posted @ 2012-01-08 22:48 Gabriel Zhang 阅读(1449) | 评论 (10) 编辑
 
摘要: 接着我们添加一个分页功能。修改ProductController,如下所示: public class ProductController : Controller { public int PageSize = 4;//后面会更改 private IProductsRepository repository; public ProductController(IProductsRepository productRepository) { repository = productRepository; ...阅读全文
posted @ 2012-01-05 21:28 Gabriel Zhang 阅读(1311) | 评论 (15) 编辑
 
摘要: 距上次的笔记已经有2个多星期了,之所以没保持前面的笔记频率,是因为书中后面的例子是基于EF实体框架的。我有点不愿意使用EF框架,不是它不好,而是我打算在操作完书中讲的例子后能够试着将这个MVC3的项目移植到mono里面,当然数据库也换了,我这里会用MySQL。最终我打算将iBatisnet学着用一下,我还是比较喜欢自己写SQL,对我自己而言比较容易掌控。前面学过NHibernate感觉比较复杂。而且自己写SQL能够不断加强自己的SQL基础,也不至于用框架用多了,基本的SQL都不熟悉了。呵呵!接下来的三章会完成一个项目SportsStore.书里面用到了EF框架,我会用IBastisnet代替E阅读全文
posted @ 2012-01-04 21:51 Gabriel Zhang 阅读(1961) | 评论 (21) 编辑
 
摘要: 使用Moq前面我创建了一个FakeRepository类来支持我们的测试,但是并没有创建一个实际的Repository的实现,所以我需要一个替代品。FakeRepository类是IProductRepository接口的一个模拟实现,Moq是一个框架,为了让我们能够快速,简便的实现模拟,而不用手工添加一些额外的代码。首先我们需要下载一个Moq的组件,猛击这里可以下载。在我们的测试项目ProductApp.Tests里面添加对Moq的引用。使用mocking工具好处就是我们能够创建足够适应我们功能的mocks来帮助测试。可能在这个项目里面我们体会不出Moq的优势,但是在实际的项目中,Moq让我阅读全文
posted @ 2011-12-19 00:25 Gabriel Zhang 阅读(1430) | 评论 (2) 编辑
 
摘要: 前面的笔记做了关于Ninject(MVC三类工具里面第一类IoC容器),本次的笔记是关于VS里面提供的Unit Testing工具的使用以及Moq(模拟工具)。1.Visual Studio自带的单元测试工具除了使用微软自带的单元测试工具,我们还可以选择NUnit--非常流行的一款测试工具。接下来我们创建一个项目ProductApp,你也可以使用NUnit,猛击这里获取。它的使用跟VS自带的非常类似。首先我们创建用来的测试的类和接口,如下所示:public class Product { public int ProductID { get; set; } public st...阅读全文
posted @ 2011-12-18 00:37 Gabriel Zhang 阅读(1361) | 评论 (11) 编辑
 
摘要: 接着上次的Ninject的笔记,如果你是初次路过,可以先看看我前面的笔记。一,创建依赖链(Chains of Dependency)当我们向Ninject请求创建一个类型时,Ninject会去检查该类型和其他类型之间的耦合关系。如果有额外的依赖,Ninject也会解析它们并创建我们需要的所有类的实例。为了进一步说明,我们创建一个新的接口和一个实现该接口的类。请注意我们的例子是跟前面的笔记衔接的,所以如果你打算跟着一起操作的话,最好能够去看看前面的笔记。创建一个IDiscountHelper如下所示:public interface IDiscountHelper { //Product...阅读全文
posted @ 2011-12-10 00:07 Gabriel Zhang 阅读(1397) | 评论 (10) 编辑
 
摘要: 本次的笔记分为三个部分:Ninject(依赖注入容器,前面有介绍的,如果你第一次路过这里,可以先看下我前面的笔记),NUnit(单元测试工具),Moq(用来模拟在单元测试中的接口实现).今天我做的笔记是关于第一部分:Ninject.如果你对依赖注入(DI)没有任何的了解,你可以看看我前面的笔记或者在网上搜索相关的资料进行了解。下面通过一个实例来介绍Ninject的使用,首先我们需要猛击这里下载相关的DLL。我们仍然用到的前面的Product,实现技术所有Product的总价值。下面通过几个步骤来具体的介绍:1.创建一个Console Application,如果你不介意,我们暂且给它命名为Ni阅读全文
posted @ 2011-12-09 00:07 Gabriel Zhang 阅读(1915) | 评论 (28) 编辑
 
摘要: 继续完成上次提到的第二部分的笔记:Razor视图引擎1.Razor是什么:Razor是MVC3里面提供的一个新的视图引擎。ASP.NET视图引擎通过寻找包含服务端指令的特殊元素用来处理web页,正如我们早期所注意到的那样,标准的ASPX视图引擎依赖<%和%>元素,这对于我们来说是非常熟悉的。通过Razor,MVC的开发团队引入了一套以@为中心的新句法元素。一般来说,只要我们熟悉了<%%>的语法,对Razor的使用就不会有太大的问题,尽管可能有一些新的规则。2.Razor的使用step1:创建一个空的MVC3的项目Razor,并添加一个Product.cs的Model,如阅读全文
posted @ 2011-12-08 00:01 Gabriel Zhang 阅读(1668) | 评论 (16) 编辑
 
摘要: 本次笔记分为两个部分:C#语言的部分特性和MVC3里面提供的新视图引擎Razor的@句法。今天晚上的笔记是第一部分:C#的部分特性(我主要选择扩展方法,泛型委托,Lambda表达式等内容,选择这些是因为我对这几个部分不是很熟悉)。如果你已经对C#2.0及3.0里面出现的几个特性比较了解,那你完全可以忽略这部分直接去看下次的关于Razor的笔记。一,扩展方法(Extension Methods)1.扩展方法给我们提供了一种很便捷的方式,通过这种方式我可以给那些不是我们自己创建的类(如第三方组件里面的)或是我们不能直接修改的类添加方法。下面是一个关于购物车的例子,我们定义一个ShoppingCar阅读全文
posted @ 2011-12-06 23:59 Gabriel Zhang 阅读(1710) | 评论 (5) 编辑
 
摘要: 一,创建松耦合的组件1."分解关注点"是MVC模式里面一个非常重要的特性。我们想要在应用程序里面创建的组件尽可能的独立,这样我们就能管理比较少的依赖关系。理想情况下,每个组件都是孤立的,不知道其他组件的存在,处理应用程序的其他领域仅仅通过抽象接口,这就是所谓的松耦合,它让我们的应用程序更加容易测试和修改。通过一个简单的例子可以帮助我们理解,假如我们想写一个发邮件的组件,暂且就把这个组件命名为MyEmailSender,接着我们实现一个接口,这个接口定义了所有需要发送邮件的功能,也暂且将这个接口命名为IEmailSender。任何其他的应用程序的组件需要引用IEmailSen阅读全文
posted @ 2011-12-04 22:34 Gabriel Zhang 阅读(1932) | 评论 (10) 编辑
 
摘要: 主题:应用领域驱动开发(Applying Domain-Driven Development)Domain Model是MVC程序的"心脏",其他的一切,包括Controllers和Views仅仅是用来跟Domain Model交互的一种方式,ASP.NET MVC并没有限制使用在Domain Model上面的技术,我们可以自由的选择跟.net framework交互的技术,并且这样的选择是非常多的。不仅如此,ASP.NET MVC为我们提供了基础的架构和约定来帮助Domain Model里面的Classes跟Controllers和Views的联系,也包括跟MVC自己的联阅读全文
posted @ 2011-12-04 01:32 Gabriel Zhang 阅读(1994) | 评论 (21) 编辑
 
摘要: 主题:MVC模式1.MVC的历史:MVC(model-view-controller)这个概念在20世纪70年代就已经被使用了,MVC是从Smalltalk项目中提出的。所以原始的MVC模式所包含非常好的细节跟Smalltalk项目的具体概念是紧密相关的。我们假定View是无状态的,跟mvc的应用程序的交互遵循这样一个的过程:用户产生行为造成view更新,这刚好跟Web应用程序通过HTTP请求和响应的本质吻合。而且,mvc强调分解关注点的思想--领域模型和控制逻辑跟UI的松耦合,这意味着大量的HTML是可以独立其他部分而存在,这也使得维护和测试更加的简单。当然,这也是Ruby on Rails阅读全文
posted @ 2011-12-03 02:36 Gabriel Zhang 阅读(2152) | 评论 (8) 编辑
 
摘要: 接着昨天的笔记:为第一次的Demo添加动态输出(Dynamic Output)整个应用程序平台的关键点就是构建动态的输出,在MVC中,构建数据是controller的工作,将数据作为HTML的呈现是View的工作,很明显这里有一个将数据从Controller传递到View的过程。其中的一种方式就是通过ViewBag,ViewBag是Controller基类的一个成员,它是一个动态的对象,我们可以给它赋予任意的属性值,并在View中呈现。修改Index Action如下: public ViewResult Index() { int hour ...阅读全文
posted @ 2011-12-01 22:50 Gabriel Zhang 阅读(3006) | 评论 (19) 编辑
 
摘要: 序论:asp.net mvc出现已经有两三年的时间了(2009开始1.0版本),但是这么方面的中文学习资料仍然非常少,特别是asp.net mvc3,几乎就没有中文的学习书籍。在英文的书籍中有两本是非常经典的mvc3教程:《Professional ASP.NET MVC 3》--作者:Jon Galloway , Phil Haack, Brad Wilson , K. Scott Allen和《Pro ASP.NET MVC 3 Framework》--作者:Steven Sanderson。我正在看的是后面这本。虽然勉强能看明白点,但为了以后查阅方便,也希望能给那些跟我一样初学MVC3又阅读全文
posted @ 2011-11-30 23:34 Gabriel Zhang 阅读(4141) | 评论 (35) 编辑
原文地址:https://www.cnblogs.com/Leo_wl/p/2551594.html