Wcf 如何逐个操作添加restful服务操作的缓存控制?
我已经使用WCF编写了一个rest服务。该服务包含多个操作。有些是基于GET的(Wcf 如何逐个操作添加restful服务操作的缓存控制?,wcf,rest,caching,Wcf,Rest,Caching,我已经使用WCF编写了一个rest服务。该服务包含多个操作。有些是基于GET的([WebGet]),有些是基于POST的([WebInvoke]) 服务正在按预期工作。但是,基于GET的操作放在客户机缓存中,这不是所有操作都需要的 经过一番搜索,我找到了。这是工作,但我发现它不是很可重用 我的平台不允许我更新web.config。实际上,我的服务是SharePoint项目的一部分。更新web.config文件很难正确实现。这禁止我使用[WebCache]属性 因此,我实现了一个定制的Messag
[WebGet]
),有些是基于POST的([WebInvoke]
)
服务正在按预期工作。但是,基于GET的操作放在客户机缓存中,这不是所有操作都需要的
经过一番搜索,我找到了。这是工作,但我发现它不是很可重用
我的平台不允许我更新web.config。实际上,我的服务是SharePoint项目的一部分。更新web.config文件很难正确实现。这禁止我使用[WebCache]
属性
因此,我实现了一个定制的MessageInspector
,它修复了正确的标题:
public class CacheAttribute : Attribute, IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase host)
{
foreach (ChannelDispatcher cDispatcher in host.ChannelDispatchers)
{
foreach (EndpointDispatcher eDispatcher in cDispatcher.Endpoints)
{
eDispatcher.DispatchRuntime.MessageInspectors.Add(new CacheInspector(m_CacheEnabled, CacheDuration));
}
}
}
/*...
Other code omitted for brievty
*/
}
public class CacheInspector : IDispatchMessageInspector
{
/*...
Code omitted for brievety
*/
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
var cache = HttpContext.Current.Response.Cache;
if (m_CacheEnabled)
{
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.UtcNow + CacheDuration.Value);
}
else
{
cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));
cache.SetNoStore();
}
}
}
此代码按预期工作,但它适用于服务中的所有操作
如何对应用相同逻辑但在操作范围内的基于属性的类进行编码
我试图在IOperationBehavior
接口中找到一些有用的东西,但没有找到合适的实现
完整代码(.net 4.5):
[AttributeUsage(AttributeTargets.Class,Inherited=false,AllowMultiple=true)]
公共类CacheAttribute:属性,IServiceBehavior
{
私有只读bool m_CacheEnabled;
public bool CacheEnabled{get{return m_CacheEnabled;}}
公共时间跨度?缓存持续时间{get;set;}
公共缓存属性(bool cacheEnabled)
{
this.m_CacheEnabled=CacheEnabled;
}
public CacheAttribute(TimeSpan cacheDuration):此值(true)
{
this.CacheDuration=CacheDuration;
}
公共无效ApplyDispatchBehavior(ServiceDescription ServiceDescription,ServiceHostBase主机)
{
foreach(主机中的ChannelDispatcher CDDispatcher.ChannelDispatchers)
{
foreach(CDDispatcher.Endpoints中的EndpointDispatcher eDispatcher)
{
eDispatcher.DispatchRuntime.MessageInspectors.Add(新的CacheInspector(m_CacheEnabled,CacheDuration));
}
}
}
public void AddBindingParameters(ServiceDescription ServiceDescription、ServiceHostBase ServiceHostBase、集合终结点、BindingParameterCollection bindingParameters)
{
}
公共无效验证(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
}
}
公共类CacheInspector:IDispatchMessageInspector
{
私有只读bool m_CacheEnabled;
私有只读时间跨度?缓存持续时间;
公共CacheInspector(布尔m_CacheEnabled,TimeSpan?CacheDuration)
{
this.m_CacheEnabled=m_CacheEnabled;
this.CacheDuration=CacheDuration;
}
公共对象AfterReceiveRequest(参考System.ServiceModel.Channels.Message request、System.ServiceModel.IClientChannel、System.ServiceModel.InstanceContext InstanceContext)
{
返回null;
}
SendReply之前的公共无效(参考System.ServiceModel.Channels.Message reply,object correlationState)
{
var cache=HttpContext.Current.Response.cache;
如果(已启用m_缓存)
{
SetCacheability(HttpCacheability.Public);
SetExpires(DateTime.UtcNow+CacheDuration.Value);
}
其他的
{
SetExpires(DateTime.UtcNow.AddMinutes(-1));
cache.SetNoStore();
}
}
}
我想这就是你想要的
[AttributeUsage(AttributeTargets.Method)]
public class CacheAttribute : Attribute, IOperationBehavior, IParameterInspector
{
public TimeSpan CacheLifetime { get; private set; }
public CacheAttribute(double lifetime)
{
this.CacheLifetime = TimeSpan.FromSeconds(lifetime);
}
#region IOperationBehavior Members
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) {}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) {}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.ParameterInspectors.Add(this);
}
public void Validate(OperationDescription operationDescription) {}
#endregion
#region IParameterInspector Members
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
if (this.CacheLifetime == TimeSpan.Zero) {
WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", "no-cache");
} else {
WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", string.Format("max-age={0}",this.CacheLifetime.TotalSeconds));
}
}
public object BeforeCall(string operationName, object[] inputs)
{
return null;
}
#endregion
}
用法
我想这就是你要找的
[AttributeUsage(AttributeTargets.Method)]
public class CacheAttribute : Attribute, IOperationBehavior, IParameterInspector
{
public TimeSpan CacheLifetime { get; private set; }
public CacheAttribute(double lifetime)
{
this.CacheLifetime = TimeSpan.FromSeconds(lifetime);
}
#region IOperationBehavior Members
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) {}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) {}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.ParameterInspectors.Add(this);
}
public void Validate(OperationDescription operationDescription) {}
#endregion
#region IParameterInspector Members
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
if (this.CacheLifetime == TimeSpan.Zero) {
WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", "no-cache");
} else {
WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", string.Format("max-age={0}",this.CacheLifetime.TotalSeconds));
}
}
public object BeforeCall(string operationName, object[] inputs)
{
return null;
}
#endregion
}
用法
[ServiceContract]
public interface ICacheTestService
{
[OperationContract]
[WebGet(UriTemplate = "CurrentTime")]
[Cache(0)]
string GetCurrentTime();
[OperationContract]
[WebGet(UriTemplate = "CurrentTimeCached")]
[Cache(30)]
string GetCurrentTimeCached();
[OperationContract]
[WebGet(UriTemplate = "CurrentTimeNoCC")]
string GetCurrentTimeNoCC();
}