WCF GZip Сжатие Запрос / Обработка Ответа
Как получить клиент WCF для обработки ответов сервера, которые были разархивированы или разорваны IIS?
В IIS я следовал приведенным здесь инструкциям о том, как сделать IIS 6 gzip для всех ответов (где запрос содержал "Accept-Encoding: gzip, deflate"), отправляемых службами.svc wcf.
На клиенте я следовал инструкциям здесь и здесь о том, как вставить этот заголовок в веб-запрос: "Accept-Encoding: gzip, deflate".
Fiddler2 показывает, что ответ является двоичным, а не простым старым Xml.
Клиент аварийно завершает работу с исключением, которое в основном говорит, что нет XML-заголовка, что, конечно, верно.
В моем IClientMessageInspector происходит сбой приложения до вызова AfterReceiveReply.
Некоторые дальнейшие заметки:
(1) Я не могу изменить службу или клиент WCF, так как они предоставлены третьей стороной. Однако я могу прикрепить поведение и / или инспекторов сообщений через конфигурацию, если это правильное направление.
(2) Я не хочу сжимать / распаковывать только мыльное тело, но все сообщение.
Есть идеи / решения?
* Решено *
Не было возможности написать расширение WCF для достижения этих целей. Вместо этого я следовал за этой статьей CodeProject, которая защищает вспомогательный класс:
public class CompressibleHttpRequestCreator : IWebRequestCreate
{
public CompressibleHttpRequestCreator()
{
}
WebRequest IWebRequestCreate.Create(Uri uri)
{
HttpWebRequest httpWebRequest =
Activator.CreateInstance(typeof(HttpWebRequest),
BindingFlags.CreateInstance | BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance,
null, new object[] { uri, null }, null) as HttpWebRequest;
if (httpWebRequest == null)
{
return null;
}
httpWebRequest.AutomaticDecompression =DecompressionMethods.GZip |
DecompressionMethods.Deflate;
return httpWebRequest;
}
}
а также дополнение к файлу конфигурации приложения:
<configuration>
<system.net>
<webRequestModules>
<remove prefix="http:"/>
<add prefix="http:"
type="Pajocomo.Net.CompressibleHttpRequestCreator, Pajocomo" />
</webRequestModules>
</system.net>
</configuration>
Кажется, что происходит то, что в конечном итоге WCF запрашивает какую-то фабрику или другой источник в system.net, чтобы предоставить экземпляр HttpWebRequest, и мы предоставляем помощника, которому будет предложено создать требуемый экземпляр.
В файле конфигурации клиента WCF все, что требуется, это простой basicHttpBinding без каких-либо пользовательских расширений.
Когда приложение запускается, клиентский Http-запрос содержит заголовок "Accept-Encoding: gzip, deflate", сервер возвращает сжатый веб-ответ, и клиент прозрачно распаковывает http-ответ перед его передачей в WCF.
Когда я попытался применить эту технику к веб-сервисам, я обнаружил, что она НЕ работает. Хотя вспомогательный класс выполнялся так же, как и при использовании клиентом WCF, запрос http не содержал заголовок "Accept-Encoding: ...".
Чтобы это работало для веб-служб, мне пришлось отредактировать класс веб-прокси и добавить этот метод:
protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
System.Net.HttpWebRequest rq = (System.Net.HttpWebRequest)base.GetWebRequest(uri);
rq.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
return rq;
}
Обратите внимание, что не имело значения, присутствовали CompressibleHttpRequestCreator и блок из файла конфигурации приложения или нет. Для веб-сервисов работало только переопределение GetWebRequest в Прокси-сервер веб-службы.
2 ответа
Спасибо за ваш совет WCF! Мы собираемся включить сжатие IIS для служб в моем магазине, и я надеюсь, что ваше решение будет работать. Под "Чтобы это работало для веб-сервисов" - вы имели в виду клиентов SoapHttpProtocol старой школы? Потому что класс SoapHttpProtocol имеет встроенное свойство EnableDecompression, которое будет автоматически обрабатывать заголовок Compression и обработку ответов.
Вот ответ, который я дал на другой вопрос по этому вопросу. Этот вопрос был задан с точки зрения ADO.NET Data Services, но мой ответ был чисто о WCF.