网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 设计资源 > .Net编程 > 正文

ActionFilters以及自定义OutputCacheActionFilterAttribute事件发生次序

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

理解 Action Filters[本文示例源码下载]

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 属性使用的设置不建议通过设置“*”的值来使用所有参数进行区分。这可能会导致缓存溢出。

  1. public class DataController : Controller  
  2.  {  
  3.  //  
  4.  // GET: /Data/  
  5.  [OutputCache(Duration = 20,VaryByParam ="")]  
  6.  public string Index()  
  7.  {  
  8.  return DateTime.Now.ToString();  
  9.  }  
  10.  } 

如果你重复调用Index() action(不断刷新当前页面), 那么你将看到当前的内容在Duration = 20秒内是不变的.

 

 一个单一的action filter –  OutputCache action filter – 被应用于Index() 方法. 同样,你可以应用多个action filters 在同一个action上.

不同类型的Filters

ASP.NET MVC框架支持多种不同类型的过滤器:

  1. Authorization filters – 实现IAuthorizationFilter 特性.
  2. Action filters – 实现IActionFilter 特性.
  3. Result filters – 实现IResultFilter 特性.
  4. Exception filters –实现IExceptionFilter 特性.

Filters 按照上面列出的顺序执行。例如, authorization filters 总是在action filters之前执行,exception filters在所有其他类型的filter之后执行.

ActionFilterAttribute 基类

为了使你能够更加容易的实现自定义的action filter, ASP.NET MVC框架包含一个ActionFilterAttribute 基类. 这个类实现了IActionFilterIResultFilter 接口,并且继承了Filter 类。

ActionFilterAttribute 基类拥有以下可以重载的方法:

  • OnActionExecuting在action method调用前发生。
  • OnActionExecuted在action method调用后发生, 但是在result执行前发生 (在 view 呈现前)
  • OnResultExecuting在result执行前发生(在view 呈现前)
  • OnResultExecuted 在result执行后发生(在view 呈现后)

 

创建一个ASP.NET MVC OutputCache ActionFilterAttribute

 在每一个web应用程序中, 有的情况下,你想在一段时间内缓存一个具体的页面HTML输出,因为相关的数据和处理并不是总是变化。这种缓存的响应是储存在服务器的内存中。因为没有必要的额外处理,它提供了非常快速的响应。使用经典的ASP.NET,你可以在.aspx页面上使用OutputCache指令,它告诉ASP.NET运行时在某一特定的时间段内来缓存响应数据。缓存可随参数而改变,这将导致产生依赖于参数的不同缓存响应。作为一个额外的功能,还可以发送一些HTTP头到客户端。在一段时间以内,客户端从浏览器缓存中加载页面。大的优势是你的web服务器将接收更少的客户端要求,因为他们仅仅是使用他们自己的缓存。

 

使用ASP.NET MVC 框架, 简单的指定OutputCache 指令并不能达到理想的效果. 幸好, ActionFilterAttribute让你能够在 controller action执行的前后运行代码.

