WCF .NET 4 OutputCaching с Stream, похоже, не работает - PullRequest
0 голосов
/ 21 октября 2010

У меня проблемы с OutputCaching через службу WCF REST на .NET4-IIS7.Мой сервис имеет собственную схему авторизации (реализующую 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 () превращается в поток, и возвращается:

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

Если вывод кэшируется, этот метод вообще не должен выполняться ... Я ожидаю, что Stream будет кэшироваться и обслуживаться напрямую, без запросов к базе данных и чтения с диска.Каждый zip-файл имеет размер около 1 МБ.Что я пропускаю или делаю неправильно?

1 Ответ

0 голосов
/ 03 ноября 2010

После игры с настройками некоторое время получился ответ: OutputCache не будет работать, если TransferMode является потоковым, даже если вы реализуете свой собственный OutputCacheProvider.Причиной этого является то, что в сценарии с потоковым ответом вы говорите WCF , а не , чтобы буферизовать ваш ответ в памяти и пытаться прочитать его отовсюду и отправить на транспортный уровень.OutputCache зависит от того, находится ли объект полностью в памяти до его возвращения, поэтому WCF может сохранить ссылку на него и поместить его в кэш.В вашем сценарии вы должны убедиться, что включение потоковой передачи без кэша вывода выполняется быстрее, чем чтение и сохранение объекта в памяти, поэтому вы можете выводить его напрямую.

...