ASP.NET的输出缓存(Output Caching)机制允许我们针对整个Web页面或者页面的某个部分(主要针对用户控件)最终呈现的HTML进行缓存。对于后续针对相同资源的请求,只需要直接将缓存的HTML予以回复而无须按照页面处理生命周期对每次请求进行重复处理。WCF通过操作行为AspNetCacheProfileAttribute利用ASP.NET的输出缓存提供一种针对于某个操作的声明式缓存机制。[源代码从这里下载]

一、AspNetCacheProfileAttribute

WCF对ASP.NET缓存的支持是通过AspNetCacheProfileAttribute特性来实现的。通过如下的代码我们不难看出AspNetCacheProfileAttribute是实现了IOperationBehavior接口的操作行为,我们可以直接将其应用到契约接口/类中的某个具有缓存需要的操作方法上。

   1: [AttributeUsage(AttributeTargets.Method)]
   2: public sealed class AspNetCacheProfileAttribute : Attribute, IOperationBehavior
   3: {
   4:     //其他成员
   5:     public AspNetCacheProfileAttribute(string cacheProfileName);
   6:     public string CacheProfileName { get; }
   7: }

AspNetCacheProfileAttribute构造函数参数cacheProfileName表示的CacheProfile的配置名称,目标操作按照定义在相应CacheProfile的缓存策略实施缓存。CacheProfile配置在<system.web>/<caching>/<outputCacheSettings>/<outputCacheProfiles>节点下。

   1: <configuration>
   2:   <connectionStrings>
   3:     <add name="localDb" 
   4:          connectionString="Server=.; Database=TestDb; Uid=sa; Pwd=password"
   5:          providerName="System.Data.SqlClient"/>
   6:   </connectionStrings>
   7:   <system.web>
   8:     <caching>
   9:       <outputCacheSettings>
  10:         <outputCacheProfiles>
  11:           <add name="default" 
  12:                duration="60" 
  13:                varyByParam="none" 
  14:                sqlDependency="TestDb: TestTable"/>
  15:         </outputCacheProfiles>
  16:       </outputCacheSettings>
  17:       <sqlCacheDependency>
  18:         <databases>
  19:           <add name="TestDb" connectionStringName="localDb"/>
  20:         </databases>
  21:       </sqlCacheDependency>
  22:     </caching>
  23:   </system.web>
  24: </configuration>

在如上所示的配置片断中,我们定义了一个名称为default的CacheProfile。代表缓存时间的duration属性被设置为60,意味着缓存项在被存储之后1分钟之后实失效;属性varyByParam被设置为none表示缓存项与请求的查询字符串无关。此外,该CacheProfile还设置针对某个本地数据库中的TestTable表的SQL依赖(SQL Dependency)。关于CacheProfile的配置属于ASP.NET的范畴,在这里我们不会作过多的讨论。

既然是采用ASP.NET输出缓存,WCF服务自然需要采用IIS寄宿并采用ASP.NET 兼容模式。值得一提的是,基于AspNetCacheProfileAttribute的输出缓存仅仅针对HTTP-GET。

二、实例演示:创建采用输出缓存的服务

接下来我们通过一个简单的实例来演示如何通过操作行为对某个操作的返回值实施缓存,为此我们创建一个用于返回当前时间的服务。如下所示的是作为服务契约的ITime接口的定义,AspNetCacheProfileAttribute特性被应用到了用于返回当前时间的操作方法GetCurrentTime上。

   1: using System;
   2: using System.ServiceModel;
   3: using System.ServiceModel.Web;
   4: namespace Artech.WcfServices.Service.Interface
   5: {
   6:     [ServiceContract(Namespace = "http://www.artech.com/")]
   7:     public interface ITime
   8:     {
   9:         [WebGet(UriTemplate = "/current")]
  10:         [AspNetCacheProfile("default")]
  11:         DateTime GetCurrentTime();
  12:     }
  13: }