让我们使用类似的方法来创建OutputCache ActionFilterAttribute

  1. [OutputCache(Duration = 60, VaryByParam = "*", CachePolicy = CachePolicy.Server)]  
  2. public ActionResult Index()  
  3. {  
  4.  //   

我们将使用命名为CachePolicy的枚举类型来指定OutputCache 特性应怎样以及在哪里进行缓存:

  1. public enum CachePolicy  
  2. {  
  3.  NoCache = 0,  
  4.  Client = 1,  
  5.  Server = 2,  
  6.  ClientAndServer = 3  
  7. }   
  8.  

1.实现client-side缓存

事实上,这是很容易的。在view呈现前,我们将增加一些HTTP头到响应流。网页浏览器将获得这些头部,并且通过使用正确的缓存设置来回应请求。如果我们设置duration为60,浏览器将首页缓存一分钟。

  1. using System.Web.Mvc;  
  2.  
  3. namespace MVCActionFilters.Web.Models  
  4. {  
  5.  public class OutputCache:System.Web.Mvc.ActionFilterAttribute   
  6. {  
  7.  public int Duration { getset; }  
  8.  public CachePolicy CachePolicy { getset; }  
  9.  
  10.  public override void OnActionExecuted(ActionExecutedContext filterContext)  
  11.  {  
  12.  if (CachePolicy == CachePolicy.Client || CachePolicy == CachePolicy.ClientAndServer)  
  13.  {  
  14.  if (Duration <= 0) return;  
  15.  
  16.  //用于设置特定于缓存的 HTTP 标头以及用于控制 ASP.NET 页输出缓存  
  17.  HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;  
  18.  TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);  
  19.  
  20.  cache.SetCacheability(HttpCacheability.Public);  
  21.  cache.SetExpires(DateTime.Now.Add(cacheDuration));  
  22.  cache.SetMaxAge(cacheDuration);  
  23.  cache.AppendCacheExtension("must-revalidate, proxy-revalidate");  
  24.  }  
  25.  }  
  26.  }  

2. 实现server-side缓存

Server-side 缓存有一点难度. 首要的,在输出缓存系统中,我们将不得不准备HTTP 响应为可读的。为了这样做,我们首先保存当前的HTTP context到类的一个变量中. 然后, 我们创建一个新的httpcontext ,通过它将数据写入StringWriter,同时允许读操作可以发生:

  1. existingContext = System.Web.HttpContext.Current;//保存当前的HTTP context到类的一个变量中  
  2. writer = new StringWriter();  
  3. HttpResponse response = new HttpResponse(writer);  
  4. HttpContext context = new HttpContext(existingContext.Request, response)  
  5. {  
  6.  User = existingContext.User  
  7. };  
  8. System.Web.HttpContext.Current = context; 
  1. public override void OnResultExecuting(ResultExecutingContext filterContext)  
  2.  {  
  3.  if (CachePolicy == CachePolicy.Server || CachePolicy == CachePolicy.ClientAndServer)  
  4.  {  
  5.  //获取缓存实例  
  6.  cache = filterContext.HttpContext.Cache;  
  7.  
  8.  // 获取缓存数据  
  9.  object cachedData = cache.Get(GenerateKey(filterContext));  
  10.  if (cachedData != null)  
  11.  {  
  12.  // 返回缓存数据  
  13.  cacheHit = true;  
  14.  filterContext.HttpContext.Response.Write(cachedData);  
  15.  filterContext.Cancel = true;  
  16.  }  
  17.  else 
  18.  { //重新设置缓存数据  
  19.  existingContext = System.Web.HttpContext.Current;  
  20.  writer = new StringWriter();  
  21.  HttpResponse response = new HttpResponse(writer);  
  22.  HttpContext context = new HttpContext(existingContext.Request, response)  
  23.  {  
  24.  User = existingContext.User  
  25.  };  
  26.  foreach (var key in existingContext.Items.Keys)  
  27.  {  
  28.  context.Items[key] = existingContext.Items[key];  
  29.  }  
  30.  System.Web.HttpContext.Current = context;  
  31.  }  
  32.  }  
  33.  } 

利用该代码,我们能从高速缓存中检索现有项,并设置了HTTP响应能够被读取。在视图呈现之后,将数据存储在高速缓存中:

  1. public override void OnResultExecuted(ResultExecutedContext filterContext)  
  2.  {  
  3.  // 服务器端缓存?  
  4.  if (CachePolicy == CachePolicy.Server || CachePolicy == CachePolicy.ClientAndServer)  
  5.  {  
  6.  if (!cacheHit)  
  7.  {  
  8.  // 存储原有的context  
  9.  System.Web.HttpContext.Current = existingContext;  
  10.  
  11.  // 返回呈现的数据  
  12.  existingContext.Response.Write(writer.ToString());  
  13.  
  14.  //增加数据到缓存  
  15.  cache.Add(  
  16.  GenerateKey(filterContext),  
  17.  writer.ToString(),  
  18.  null,  
  19.  DateTime.Now.AddSeconds(Duration),  
  20.  Cache.NoSlidingExpiration,  
  21.  CacheItemPriority.Normal,  
  22.  null);  
  23.  }  
  24.  }  
  25.  } 

你现在注意到添加了一个VaryByParam到 OutputCache ActionFilterAttribute。当缓存server-side时,我可以通过传入的参数来改变缓存存储。这个GenerateKey方法会产生一个依赖于controller,action和VaryByParam的键。

  1. private string GenerateKey(ControllerContext filterContext)  
  2.  {  
  3.  StringBuilder cacheKey = new StringBuilder();  
  4.  
  5.  // Controller + action  
  6.  cacheKey.Append(filterContext.Controller.GetType().FullName);  
  7.  if (filterContext.RouteData.Values.ContainsKey("action"))  
  8.  {  
  9.  cacheKey.Append("_");  
  10.  cacheKey.Append(filterContext.RouteData.Values["action"].ToString());  
  11.  }  
  12.  
  13.  // Variation by parameters  
  14.  List<string> varyByParam = VaryByParam.Split(';').ToList();  
  15.  
  16.  if (!string.IsNullOrEmpty(VaryByParam))  
  17.  {  
  18.  foreach (KeyValuePair<stringobject> pair in filterContext.RouteData.Values)  
  19.  {  
  20.  if (VaryByParam == "*" || varyByParam.Contains(pair.Key))  
  21.  {  
  22.  cacheKey.Append("_");  
  23.  cacheKey.Append(pair.Key);  
  24.  cacheKey.Append("=");  
  25.  cacheKey.Append(pair.Value.ToString());  
  26.  }  
  27.  }  
  28.  }  
  29.  return cacheKey.ToString();  
  30.  } 

现在你可以增加 OutputCache attribute 到应用程序的任何一个controller 与controller action中 。

  1. [MVCActionFilters.Web.Common.OutputCache(Duration = 20, VaryByParam = "*",CachePolicy=Common.CachePolicy.Client)]  
  2.  public string Cache()  
  3.  {  
  4.  return DateTime.Now.ToString();  
  5.  } 

总结

需注意事件的发生时间段

  • OnActionExecuting在action method调用前发生。
  • OnActionExecuted在action method调用后发生, 但是在result执行前发生 (在 view 呈现前)
  • OnResultExecuting在result执行前发生(在view 呈现前)
  • OnResultExecuted 在result执行后发生(在view 呈现后) 
  • 设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
    版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
    Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师