《Pro ASP.NET MVC 3 Framework》学习笔记之二十五【Filters】

过滤器(Filters)

过滤器(Filters)向请求处理管道注入了额外的逻辑。他们提供了一种简单而优雅的方式实现了横切关注点,这个术语是针对整个应用程序使用的功能,并不能灵活的适用任何一个点,所以这个会打破分解关注点的模式。像日志,验证和缓存都是经典的横切关注点的例子。

之所以称为过滤器(Filters),是因为这个术语同样应用于其他web应用程序框架里面,包括Ruby on Rails。然而,MVC框架里面的过滤器完全不同于ASP.NET平台里面的Request.Filters和Response.Filter对象,这两个对象是实现请求和响应流的传输(一种高级的并很少发生的活动)。当然,我们能够在MVC框架里面使用这两个对象,但通常我们谈及过滤器是指MVC框架里面的过滤器。本章里面会介绍MVC框架所支持的不同的过滤器策略以及如何控制它们执行。

使用Filters

在前面的SportsStore项目里面已经使用了过滤,就是将验证应用到了Controller的action方法里面,只有验证的用户才能请求相应的action方法,这为我们提供了一种选择的途径。我们可以在每一个action方法里面检查请求的验证状态。如下所示:

View Code

namespace SportsStore.WebUI.Controllers { 

public class AdminController : Controller { 

// ... 

public ViewResult Index() { if (!Request.IsAuthenticated) {                 FormsAuthentication.RedirectToLoginPage();             } // ...        } public ViewResult Create() { if (!Request.IsAuthenticated) {                 FormsAuthentication.RedirectToLoginPage();             } // ...        } 

public ViewResult Edit(int productId) { if (!Request.IsAuthenticated) {                 FormsAuthentication.RedirectToLoginPage();             } // ...        } 

// ...     } } 

通过上面的代码,我们可以发现其实里面有很多重复的地方,那使用Filters就能解决这个问题。如下代码所示:

View Code

namespace SportsStore.WebUI.Controllers { 

[Authorize] public class AdminController : Controller { 

// ...

public ViewResult Index() { 

// ...        } 

public ViewResult Create() { // ...        } 

public ViewResult Edit(int productId) { // ...        } 

// ...     } } 

Filters是.NET里面的特性(Attributes),这些是添加到请求处理管道额外的步骤。上面使用了Authorize过滤器实现同样的效果,但是代码显然更加简捷优雅。有四种基本的过滤器类型:Authorization, Action, Result, Exception对应接口为IAuthorizationFilter,IActionFilter,IResultFilter,IExceptionFilter。

在MVC框架调用一个Action之前,它会检查方法的定义中是否有实现了上面接口的特性(Attributes).如果有的话,那么在请求处理管道适当的位置,通过该接口定义的方法会被调用。MVC框架包含了默认已经实现了过滤器接口的Attributes类。

注:ActionFilterAttribute类实现了IActionFilter和IResultFilter接口,这个类是抽象类。其他的像AuthorizeAttribute和HandleErrorAttribute,包含了有用的功能,不需要派生出一个类就可以直接使用。

对Controllers和Action方法应用过滤器

Filters可以应用到单个的Action方法或者是整个Controller类,如下所示:

View Code

namespace SportsStore.WebUI.Controllers { 

public class AdminController : Controller { 

// ... instance variables and constructor         [Authorize] public ViewResult Index() { if (!Request.IsAuthenticated) {                 FormsAuthentication.RedirectToLoginPage();             } // ...rest of action method         } 

[Authorize] public ViewResult Create() { if (!Request.IsAuthenticated) {                 FormsAuthentication.RedirectToLoginPage();             } // ...rest of action method         } 

// ... other action methods     } } 

我们可以使用多个Filters,也可以混合使用Filters。如下所示:

View Code

[Authorize(Roles="trader")] // applies to all actions public class ExampleController : Controller { 

[ShowMessage]                   // applies to just this action     [OutputCache(Duration=60)]      // applies to just this action     public ActionResult Index() { // ... action method body     } } 

有一些过滤器获取几个参数,后面会有探究其原理。
注:如果我们自定义了针对Controllers的基类,任何应用在基类的过滤器会对其所有的派生类起作用。

使用Authorization过滤器

Authorization过滤器是在其他的过滤器之前运行,并且也是在Action方法被调用之前。这个过滤器是用来授权认证的,确保只有授权的用户才能调用。看一下这样一个场景,MVC框架接收一个来自浏览器的请求,路由系统处理请求的URL并提取被命中的controller和action的名字。一个新的controller实例被创建,但是在action方法被调用之前,MVC框架会检查是否有应用到该action方法上面的授权认证过滤器(authorization filters)。如果有,那么定义在IAuthorizationFilter接口里面的唯一的方法OnAuthorization会被调用。如果authentication filter批准了该请求,那么请求管道里面的下一步就会被执行,否则请求就会被拒绝。

创建一个授权认证过滤器(Creating an Authentication Filter)

下面是一个检查用户是否登录的过滤器,如下所示:

View Code

namespace MvcFilters.Infrastructure.Filters { public class CustomAuthAttribute : AuthorizeAttribute     { private string[] allowedUsers; public CustomAuthAttribute(params string[] users)         {             allowedUsers = users;         } 

protected override bool AuthorizeCore(HttpContextBase httpContext)        { return httpContext.Request.IsAuthenticated &&                 allowedUsers.Contains(httpContext.User.Identity.Name,                     StringComparer.InvariantCultureIgnoreCase);         }     } } 

我们定义的过滤器需要一个数组参数,数组里面包含了被授权认证的用户,我们的过滤器里面包含了PerformAuthenticationCheck方法,确保请求是被认证的并用户也是在授权的集合里面的。这个类里面最有趣的部分是OnAuthorization方法的实现,传递给该方法的参数是AuthorizationContext类的实例,这个类是从ControllerContext派生。这让我们可以访问一些有用的对象,这些对象包含:Controller,HttpContext,IsChildAction,RequestContext,RouteData。

回想下,当我们判断请求是否通过验证用到的方法:filterContext.HttpContext.Request.IsAuthenticated。使用Context对象,我们能获取需要对请求做决断的所有信息。

AuthorizationContext定义了两个额外的属性:

1.ActionDescriptor(类型是ActionDescriptor)提供Action方法的详情
2.Result(类型是ActionResult)Action方法的返回结果,是一个通过设置这个属性值为non-null来取消请求的过滤器

第一个属性ActionDescriptor返回的是System.Web.Mvc.ActionDescriptor类的实例,我们能够用来获取应用了过滤器的action方法的有关信息。
第二个属性Result,是让过滤器工作的关键。当我们给一个针对action请求授权,然后我们在OnAuthorization里面什么都不做,这会让MVC框架默认请求应该被处理。然而如果我们设置Result属性为一个ActionResult对象,MVC框架会使用它作为所有请求的结果,在请求管道里剩余的步骤也不会执行,并且我们提供的结果会为用户生成输出。

我们的例子里面,如果PerformAuthenticationCheck返回false(表明请求没有被验证或用户没有被授权),那么我们创建一个HttpUnauthorizedResult结果并赋给Result属性,如:filterContext.Result = new HttpUnauthorizedResult();

使用我们自定义的过滤器如下:

View Code

... [CustomAuth("adam", "steve", "bob")] public ActionResult Index() { return View(); } ... 

使用内置的授权过滤器(Using the Built-in Authorization Filter)

MVC框架里面包含了一个非常有用的内置的授权过滤器称为AuthorizeAttribute。我们可以具体通过两个属性来设置验证策略。
两个公开的属性:1.Users(类型String)  2.Roles(类型String)。示例代码如下:

View Code

... [Authorize(Users="adam, steve, bob", Roles="admin")] public ActionResult Index() { return View(); } ... 

上面的过滤器表示只有用户是  adam,  steve, 和bob的,并且用户有管理员权限的才能请求该action方法。

对大多数应用程序,AuthorizeAttribute提供的验证策略已经足够使用。如果我们想实现比较特殊的过滤器,可以从这个类派生。相对于直接实现IAuthorizationFilter接口的方式,这种风险更低。AuthorizeAttribute类提供两个可以自己现实的点。分别如下:

1.AuthorizeCore方法:被OnAuthorization的AuthorizeAttribute实现调用以及实现授权检查
2.HandleUnauthorizedRequest方法:当授权检查失败时调用

注:我们能够重写的第三个方法是OnAuthorization,推荐不要这样做。因为这个方法默认的实现包含了对内容缓存使用输出缓存过滤器的安全地处理。后面会介绍

实现一个自定义授权策略

下面创建一个自己的AuthorizeAttribute子类。这个策略将要授权任何从服务器桌面直接运行浏览器(Request.IsLocal为true),或者远程用户的用户名能够匹配normalAuthorizeAttribute的规则。这对于服务器管理员绕开网站的登录过程非常有用。代码实现如下:

View Code

using System.Web; using System.Web.Mvc; 

namespace MvcFilters.Infrastructure.Filters{ public class OrAuthorizationAttribute : AuthorizeAttribute    { 

protected override bool AuthorizeCore(HttpContextBase httpContext)        { return httpContext.Request.IsLocal || base.AuthorizeCore(httpContext);         }     } } 

可以这样使用这个过滤器:[OrAuthorization(Users = "adam, steve, bob", Roles = "admin")]

实现一个自定义的授权失败策略

默认的处理为通过授权的做法是重定向用户到登录页面。但是我不想一直这么做,例如,如果我们使用AJAX,发送一个重定向能让登录页出现在当前页面的中间(类似模态窗口这样的效果)。这时我们可以重写HandleUnauthorizedRequest方法来实现,如下所示:

View Code

using System.Web.Mvc; 

namespace MvcFilters.Infrastructure.Filters { public class AjaxAuthorizeAttribute : AuthorizeAttribute { 

protected override void HandleUnauthorizedRequest(AuthorizationContext context) { 

if (context.HttpContext.Request.IsAjaxRequest()) {                 UrlHelper urlHelper = new UrlHelper(context.RequestContext);                 context.Result = new JsonResult {                     Data = new {                         Error = "NotAuthorized",                         LogOnUrl = urlHelper.Action("LogOn", "Account")                     }, JsonRequestBehavior = JsonRequestBehavior.AllowGet};             } else { base.HandleUnauthorizedRequest(context);             }         }     } } 

使用异常过滤器(Using Exception Filters)

异常过滤器是在调用一个action方法抛出了无法处理的异常时运行。
创建一个异常过滤器(Creating an Exception Filter)
异常过滤器必须实现IExceptionFilter接口:public interface IExceptionFilter {void OnException(ExceptionContext filterContext);}   OnException方法在异常抛出的时候调用。参数是ExceptionContext对象。下面是一个示例:

View Code

using System.Web.Mvc; using System; 

namespace MvcFilters.Infrastructure.Filters { 

public class MyExceptionAttribute: FilterAttribute, IExceptionFilter { 

public void OnException(ExceptionContext filterContext) { 

if (!filterContext.ExceptionHandled &&                 filterContext.Exception is NullReferenceException) { 

filterContext.Result = new RedirectResult("/SpecialErrorPage.html");                 filterContext.ExceptionHandled = true;             }         }     } } 

这个过滤器响应NullReferenceException异常的实例,并在没有其他异常过滤器显示异常被处理的情况下执行。我们重定向用户到错误页面。

使用内置的异常过滤器

HandleErrorAttribute就是内置的实现了IExceptionFilter接口的过滤器,并是创建异常过滤器变得容易。

当一个未处理的并指定了ExceptionType的异常发生时,过滤器会设置HTTP结果代码为500(服务器错误),并呈现在View属性里面指定的视图,如下所示:

[HandleError(ExceptionType=typeof(NullReferenceException), View="SpecialError")]

注意:HandleErrorAttribute只有在web.config文件里面添加了<customErrors mode="On" />才能工作。默认的为RemoteOnly,这意味着在开发过程中HandleErrorAttribute不会拦截异常,当部署到服务器并从另外的计算机发送请求是才起作用。

当呈现一个视图时,HandleErrorAttribute过滤器会传递一个HandleErrorInfo视图模型对象,如下所示:

View Code

@Model HandleErrorInfo @{     ViewBag.Title = "Sorry, there was a problem!"; } 

<p>     There was a <b>@Model.Exception.GetType().Name</b> while rendering <b>@Model.ControllerName</b>'s <b>@Model.ActionName</b> action. </p> <p>     The exception message is: <b><@Model.Exception.Message></b> </p> <p>Stack trace:</p> <pre>@Model.Exception.StackTrace</pre> 

使用Action和Result过滤器

Action和Result过滤器是过多用途的过滤器,可用于任何意图。为了创建这些过滤器类型的内置类,IActionFilter,实现了以上接口。如下:

View Code

namespace System.Web.Mvc { 

public interface IActionFilter { void OnActionExecuting(ActionExecutingContext filterContext); void OnActionExecuted(ActionExecutedContext filterContext);     } } 

接口定义了两个方法,MVC框架在调用Action方法之前调用OnActionExecuting方法,OnActionExecuted方法则是在Action方法调用完成后被调用。

实现OnActionExecuting方法

OnActionExecuting方法在Action方法之前调用,所以,我们可以利用这个机会来检查请求,取消请求,修改请求,或者启用一些活动来跨越action方法。参数类型ActionExecutingContext是ControllerContext的子类并定义了两个属性:ActionDescriptor和Result。我们可以通过Result属性选择性的取消请求,如下所示:

View Code

using System.Web.Mvc; 

namespace MvcFilters.Infrastructure.Filters { 

public class MyActionFilterAttribute : FilterAttribute, IActionFilter { 

public void OnActionExecuting(ActionExecutingContext filterContext) { if (!filterContext.HttpContext.Request.IsSecureConnection) {                 filterContext.Result = new HttpNotFoundResult();             } 

} 

public void OnActionExecuted(ActionExecutedContext filterContext) { // do nothing         }     } } 

上面的例子用来检查请求是否使用了SSL,如果没有则返回404.

实现OnActionExecuted方法

我们也可以使用这个过滤器来执行一些跨越action方法执行的任务,下面的示例计算action方法执行的时间,如下:

View Code

using System.Diagnostics; using System.Web.Mvc; 

namespace MvcFilters.Infrastructure.Filters { 

public class ProfileAttribute : FilterAttribute, IActionFilter { private Stopwatch timer; public void OnActionExecuting(ActionExecutingContext filterContext) {             timer = Stopwatch.StartNew();             } 

public void OnActionExecuted(ActionExecutedContext filterContext) {             timer.Stop(); if (filterContext.Exception == null) {                 filterContext.HttpContext.Response.Write( string.Format("Action method elapsed time: {0}",                          timer.Elapsed.TotalSeconds));             }         }     } } 

实现结果过滤器(Implementing a Result Filter)

Action filters和Result filters有很多共同点。它要实现IResultFilter接口,如下:

View Code

namespace System.Web.Mvc { 

public interface IResultFilter { void OnResultExecuting(ResultExecutingContext filterContext); void OnResultExecuted(ResultExecutedContext filterContext);     } } 

一旦action方法返回了一个action result,OnResultExecuting方法就会被调用,但这是在action result执行之前,OnResultExecuted方法是在action result执行之后。
示例如下:

View Code

using System.Diagnostics; using System.Web.Mvc; 

namespace MvcFilters.Infrastructure.Filters { public class ProfileResultAttribute : FilterAttribute, IResultFilter { private Stopwatch timer; 

public void OnResultExecuting(ResultExecutingContext filterContext) {             timer = Stopwatch.StartNew();         } 

public void OnResultExecuted(ResultExecutedContext filterContext) {             timer.Stop();             filterContext.HttpContext.Response.Write( string.Format("Result execution - elapsed time: {0}",                         timer.Elapsed.TotalSeconds));         }     } } 

使用内置的Action和Result过滤器类

MVC框架包含了能够创建action和result过滤器的内置类,但是没有提供任何有用的功能,这个ActionFilterAttribute类如下所示:

View Code

public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter{ 

public virtual void OnActionExecuting(ActionExecutingContext filterContext) {         } 

public virtual void OnActionExecuted(ActionExecutedContext filterContext) {         } 

public virtual void OnResultExecuting(ResultExecutingContext filterContext) {         } 

public virtual void OnResultExecuted(ResultExecutedContext filterContext) {         }     } } 

下面是一个从它派生的过滤器,如下:

View Code

using System.Diagnostics; using System.Web.Mvc; 

namespace MvcFilters.Infrastructure.Filters { 

public class ProfileAllAttribute : ActionFilterAttribute { private Stopwatch timer; 

public override void OnActionExecuting(ActionExecutingContext filterContext) {             timer = Stopwatch.StartNew();         } 

public override void OnActionExecuted(ActionExecutedContext filterContext) {             timer.Stop();             filterContext.HttpContext.Response.Write( string.Format("Action method elapsed time: {0}",                     timer.Elapsed.TotalSeconds));         } public override void OnResultExecuting(ResultExecutingContext filterContext) {             timer = Stopwatch.StartNew();         } 

public override void OnResultExecuted(ResultExecutedContext filterContext) {             timer.Stop();             filterContext.HttpContext.Response.Write( string.Format("Action result elapsed time: {0}",                     timer.Elapsed.TotalSeconds));         }     } } 

使用其他过滤功能

除了上面介绍的过滤器以外,还有一些非常有趣但是用的并不那么广泛的过滤功能。如下:

不使用特性的过滤

使用过滤器常规的方式是创建和使用特性(attributes),然而有一种可以替代的方式。Controller类实现IAuthorizationFilter,  IActionFilter,  IResultFilter, IExceptionFilter这些接口,同时也提供了每一种OnXXX方法的虚拟实现。下面是计算action方法执行时间的实现,如下:

View Code

using System.Diagnostics; using System.Web.Mvc; 

namespace MvcFilters.Controllers { 

public class SampleController : Controller { private Stopwatch timer; 

public ActionResult Index() { return View();         } 

protected override void OnActionExecuting(ActionExecutingContext filterContext) {             timer = Stopwatch.StartNew();         } 

protected override void OnActionExecuted(ActionExecutedContext filterContext) {             timer.Stop();             filterContext.HttpContext.Response.Write( string.Format("Action method elapsed time: {0}",                     timer.Elapsed.TotalSeconds));         } 

protected override void OnResultExecuting(ResultExecutingContext filterContext) {             timer = Stopwatch.StartNew();         } 

protected override void OnResultExecuted(ResultExecutedContext filterContext) {             timer.Stop();             filterContext.HttpContext.Response.Write( string.Format("Action result elapsed time: {0}",                     timer.Elapsed.TotalSeconds));         }     } } 

这种技术在我们创建一个基类,该基类从项目里面多个控制器派生出来。过滤的重点就是把跨应用程序所需的代码放在一个可重复使用的位置。对我们的项目而言,我们宁愿使用特性。这样能够将控制逻辑和过滤逻辑分开。

使用全局过滤

全局过滤是应用到所有的action方法,通过如下的方式实现:

public class MvcApplication : System.Web.HttpApplication { 

public static void RegisterGlobalFilters(GlobalFilterCollection filters)//在Application_Start里面调用   {         filters.Add(new HandleErrorAttribute());  filters.Add(new ProfileAllAttribute()); //注意这里一定是完整的类名,不能是ProfileAll。一旦我们在这里注册了过滤器,将应用与所有的action    } ... 

过滤执行排序

前面解释了过滤器按类型被执行,顺序是:authorization过滤器,action过滤器,result过滤器。如果在执行的任何一步出现未处理的异常,异常过滤器都会被执行。然而在每一个类型里面,我们能够控制个别的过滤器的顺序。如下:

View Code

using System; using System.Web.Mvc; 

namespace MvcFilters.Infrastructure.Filters { 

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple=true)] public class SimpleMessageAttribute : FilterAttribute, IActionFilter { 

public string Message { get; set; } 

public void OnActionExecuting(ActionExecutingContext filterContext) {             filterContext.HttpContext.Response.Write( string.Format("[Before Action: {0}]", Message));         } 

public void OnActionExecuted(ActionExecutedContext filterContext) {             filterContext.HttpContext.Response.Write( string.Format("[After Action: {0}]", Message));                     }     } } 

在action里面使用如下:

View Code

... [SimpleMessage(Message="A")] [SimpleMessage(Message="B")] public ActionResult Index() {     Response.Write("Action method is running"); return View(); } ... 

运行结果如下:

如果我们要指定顺序可以这样:

View Code

... [SimpleMessage(Message="A", Order=2)] [SimpleMessage(Message="B", Order=1)] public ActionResult Index() {     Response.Write("Action method is running"); return View(); } ... 

运行程序如下:

如果我们不给order指定一个具体的值,默认会是-1。如果我们混淆了过滤器以至于一些有其他的值,一些没有,这些没有值的将会首先被执行。如果多个filters有同样的值,那么MVC框架根据它们被使用的地方来决定执行顺序。全局过滤器最先执行,然后应用在controller类上面的,最后是action上面的过滤器执行。

使用内置的过滤器

MVC框架提供了一些内置的过滤器,以备我们在程序里面直接使用。如下所示:


好了,本章的笔记到这就结束了,祝大家愉快!

时间: 2024-10-27 01:49:30

《Pro ASP.NET MVC 3 Framework》学习笔记之二十五【Filters】的相关文章

WPF and Silverlight学习笔记(二十五)

WPF and Silverlight学习笔记(二十五):使用CollectionView实现对绑定数据的排序.筛选.分组 在第二十三节,我们使用CollectionView实现了对于绑定数据的导航,除导 航功能外,还可以通过CollectionView对数据进行类似于DataView的排序.筛选 等功能. 一.数据的排序: 使用第二十四节的数据源,查询所有 的产品信息: 1: <Window x:Class="WPF_24.CollectionViewSortData" 2:

ASP.NET MVC 3 Framework学习笔记之Model Templates

.使用模板化的视图Helpers(Using Templated View Helpers) 模版化视图helpers的创意就是它们更加灵活.我们不用自己去指定应该用什么HTML元素来呈现一个模型的属性,MVC自己会搞定,在我们更新了视图模型时,也不用手动的更新视图.下面是一个例子:  代码如下 复制代码 //在Models里面添加Persons.cs using System; using System.Collections.Generic; using System.Linq; using

《Pro ASP.NET MVC 3 Framework》学习笔记目录

<Pro ASP.NET MVC 3 Framework>简介: 作者: Adam Freeman 和 Steven Sanderson 出版社: Apress; New 平装: 820页 语种: 英语 ISBN: 1430234040 声明:笔记里面按我自己的理解翻译了大部分内容,写这个笔记的目的:为了方便自己查阅,也为园友提供学习的方便. 我无意侵犯作者的任何权利,仅仅为了自己学习.也希望路过的朋友不要用于任何商业目的. 第一部分 ASP.NET MVC3介绍   <Pro ASP.

《Pro ASP.NET MVC 3 Framework》学习笔记之一【MVC的历程,优点,HelloWorld】

序论: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 Sa

ASP.NET MVC Web API 学习笔记----HttpClient简介

  1. HttpClient简单介绍  依稀还记得那个时候用WebClient,HttpWebRequest来发送一个请求,现在ASP.NET MVC4中自带了一个类HttpClient,用于接收HttpResponseMessage和发送HttpRequestMesssage. 问题在于既然WebClient,HttpWebRequest可以完成相应的功能,为什么还要使用HttpClient类,.NET Framework中既然提出了这样一个类肯定是有其特别之处的,这里罗列几个不同之处: (

ASP.NET MVC Web API 学习笔记---联系人增删改查

本章节简单介绍一下使用ASP.NET MVC Web API 做增删改查.目前很多Http服务还是通过REST或者类似RESP的模型来进行数据操作的.下面我们通过创建一个简单的Web API来管理联系人          说明:为了方便数据不使用真正的数据库,而是通过内存数据模拟    1.       Web API中包含的方法 Action HTTP method Relative URI GetAllContact GET /api/contact GetContact GET /api/

《Pro ASP.NET MVC 3 Framework》学习笔记之九【Ninject的使用-下】

接着上次的Ninject的笔记,如果你是初次路过,可以先看看我前面的笔记. 一,创建依赖链(Chains of Dependency) 当我们向Ninject请求创建一个类型时,Ninject会去检查该类型和其他类型之间的耦合关系.如果有额外的依赖,Ninject也会解析它们并创建我们需要的所有类的实例.为了进一步说明,我们创建一个新的接口和一个实现该接口的类.请注意我们的例子是跟前面的笔记衔接的,所以如果你打算跟着一起操作的话,最好能够去看看前面的笔记. 创建一个IDiscountHelper

《Pro ASP.NET MVC 3 Framework》学习笔记之四【领域模型介绍】

主题:应用领域驱动开发(Applying Domain-Driven Development) Domain Model是MVC程序的"心脏",其他的一切,包括Controllers和Views仅仅是用来跟Domain Model交互的一种方式,ASP.NET MVC并没有限制使用在Domain Model上面的技术,我们可以自由的选择跟.net framework交互的技术,并且这样的选择是非常多的.不仅如此,ASP.NET MVC为我们提供了基础的架构和约定来帮助Domain Mo

《Pro ASP.NET MVC 3 Framework》学习笔记之五【依赖注入及ninject工具使用】

一,创建松耦合的组件 1."分解关注点"是MVC模式里面一个非常重要的特性.我们想要在应用程序里面创建的组件尽可能的独立,这样我们就能管理比较少的依赖关系.理想情况下,每个组件都是孤立的,不知道其他组件的存在,处理应用程序的其他领域仅仅通过抽象接口,这就是所谓的松耦合,它让我们的应用程序更加容易测试和修改.通过一个简单的例子可以帮助我们理解,假如我们想写一个发邮件的组件,暂且就把这个组件命名为MyEmailSender,接着我们实现一个接口,这个接口定义了所有需要发送邮件的功能,也暂且