使用Stream的WCF .NET 4 OutputCaching似乎不起作用

时间:2010-10-21 17:37:28

标签: wcf .net-4.0 streaming authorization outputcache

我在.NET4-IIS7上的WCF REST服务上遇到OutputCaching问题。我的服务有一个自定义授权方案(通过实现ServiceAuthorizationManager),应该在每个请求上进行,并且必须在授权请求后进行任何缓存。到目前为止,这似乎有效,只有我看不到的缓存部分。

我有以下OperationContract:

[OperationContract]
[AspNetCacheProfile("PageZIP")]
[WebGet(UriTemplate = "pages/{page_id}")]
System.IO.Stream getPage(string page_id);

以下web.config:

<system.web>
<compilation targetFramework="4.0" />
<customErrors mode="Off" />
<authentication mode="None" />
<caching>
    <outputCache enableOutputCache="true"/>
    <outputCacheSettings>
        <outputCacheProfiles>
            <add name="PageZIP" duration="7200" location="ServerAndClient"
                     varyByParam="page_id" />
        </outputCacheProfiles>
    </outputCacheSettings>
</caching>
</system.web>
    <system.serviceModel>
    <behaviors>
        <serviceBehaviors>
            <behavior>
                <serviceAuthorization serviceAuthorizationManagerType="api.Authorization, api" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <standardEndpoints>
        <webHttpEndpoint>
            <standardEndpoint transferMode="StreamedResponse" automaticFormatSelectionEnabled="false" defaultOutgoingResponseFormat="Json" />
        </webHttpEndpoint>
    </standardEndpoints></system.serviceModel>

当我调用服务时,我可以看到新的响应标头填充了客户端缓存信息,但是在服务器上缓存似乎不起作用。我的自定义日志显示我的api.Authorization类被正确地调用,但是我的getPage()方法也正常执行,直到我的文件被.OpenRead()放入Stream并返回:

public System.IO.Stream getPage(string page_id) {
    File zip = FileMapper.getZip(pid);
    ctx.OutgoingResponse.Headers.Clear();
    ctx.OutgoingResponse.Headers.Add("Content-Disposition", "attachment; filename=" + page_id + ".zip");
    ctx.OutgoingResponse.Headers.Add("Content-Length", zip.size.ToString());
    ctx.OutgoingResponse.ContentType = "application/zip";

    Log.write("OpenRead", LogType.Info);
    return System.IO.File.OpenRead(zip.path);
}

如果正在缓存输出,则根本不应该执行此方法...我希望将流缓存并直接提供,而无需查询数据库和磁盘读取。每个zipfile的大小约为1 MB。 我错过了什么或做错了什么?

1 个答案:

答案 0 :(得分:0)

在播放设置一段时间后,答案就出现了:如果transferMode是流式传输,则OutputCache将无法工作,即使您实现自己的OutputCacheProvider也是如此。这背后的原因是,在流式响应方案中,您告诉WCF 而不是在内存中缓冲您的响应,并尝试从任何地方读取它并将其发送到传输级别。 OutputCache在返回之前依赖于完全在内存中的对象,因此WCF可以保留对它的引用并将其放在缓存中。

您可以在自己的场景中看到,如果启用没有输出缓存的流式传输比读取并将对象保留在内存中更快,那么您可以直接输出它。