实现了契约接口ITime的服务类型TimeService定义如下。我们将AspNetCompatibilityRequirementsAttribute特性应用在服务类型上并将RequirementsMode属性设置为Allowed以提供对ASP.NET兼容模式的支持。

   1: using System;
   2: using System.ServiceModel.Activation;
   3: using Artech.WcfServices.Service.Interface;
   4: namespace Artech.WcfServices.Service
   5: {
   6:     [AspNetCompatibilityRequirements(
   7:      RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
   8:     public class TimeService : ITime
   9:     {
  10:         public DateTime GetCurrentTime()
  11:         {
  12:             return DateTime.Now;
  13:         }
  14:     }
  15: }

在一个Web项目中我们为通过IIS寄宿的服务TimeService添加一个对应的.svc文件(TimeService.svc),如下所示的是<%@ServiceHost%>指令的定义。表示ServiceHostFactory类型的指令属性Factory被设置为System.ServiceModel.Activation.WebServiceHostFactory.

   1: <%@ ServiceHost Service="Artech.WcfServices.Service.TimeService" Factory="System.ServiceModel.Activation.WebServiceHostFactory"%>

我们在作为服务宿主的Web项目下添加一个配置文件(Web.config)并定义如下的配置。除了服务寄宿的基本配置外,我们将<system.serviceModel>/<serviceHostingEnvironment >配置节的aspNetCompatibilityEnabled属性设置为True以开启ASP.NET兼容模式。应用在操作方法GetCurrentTime上的AspNetCacheProfileAttribute特性中指定的名称为default的CacheProfile定义在该配置中,duration和varyByParam分别被设置为60和none。

   1: <configuration>
   2:     <system.serviceModel>
   3:         <services>
   4:             <service name="Artech.WcfServices.Service.TimeService">
   5:                 <endpoint binding="webHttpBinding"
   6:                           contract="Artech.WcfServices.Service.Interface.ITime"/>
   7:             </service>
   8:         </services>
   9:       <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  10:     </system.serviceModel>  
  11:   <system.web>
  12:     <caching>
  13:       <outputCacheSettings>
  14:         <outputCacheProfiles>
  15:           <add name="default" duration="60" varyByParam="none"/>
  16:         </outputCacheProfiles>
  17:       </outputCacheSettings>      
  18:     </caching>
  19:   </system.web>
  20: </configuration>

作为客户端的控制台程序在进行了相应配置之后通过如下的代码进行服务的调用。在这段代码中,我们通过创建的服务代理进行了5次服务调用,并将获取的时间打印出来。每次服务的时间间隔为1秒。

   1: using (ChannelFactory<ITime> channelFactory =  new ChannelFactory<ITime>("timeService"))
   2: {
   3:     ITime proxy = channelFactory.CreateChannel();
   4:     for (int i = 0; i < 5; i++)
   5:     { 
   6:         Console.WriteLine(proxy.GetCurrentTime().ToLongTimeString());
   7:         Thread.Sleep(1000);
   8:     }
   9: }

客户端代码执行之后会在控制台上输出如下的结果。由于服务端通过ASP.NET的输出缓存对第一次执行GetCurrentTime操作的结果进行了缓存,所以客户端返回的时间都是相同的。

   1: 4:48:43 PM
   2: 4:48:43 PM
   3: 4:48:43 PM
   4: 4:48:43 PM
   5: 4:48:43 PM

三、 AspNetCacheProfileAttribute是如何实现输出缓存的?

既然我们采用ASP.NET兼容模式来寄宿服务,意味着我们调用某个服务与访问某个页面没有本质的区别,所以基于Web页面的输出缓存能够应用于基于某个服务操作的调用就不足为奇了。现在有这么一个问题:通过AspNetCacheProfileAttribute特性指定CacheProfile是如何生效的?

如果对ASP.NET具有一定的了解,应该知道可以通过当前HttpResponse(HttpContext.Current.Response)的Cache属性表示的HttpCachePolicy对象来控制当前输出缓存的基本策略。实际上AspNetCacheProfileAttribute就是通过这种方式将定义在指定CacheProfile的缓存策略应用到针对当前操作的调用上的。

具体来说,AspNetCacheProfileAttribute针对输出缓存策略的控制是通过一个实现了接口IParameterInspector的自定义参数检验器实现的,这是一个名称为CachingParameterInspector的内部类型。操作行为AspNetCacheProfileAttribute通过实现的ApplyDispatchBehavior方法将针对某个CacheProfile创建的CachingParameterInspector对象添加到当前分发操作(DispatchOperation)的参数检验器列表中。

   1: internal class CachingParameterInspector : IParameterInspector
   2: {
   3:     public CachingParameterInspector(string cacheProfileName);
   4:     public object BeforeCall(string operationName, object[] inputshens);
   5:     public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
   6:     {
   7:         //将指定CacheProfile的输出缓存策略应用到当前HttpResponse
   8:     }
   9: }

如上面的代码片断所示,当AfterCall方法被执行的之后,在构造函数中指定的CacheProfile定义的输出缓存策略应用到当前HttpResponse。而AfterCall会在操作执行之后,回复消息序列化之前被执行。

[WCF REST] 通过ASP.NET Output Caching实现声明式缓存相关推荐

  1. ASP.NET MVC Caching with OutputCache

    ASP.NET MVC Caching with OutputCache [原文:http://tech.pro/tutorial/1434/aspnet-mvc-caching-with-outpu ...

  2. ASP.NET 2.0 中改进的缓存功能

    摘要:本文中,Stephen Walther 将重点介绍 ASP.NET 2.0 中新增的缓存功能,以及如何使用这些新功能改进 ASP.NET 应用程序的性能和可扩展性.(本文包含一些指向英文站点的链 ...

  3. ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存

    ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存 原文:ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存 ASP.Net MVC4+Memc ...

  4. ASP.NET Core 中间件之压缩、缓存

    前言 今天给大家介绍一下在 ASP.NET Core 日常开发中用的比较多的两个中间件,它们都是出自于微软的 ASP.NET 团队,他们分别是 Microsoft.AspNetCore.Respons ...

  5. 如何禁用 ASP.NET 网站的所有的 浏览器缓存 ?

    咨询区 Palani: 我在寻找一个方法禁用某个 ASP.NET MVC 网站的所有浏览器缓存,我发现了如下方法. Response.Cache.SetCacheability(System.Web. ...

  6. 声明式RESTful客户端在asp.net core中的应用

    1 声明式RESTful客户端 声明式服务调用的客户端,常见有安卓的Retrofit.SpringCloud的Feign等,.net有Refit和WebApiClient,这些客户端都是以java或. ...

  7. .Net内部缓存System.Web.Caching.Cache 和Redis缓存缓存工厂切换

    有个问题,以前系统采用的是System.Web.Caching.Cache 但是redis缓存的流行 分布式的流行,缓存就被切换了. 但是在redis缓存的环境需要配置,有时候要切换回来. 这时候就弄 ...

  8. WCF安全之ASP.NET兼容模式

    本文是利用ASP.NET兼容模式实现WCF安全的一个完整示例,其中用到了ASP.NET的Forms身份验证及Membership,并启用了角色管理. 由于整套安全方案完全利用ASP.NET相关功能实现 ...

  9. ASP.NET Core Caching简介

    在.NET Core中提供了Caching的组件.目前Caching组件提供了三种存储方式: Memory Redis SQLSever 1.Memeor Caching 新建一个ASP.NET Co ...

最新文章

  1. Python:pip 和pip3的区别
  2. 5月书讯:藏一个愿望等风来
  3. 计算机科学中抽象的好处与问题—伪共享等实例分析
  4. linux 内核中一个全局变量引发的性能问题
  5. 拦截器 java_在Java后端如何添加拦截器
  6. VTK:Utilities之ColorTransferFunction
  7. Basic操作系统概念梳理
  8. IPC-----消息队列
  9. 【人脸识别终结者】多伦多大学反人脸识别,身份欺骗成功率达99.5%
  10. 【PyTorch】torch.clamp()==>将input的值限制在[min, max]之间,并返回结果到一个新张量
  11. 全国计算机二级ms2017,2017全国计算机二级MS-Office选择题题库大全
  12. 1900页Python系列PPT分享三:选择与循环结构语法及案例(96页)
  13. 如果在文档已完成加载后执行 document.write,整个 HTML 页面将被覆盖
  14. HCIE-Security Day7:6个实验理解目的NAT
  15. vue-router: 路由传参
  16. bjui获取当前页签或者是dialog容器
  17. BUUCTF-MISC-黑客帝国~喵喵喵
  18. 内存管理单元(MMU)与内存控制器
  19. 机器翻译实战(英译汉)Transformer代码学习详解
  20. gitlab runner实现自动化部署

热门文章

  1. ELASTIC的备份与恢复
  2. HTTP 状态代码及其定义(转载)
  3. 大佬云集的「乌镇峰会」,悄悄释放出1个重要信号
  4. 如何增加儿童产品中的趣味性?
  5. 产品经理该如何全局思考和分析行业产业链?
  6. 【干货】引爆公式,让你的APP成为下一个“爆款”!
  7. 30道最常问的Java基础面试题
  8. SpringMVC 全局异常处理,返回json
  9. TortoiseGit清除账号密码
  10. Spring【AOP模块】就是这么简单