Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wcf 如何逐个操作添加restful服务操作的缓存控制?_Wcf_Rest_Caching - Fatal编程技术网

Wcf 如何逐个操作添加restful服务操作的缓存控制?

Wcf 如何逐个操作添加restful服务操作的缓存控制?,wcf,rest,caching,Wcf,Rest,Caching,我已经使用WCF编写了一个rest服务。该服务包含多个操作。有些是基于GET的([WebGet]),有些是基于POST的([WebInvoke]) 服务正在按预期工作。但是,基于GET的操作放在客户机缓存中,这不是所有操作都需要的 经过一番搜索,我找到了。这是工作,但我发现它不是很可重用 我的平台不允许我更新web.config。实际上,我的服务是SharePoint项目的一部分。更新web.config文件很难正确实现。这禁止我使用[WebCache]属性 因此,我实现了一个定制的Messag

我已经使用WCF编写了一个rest服务。该服务包含多个操作。有些是基于GET的(
[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();
}