理解MVC应用程序执行过程
基于ASP.NET MVC Web应用程序的请求首先通过一个UrlRoutingModule的对象(HTTP模块)。这个模块匹配请求,并且执行路由选择。这个UrlRoutingModule对象选择第一个匹配当前请求的路由对象。如果没有路径匹配,这个UrlRoutingModule什么也不做,让这个请求返回给常规的ASP.NET或者IIS来请求处理。
从这个被选中的Route对象,UrlRoutingModule对象获得IRouteHandler对象(IRouteHandler对象与Route对象是相互关联的)。一般来说,在一个MVC应用程序中,它将是MvcRouteHandler实例。这个IRouteHandler实例创建一个IHttpHandler对象,并且将它传递给IHttpContext对象。默认情况下,MVC IHttpHandler实例就是MvcHandler对象。然后,这个MvcHandler对象选择controller,controller将最终提交这个请求。
这个module 和 handler是ASP.NET MVC框架的入口点。它们执行下列行为:
选择合适的controller。
获得一个具体controller实例。
调用controller的执行方法。
下表列出了一个MVC Web项目的执行的各阶段。
阶段 | 详细 |
接收应用程序的第一次请求 | 在Global.asax文件中, Route对象 被添加到RouteTable对象. |
执行路由选择 | UrlRoutingModule 模块使用第一个在RouteTable 集合中匹配的Route 对象来创建RouteData对象, 然后它将使用这个RouteData对象来创建RequestContext (IHttpContext)对象. |
创建MVC request handler | MvcRouteHandler 创建MvcHandler类的一个实例,并且将它传递给RequestContext实例. |
创建controller | MvcHandler对象使用RequestContext实例来确认IControllerFactory 对象(DefaultControllerFactory类的一个实例) ,以用来创建conteoller实例。 |
执行controller | MvcHandler 实例调用controller的执行method. |
调用action | 大部分controllers 继承自Controller基础类. 与controller相关联的ControllerActionInvoker 对象决定这个controller类的哪个方法将被调用 , 然后再调用那个方法. |
执行result | 一个典型的action 方法可能接收用户输入,准备合适的响应数据, 然后通过返回一个result的类型来执行这个result. 这个内置的能够执行的result 类型 包含以下类型: ViewResult (它呈现一个视图,并且是最常用的result类型), RedirectToRouteResult, RedirectResult, ContentResult, JsonResult以及EmptyResult. |
ASP.NET Routing模块的责任是将传入的浏览器请求映射为特有的MVC controller actions。
使用默认的Route Table
当你创建一个新的ASP.NET MVC应用程序,这个应用程序已经被配置用来使用ASP.NET Routing。 ASP.NET Routing 在2个地方设置。第一个,ASP.NET Routing 在你的应用程序中的Web配置文件(Web.config文件)是有效的。在配置文件中有4个与routing相关的代码片段:system.web.httpModules代码段,system.web.httpHandlers 代码段,system.webserver.modules代码段以及 system.webserver.handlers代码段。千万注意不要删除这些代码段,如果没有这些代码段,routing将不再运行。第二个,更重要的,route table在应用程序的Global.asax文件中创建。这个Global.asax文件是一个特殊的文件,它包含ASP.NET 应用程序生命周期events的event handlers。这个route table在应用程序的起始event中创将。
在Listing 1中包含ASP.NET MVC应用程序的默认Global.asax文件.
Listing 1 - Global.asax.cs
2{
3publicstaticvoidRegisterRoutes(RouteCollectionroutes)
4{
5routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
6routes.MapRoute(
7"Default",//路由名称
8"{controller}/{action}/{id}",//带有参数的URL
9new{controller="Home",action="Index",id=UrlParameter.Optional}//参数默认值
10);
11
12}
13
14protectedvoidApplication_Start()
15{
16AreaRegistration.RegisterAllAreas();
17
18RegisterRoutes(RouteTable.Routes);
19}
20}
当一个MVC应用程序第一个启动,Application_Start() 方法被调用,这个方法反过来调用RegisterRoutes() 方法。
这个默认的route table包含一个单一的route。这个默认的route将url的第一个段映射为一个controller名称,url的第二个段映射为一个controller action,第三个段映射为命名为id的参数。
假如,你在网页浏览器的地址栏中键入下面的url:/Home/Index/3,这个默认的route将这个url映射为下面的参数:
controller = Home controller名称
action = Index controller action
id = 3 id的参数
当你请求/Home/Index/3这样的url,下面的代码将执行。HomeController.Index(3)
这个默认的route包含3个默认的参数。如果你没有提供一个 controller,那么 controller默认为Home。同样,action默认为Index,id参数默认为空字符串。
让我们来看一些关于默认的route怎么映射urls为controller actions的例子。假如你在你的浏览器地址栏中输入如下的url:/Home,由于这些默认的route参数有一些相关的默认值,键入这样的URL,将导致HomeController类的Index()方法(如Listing 2)被调用。
2{
3[HandleError]
4publicclassHomeController:Controller
5{
6publicActionResultIndex(stringid)
7{
8ViewData["Message"]="欢迎使用ASP.NETMVC!";
9
10returnView();
11}
12
13publicActionResultAbout()
14{
15returnView();
16}
17}
18}
19
20
在Listing 2中,这个HomeController 类包含一个名为Index()的方法。这个URL /Home导致Index()方法被调用,一个空的字符串将作为id参数的值。由于mvc框架调用controller actions的这种方式,这个URL /Home同样匹配HomeController类中的Index()方法(如Listing 3)。
Listing 3 - HomeController.cs (Index action with no parameter)
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
在Listing 3中,这个Index()方法不接收任何参数。这个URL /Home将导致Index()方法被调用。URL /Home/Index/3同样调用这个方法(ID被忽略)。
Listing 4 - HomeController.cs (Index action with nullable parameter)
[HandleError]
public class HomeController : Controller
{
public ActionResult Index(int? id)
{
return View();
}
}
在Listing 4中, Index() 方法有一个整数参数. 由于这个参数是可空参数 , Index() 将被调用而不引起错误.
最后, 使用 URL /Home 来调用如Listing 5中的Index() 方法 将导致异常,因为这个ID参数不是一个可空的参数。如果你试图去调用这个Index()方法,你将获得如下图所示的错误。
Listing 5 - HomeController.cs (Index action with Id parameter)
[HandleError]
public class HomeController : Controller
{
public ActionResult Index(int id)
{
return View();
}
}
另一方面,使用如Listing 5中的Index controller action,URL /Home/Index/3运行正常。Index controller action in Listing 5. /Home/Index/3请求将导致Index()方法被调用,ID参数拥有一个3的值。
总结
这是一个关于ASP.NET Routing的简要介绍. 应该了解了这个默认的route如何将URLs映射为controller actions。
创建自定义的Routes (C#)
这个教程,你将学会怎样添加一个自定义的route到一个asp.net mvc应用程序。你将学会在Global.asax文件中,怎样使用一个自定义的route来修改这个默认的route table。
对于许多简单的ASP.NET MVC 应用程序,这个默认的route table将运行得很好。然而,你可能发现,你可能特定的routing 需求。那样的话,你可能需要创建一个自定义的route。
设想一下,例如,你正在建立一个博客应用程序,你可能想要去处理像/Archive/12-25-2009的输入请求。
当一个用户键入这个请求,你想要返回与日期为12/25/2009相符的博客实体。为了处理这种类型的请求,你需要去创建一个自定义的route。
在 Listing 1中,这个Global.asax文件中包含一个新的名为Blog的自定义route,它处理类似于/Archive/entry date的请求。
Listing 1 - Global.asax (with custom route)
2usingSystem.Collections.Generic;
3usingSystem.Linq;
4usingSystem.Web;
5usingSystem.Web.Mvc;
6usingSystem.Web.Routing;
7
8namespaceMvcRoutingApp
9{
10//注意:有关启用IIS6或IIS7经典模式的说明,
11//请访问http://go.microsoft.com/?LinkId=9394801
12
13publicclassMvcApplication:System.Web.HttpApplication
14{
15publicstaticvoidRegisterRoutes(RouteCollectionroutes)
16{
17routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
18routes.MapRoute(
19"Blog",//路由名称
20"Archive/{entryDate}/{id}",//带有参数的URL
21new{controller="Archive",action="Entry",id=UrlParameter.Optional}//参数默认值
22);
23routes.MapRoute(
24"Default",//路由名称
25"{controller}/{action}/{id}",//带有参数的URL
26new{controller="Home",action="Index",id=UrlParameter.Optional}//参数默认值
27);
28
29}
30
31protectedvoidApplication_Start()
32{
33AreaRegistration.RegisterAllAreas();
34
35RegisterRoutes(RouteTable.Routes);
36}
37}
38}
你添加到route table的routes的顺序是很重要的。我们新自定义的blog route在现存的默认route之前添加。如果你颠倒了顺序,那么这个默认的route总是先调用而不是这个自定义的route。
这个自定义的blog toute匹配任何以 /Archive/ 开头的请求。所以,它匹配所有下列URLs:
/Archive/12-25-2009
/Archive/10-6-2004
/Archive/apple
这个自定义的route将输入的请求映射至名为Archive的controller,并且调用 Entry() action。当 Entry() action被调用的时候,这个输入的日期被当作名为entryDate的参数。
Listing 2 - ArchiveController.cs
public class ArchiveController : Controller
{
public string Entry(DateTime entryDate)
{
return "You requested the date:" + entryDate.ToString();
}
}
注意,在Listing 2中这个Entry()方法接收一个类型为DateTime的参数。MVC框架是足够智能的,它自动将URL中输入的date转换为一个DateTime值。如果URL中输入的date不能转换为DateTime,错误将被引发。
总结
这个教程演示怎样来创建一个自定义的route。你学会了怎样在Global.asax 文件中添加一个自定义的route到route table。我们讨论了怎样为blog实体将请求映射为名为ArchiveController的controller,名为Entry()的controller action
创建一个路由约束(C#)
你能够使用路由约束来限制匹配一个特殊路径的浏览器请求。你能够使用一个正则表达式来制定一个路由约束。
例如,假设你已经定义路由如下:
Listing 1 - Global.asax.cs
routes.MapRoute(
"Product",
"Product/{productId}",
new {controller="Product", action="Details"}
);
Listing 1 包含一个命名为Product的路由. 你能够使用这个 Product route来将将浏览器请求映射到ProductController,如下:
Listing 2 - Controllers/ProductController.cs
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
public class ProductController : Controller
{
public ActionResult Details(int productId)
{
return View();
}
}
}
注意:Details() action 接收一个命名为 productId的单一参数. 这个参数是整型参数.
在Listing 1 will中定义的route将匹配一下的任何一个URLs:
?/Product/23
?/Product/7
遗憾的,这个route也同样匹配以下的URLs:
?/Product/blah
?/Product/apple
因为Details() action预期接收一个整型的参数,当请求中包含的内容不同于整数时,它将导致一个错误。
你真正想要做的,仅仅是匹配包含一个的整数productId的URLs。当你定义一个route时,你能够使用一个限制条件来限制URLs,使它匹配这个route。在Listing 3中,这个route包含一个只匹配整数的正则表达式约束。
Listing 3 - Global.asax.cs
routes.MapRoute(
"Product",
"Product/{productId}",
new {controller="Product", action="Details"},
new {productId = @"/d+" }
);
这个真正表达式约束/d+ 匹配一个或多个整数. 这个约束导致Product route匹配如下的URLs:
?/Product/3
?/Product/8999
但不是如下的URLs:
?/Product/apple
?/Product
这个浏览器请求将被另一个route处理。或者,如果没有匹配的routes, “The resource could not be found ”错误将被返回.
创建一个自定义路由约束 (C#)
演示如何创建一个自定义的路由约束.约束接口中的Match方法如下:
IRouteConstraint.Match Method
bool Match(
HttpContextBase httpContext,
Route route,
string parameterName,
RouteValueDictionary values,
RouteDirection routeDirection
)
你可以通过实现IRouteConstraint接口来创建一个路径约束,并且通过几个步骤把它添加到你的路径中。IRouteConstraint仅有一个Match方法,它返回一个布尔值。这个布尔值决定该请求是否应该被route对象处理。
如何创建一个ASP.NET MVC应用程序来模拟一个仅仅在视图中显示年份,月份,日期的文章系统,类似于博客系统的路径?
(一)首先,创建一个ArchiveController,它包含一个仅仅显示年份,月份,日期值的Index action 方法。
{
publicclassArchiveController:Controller
{
//
//GET:/Archive
publicActionResultIndex(intyear,intmonth,intday)
{
ViewData["Year"]=year;
ViewData["Month"]=month;
ViewData["Day"]=day;
returnView();
}
}
}
(二)创建一个显示数据的view。
<asp:ContentID="Content1"ContentPlaceHolderID="TitleContent"runat="server">
Index
</asp:Content>
<asp:ContentID="Content2"ContentPlaceHolderID="MainContent"runat="server">
<h2>Index</h2>
<fieldset>
<legend>Fields</legend>
<p>Year:
<%=ViewData["Year"]%>
</p><p>
Month:
<%=ViewData["Month"]%>
</p><p>
Day:
<%=ViewData["Day"]%></p>
</fieldset>
</asp:Content>
(三)最主要的步骤,需要创建年份,月份,日期验证的三个分离的约束。它们将在路径定义中应用。以创建一个DayConstraint来开始。
usingSystem.Globalization;
namespaceMvcAppRouting.RouteConstraints
{
publicclassDayConstraint:System.Web.Routing.IRouteConstraint
{
publicboolMatch(HttpContextBasehttpContext,Routeroute,stringparameterName,RouteValueDictionaryvalues,RouteDirectionrouteDirection)
{
if((routeDirection==RouteDirection.IncomingRequest)&&(parameterName.ToLower(CultureInfo.InvariantCulture)=="day"))
{
try{
intmonth=int.Parse(values["Month"].ToString());
intday=int.Parse(values["Day"].ToString());
if(month<=0||month>12)returnfalse;
if(day<1)returnfalse;
switch(month)
{
case1:
case3:
case5:
case7:
case8:
case10:
case12:
if(day<32)returntrue;
break;
case2:
if(day<29)returntrue;
break;
case4:
case6:
case9:
case11:
if(day<31)returntrue;
break;
}
}
catch{
returnfalse;
}
}
returnfalse;
}
}
}
年份数据限制为1950-2010。同样,月份的值在1-12之间,此处不再叙述,详见源代码。
(四)最后一步是将所有的联系在一起,使ASP.NET MVC 应用程序能够运行。这里仅仅是定义一个routes。
{
//注意:有关启用IIS6或IIS7经典模式的说明,
//请访问http://go.microsoft.com/?LinkId=9394801
publicclassMvcApplication:System.Web.HttpApplication
{
publicstaticvoidRegisterRoutes(RouteCollectionroutes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",//路由名称
"{controller}/{action}/{id}",//带有参数的URL
new{controller="Home",action="Index",id=UrlParameter.Optional}//参数默认值
);
routes.MapRoute(
"Archive",
"archive/{year}/{month}/{day}",
new
{
controller="Archive",
action="Index",
year="",
month="",
day=""
},
new
{
year=newRouteConstraints.YearConstraint(),
month=newRouteConstraints.MonthConstraint(),
day=newRouteConstraints.DayConstraint()
}
);
}
protectedvoidApplication_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
}
}
实例中的“archive/{year}/{month}/{day}”模式,像正常的routes一样,同样为route设置了默认的值,并且增加了一个约束对象。这个约束对象将模式中的参数映射至它的约束实例中,因此这些值能够被验证。
现在我用一个验证的请求模式来运行这个应用程序,展示的页面如下。
同样,发送一个archive/2000/2/30这个请求,它是不能通过验证,并且得到一个错误。
总结:
应该注意约束条件必须继承IRouteConstraint,并且实现Match方法
创建一个自定义action必须满足的要求
方法必须为公共的.
方法不能为静态方法.
方法不能是Control基类中的方法(如:ToString,GetHashCode等)方法不能为扩展方法.
方法不能为一个构造函数 ,getter, setter.
方法不能包含ref 或 out 参数.
使用 NonActionAttribute 特性将阻止该action被调用
{
[HandleError]
publicclassUserDemoController:Controller
{
//
//GET:/UserDemo/
//自定义一个简单的方法
[NonAction]
//publicsealedclassNonActionAttribute表示一个特性,该特性用于指示控制器方法不是操作方法。
publicstringDisplayString()
{
return"thisisademostring!";
}
}
}
理解Views
相对于ASP.NET与 Active Server Pages, ASP.NET MVC 并不包含任何直接对应的一个页面。在ASP.NET MVC 应用程序中,你键入浏览器地址栏中的URL在磁盘上并没有相应的一个页面,该URL被映射为controller actions。与页面page最相近的正是我们所说的View。
最基本的如下:
{
returnView();
}
为了探究view的本质,以显示如下的结果:
{
publicRssActionResultRssShow()
{
returnnewRssActionResult();
}
}
我们需要创建一个继承ActionResult的RssActionResult类,如下所示:
{
/*
*System.Web.Mvc
publicabstractclassActionResult
{
protectedActionResult();
publicabstractvoidExecuteResult(ControllerContextcontext);
}*/
publicclassRssActionResult:ActionResult
{
publicRssActionResult()
{
}
//
publicoverridevoidExecuteResult(ControllerContextcontext)
{
if(context==null)
{
thrownewArgumentNullException("ControllerContextisnull!");
}
HttpResponseBaseresponse=context.HttpContext.Response;
Rssrss=newRss();
rss.CreateSampleRss(response);
}
}
通过从 System.Web.Mvc.ActionResult 类继承的自定义类型,ExecuteResult(ControllerContextcontext)启用对操作方法结果的处理。
附:ExecuteResult()中的rss.CreateSampleRss(response)方法通过利用HttpResponseBase来处理响应流。
{
XmlTextWriterwriter=newXmlTextWriter(response.OutputStream,System.Text.Encoding.UTF8);
WriteRssHeader(writer);
for(inti=0;i<50;i++)
{
WriteRssItem(writer,"demotitle:jasenkin"+i.ToString(),http://jasenkin/,"decription:--->"+i.ToString());
}
WriteRssBottom(writer);
writer.Flush();
writer.Close();
response.ContentEncoding=System.Text.Encoding.UTF8;
response.ContentType="text/xml";
response.Cache.SetCacheability(HttpCacheability.Public);
response.End();
}
执行结果如下:
一个典型的Action可能接收用户输入,准备合适的响应数据, 然后通过返回一个Result的类型(如上例中的RssActionResult),系统将自动调用这个Result类型(如上例中的RssActionResult)的ExecuteResult(context)来响应浏览器请求,呈现的就是我们所说的View了(如上图)。
这仅仅是一个继承自actionresult的自定义类,其中的ExecuteResult()方法才是该类的关键之处
Action filter 是能够应用于controller action --或整个controller的一个特性,它们的基类为System.Web.Mvc.FilterAttribute 。它限定了action执行的方式。ASP.NET MVC框架包含数个action filters。
- HandleError – 这个action 过滤器处理controller action执行时出现的错误。
- OutputCache – 这个action 过滤器将 controller action的输出缓存一段制定的时间 .
- Authorize – 这个action 过滤器使你能够限制特定的用户或角色的访问.
使用Action Filter
action filter是一个特性. 你能够应用大部分的action filters 在单个的controller action 或者整个controller上.
例如下面的Data controller有一个返回当前时间的Index()方法.这个action拥有OutputCache
action filter. 这个过滤器导致由action返回的值能够缓存10秒钟.
VaryByParam 属性使用的设置不建议通过设置“*”的值来使用所有参数进行区分。这可能会导致缓存溢出。
{
//
//GET:/Data/
[OutputCache(Duration=20,VaryByParam="")]
publicstringIndex()
{
returnDateTime.Now.ToString();
}
}
如果你重复调用Index()
action(不断刷新当前页面), 那么你将看到当前的内容在Duration=20秒内是不变的.
一个单一的action filter – OutputCache
action filter – 被应用于Index()
方法. 同样,你可以应用多个action filters 在同一个action上.
不同类型的Filters
ASP.NET MVC框架支持多种不同类型的过滤器:
- Authorization filters – 实现
IAuthorizationFilter
特性. - Action filters – 实现
IActionFilter
特性. - Result filters – 实现
IResultFilter
特性. - Exception filters –实现
IExceptionFilter
特性.
Filters 按照上面列出的顺序执行。例如, authorization filters 总是在action filters之前执行,exception filters在所有其他类型的filter之后执行.
ActionFilterAttribute 基类
为了使你能够更加容易的实现自定义的action filter, ASP.NET MVC框架包含一个ActionFilterAttribute
基类. 这个类实现了IActionFilter
与IResultFilter
接口,并且继承了Filter
类。
ActionFilterAttribute
基类拥有以下可以重载的方法:
- OnActionExecuting在action method调用前发生。
- OnActionExecuted在action method调用后发生, 但是在result执行前发生 (在 view 呈现前)
- OnResultExecuting在result执行前发生(在view 呈现前)
- OnResultExecuted 在result执行后发生(在view 呈现后)
创建一个ASP.NET MVC OutputCache ActionFilterAttribute
使用ASP.NET MVC 框架, 简单的指定OutputCache 指令并不能达到理想的效果. 幸好, ActionFilterAttribute让你能够在 controller action执行的前后运行代码.
让我们使用类似的方法来创建OutputCache ActionFilterAttribute。
publicActionResultIndex()
{
//...
}
我们将使用命名为CachePolicy的枚举类型来指定OutputCache 特性应怎样以及在哪里进行缓存:
{
NoCache=0,
Client=1,
Server=2,
ClientAndServer=3
}
1.实现client-side缓存
事实上,这是很容易的。在view呈现前,我们将增加一些HTTP头到响应流。网页浏览器将获得这些头部,并且通过使用正确的缓存设置来回应请求。如果我们设置duration为60,浏览器将首页缓存一分钟。
namespaceMVCActionFilters.Web.Models
{
publicclassOutputCache:System.Web.Mvc.ActionFilterAttribute
{
publicintDuration{get;set;}
publicCachePolicyCachePolicy{get;set;}
publicoverridevoidOnActionExecuted(ActionExecutedContextfilterContext)
{
if(CachePolicy==CachePolicy.Client||CachePolicy==CachePolicy.ClientAndServer)
{
if(Duration<=0)return;
//用于设置特定于缓存的HTTP标头以及用于控制ASP.NET页输出缓存
HttpCachePolicyBasecache=filterContext.HttpContext.Response.Cache;
TimeSpancacheDuration=TimeSpan.FromSeconds(Duration);
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.Now.Add(cacheDuration));
cache.SetMaxAge(cacheDuration);
cache.AppendCacheExtension("must-revalidate,proxy-revalidate");
}
}
}
}
2. 实现server-side缓存
Server-side 缓存有一点难度. 首要的,在输出缓存系统中,我们将不得不准备HTTP响应为可读的。为了这样做,我们首先保存当前的HTTP context到类的一个变量中. 然后, 我们创建一个新的httpcontext ,通过它将数据写入StringWriter,同时允许读操作可以发生:
writer=newStringWriter();
HttpResponseresponse=newHttpResponse(writer);
HttpContextcontext=newHttpContext(existingContext.Request,response)
{
User=existingContext.User
};
System.Web.HttpContext.Current=context;
{
if(CachePolicy==CachePolicy.Server||CachePolicy==CachePolicy.ClientAndServer)
{
//获取缓存实例
cache=filterContext.HttpContext.Cache;
//获取缓存数据
objectcachedData=cache.Get(GenerateKey(filterContext));
if(cachedData!=null)
{
//返回缓存数据
cacheHit=true;
filterContext.HttpContext.Response.Write(cachedData);
filterContext.Cancel=true;
}
else
{//重新设置缓存数据
existingContext=System.Web.HttpContext.Current;
writer=newStringWriter();
HttpResponseresponse=newHttpResponse(writer);
HttpContextcontext=newHttpContext(existingContext.Request,response)
{
User=existingContext.User
};
foreach(varkeyinexistingContext.Items.Keys)
{
context.Items[key]=existingContext.Items[key];
}
System.Web.HttpContext.Current=context;
}
}
}
利用该代码,我们能从高速缓存中检索现有项,并设置了HTTP响应能够被读取。在视图呈现之后,将数据存储在高速缓存中:
{
//服务器端缓存?
if(CachePolicy==CachePolicy.Server||CachePolicy==CachePolicy.ClientAndServer)
{
if(!cacheHit)
{
//存储原有的context
System.Web.HttpContext.Current=existingContext;
//返回呈现的数据
existingContext.Response.Write(writer.ToString());
//增加数据到缓存
cache.Add(
GenerateKey(filterContext),
writer.ToString(),
null,
DateTime.Now.AddSeconds(Duration),
Cache.NoSlidingExpiration,
CacheItemPriority.Normal,
null);
}
}
}
你现在注意到添加了一个VaryByParam到 OutputCache ActionFilterAttribute。当缓存server-side时,我可以通过传入的参数来改变缓存存储。这个GenerateKey方法会产生一个依赖于controller,action和VaryByParam的键。
{
StringBuildercacheKey=newStringBuilder();
//Controller+action
cacheKey.Append(filterContext.Controller.GetType().FullName);
if(filterContext.RouteData.Values.ContainsKey("action"))
{
cacheKey.Append("_");
cacheKey.Append(filterContext.RouteData.Values["action"].ToString());
}
//Variationbyparameters
List<string>varyByParam=VaryByParam.Split(';').ToList();
if(!string.IsNullOrEmpty(VaryByParam))
{
foreach(KeyValuePair<string,object>pairinfilterContext.RouteData.Values)
{
if(VaryByParam=="*"||varyByParam.Contains(pair.Key))
{
cacheKey.Append("_");
cacheKey.Append(pair.Key);
cacheKey.Append("=");
cacheKey.Append(pair.Value.ToString());
}
}
}
returncacheKey.ToString();
}
现在你可以增加OutputCache attribute到应用程序的任何一个controller 与controller action中。
publicstringCache()
{
returnDateTime.Now.ToString();
}
设置CachePolicy为Common.CachePolicy.Client时,将直接在客户端缓存中读取数据。
总结
需注意事件的发生时间段
相关推荐
ASP.NET MVC4 CMS 是一个基于微软的ASP.NET MVC4框架构建的内容管理系统,它提供了一种高效、可扩展...通过深入研究其源代码,开发者可以学习到如何构建高效、可扩展的Web应用,并提升在ASP.NET MVC平台上的开发技能。
通过本书的学习,读者可以全面掌握ASP.NET MVC的开发,并从代码中获取软件开发与架构设计的经验与灵感。本书具有很大的参考价值,既适合ASP.NET MVC开发初学者阅读,也适合有一定基础的ASP.NET MVC开发人员进行技术...
学习ASP.NET MVC5,开发者可以掌握Web应用程序的高级开发技巧,包括如何组织项目结构、如何处理用户输入、如何进行数据库操作、如何实现用户认证和授权,以及如何调试和测试代码。"J.T.ASP.NET MVC 5.pdf"这个文件很...
ASP.NET MVC学习笔记-Controller与View传值.
Asp.Net MVC是一种基于模型-视图-控制器(Model-View-Controller)设计模式的Web应用程序开发框架。它由微软公司推出,旨在...通过学习这些案例,开发者可以逐步掌握Asp.Net MVC的精髓,从而高效地构建现代Web应用。
ASP.NET MVC5 是微软开发的一款用于构建Web应用程序的框架,它结合了模型-视图-控制器(MVC)设计模式、ASP.NET Web Forms组件以及Web API功能,为开发者提供了更灵活、可测试的Web开发解决方案。这本书《ASP.NET ...
在这个"asp.net mvc 示例项目"中,我们可以深入学习和理解ASP.NET MVC的核心概念和实践技巧。 首先,我们来探讨一下ASP.NET MVC的核心组成部分: 1. **模型(Model)**:模型是应用程序中的业务逻辑和数据处理部分...
过去的几年里,很多人要求ASP.NET的一件事情就 是对使用基于model-view-controller(模型-视 图-控制器,简称MVC)架构来开发web应用的内置 支持。。
为了理解这个基于ASP.NET MVC的项目,你可以按照以下步骤进行学习: - **了解基本概念**:首先,你需要熟悉MVC模式的基本原理,以及ASP.NET MVC框架的关键组件。 - **安装环境**:确保你已安装了Visual Studio,并...
ASP.NET MVC作为微软官方的.NET平台下MVC解决方案,自诞生起就吸引了众多.NET平台开发人员的眼球。ASP.NET MVC从一开始的设计思路就与Struts不同,它的映射是利用路由配置而非xml,从而大大降低了开发复杂度,并且比...
ASP.NET MVC4是一个基于模型-视图-控制器(Model-View-Controller)设计模式的开源Web应用程序框架,由...通过阅读提供的"ASP.NET MVC4 教程.pdf",你可以系统地学习这一框架,并逐步成为ASP.NET MVC4的熟练开发者。
学习ASP.NET MVC4 Web编程,你需要掌握C#语言、.NET Framework基础、HTML、CSS和JavaScript等前端技术,以及MVC设计模式的理解。通过阅读“ASP.NET MVC4 Web编程(jb51.net).pdf”这样的资源,你可以深入理解这些概念...
在这个标题为“ASP.NET MVC 5 网站开发之美”的资源中,我们可以期待深入学习如何利用这个框架创建高质量的Web应用。 1. **MVC设计模式**:MVC模式是软件工程中的一种设计模式,它将应用程序分为三个主要部分:模型...
通过分析这个项目,开发者可以学习如何将DWZ的组件与ASP.NET MVC3的路由、动作方法、视图等元素结合起来,实现功能完善的Web应用。 总之,DWZ框架与ASP.NET MVC3的结合,为开发人员提供了一种高效的Web开发解决方案...
这个"ASP.NET MVC4开发指南"提供了一套全面的学习资源,旨在帮助开发者掌握这一强大的Web开发技术。 MVC(Model-View-Controller)模式是ASP.NET MVC4的核心设计原则,它将应用程序分为三个主要部分:模型(Model)...
通过学习和实践这个基于ASP.NET MVC 2 的小程序,你将能够掌握MVC设计模式,以及如何利用该框架构建功能完善的网站。记得要深入研究每个组件,理解它们的作用以及如何协同工作,这样你才能充分利用ASP.NET MVC 2 的...
ASP.NET MVC 5入门指南 (中文PDF+源碼) 1. ASP.NET MVC 5 - 开始MVC 5之旅 2. ASP.NET MVC 5 - 控制器 3. ASP.NET MVC 5 - 视图 4. ASP.NET MVC 5 - 将数据从控制器传递给视图 5. ASP.NET MVC 5 - 添加一个模型 6. ...
The power of ASP.NET MVC 5 stems from the underlying ASP.NET platform. To make your ASP.NET MVC applications the best they can be, you need to fully understand the platform features and know how they ...
通过研究ASP.NET MVC的官方源代码,开发者不仅可以深入了解MVC模式的实现细节,还能学习到最佳实践,提升Web应用的开发效率和质量。源代码的阅读和学习对于深入理解Web开发的底层机制至关重要,尤其是对于那些希望...
MVC专家“梦之队”对ASP.NET MVC 4的全新诠释 由Microsoft专家和极受敬重的软件开发社区负责人撰写的《ASP.NET MVC 4高级编程(第4版)》将带您学习最前沿的Web框架:ASP.NET MVC 4。本书开篇简要介绍ASP.NET MVC框架...