gpt4 book ai didi

wcf - 如何通过操作添加控制restful服务操作的缓存?

转载 作者:行者123 更新时间:2023-12-02 17:37:52 25 4
gpt4 key购买 nike

我使用 WCF 编写了一个休息服务。该服务包含多个操作。有些基于 GET ([WebGet]),有些基于 POST ([WebInvoke])。

该服务按预期工作。然而,基于 GET 的操作被放在客户端缓存中,这并不是所有操作都需要的。

经过一番搜索,我找到了 How to prevent the browser from caching WCF JSON responses .这是可行的,但我发现它的可重用性不是很好。

我的平台不允许我更新 web.config。实际上,我的服务是 SharePoint 项目的一部分。并且更新 web.config 文件很难正确实现。这禁止我使用 [WebCache] 属性。

所以我实现了一个自定义的 MessageInspector 来修复正确的 header :

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 接口(interface)中找到一些有用的东西,但没有找到合适的实现。

完整代码(.net 4.5):

[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
public class CacheAttribute : Attribute, IServiceBehavior
{

private readonly bool m_CacheEnabled;

public bool CacheEnabled { get { return m_CacheEnabled; } }

public TimeSpan? CacheDuration { get; set; }

public CacheAttribute(bool cacheEnabled)
{
this.m_CacheEnabled = cacheEnabled;
}
public CacheAttribute(TimeSpan cacheDuration) : this(true)
{
this.CacheDuration = cacheDuration;
}

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));
}
}
}

public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}



public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}

}

public class CacheInspector : IDispatchMessageInspector
{
private readonly bool m_CacheEnabled;
private readonly TimeSpan? CacheDuration;

public CacheInspector(bool m_CacheEnabled, TimeSpan? CacheDuration)
{
this.m_CacheEnabled = m_CacheEnabled;
this.CacheDuration = CacheDuration;
}
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
return null;
}

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();
}

}
}

最佳答案

我想这就是您要找的。

[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();
}

关于wcf - 如何通过操作添加控制restful服务操作的缓存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24424907/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com