2009-11-16 5 views
24

Wie bekomme ich einen WCF-Client zur Verarbeitung von Server-Antworten, die von IIS Gziped oder Deflated wurden?WCF GZip Compression Anfrage/Antwort Verarbeitung

Auf IIS, ich habe die Anweisungen here auf, wie IIS 6 Gzip alle Antworten (wo die Anfrage enthalten "Accept-Encoding: gzip, deflate") von .svc WCF-Dienste emittiert.

Auf dem Client habe ich die Anweisungen here und here auf, wie man diesen Header in die Web-Anfrage injizieren: "Accept-Encoding: gzip, deflate".

Fiddler2 zeigt die Antwort ist binär und nicht einfach alte Xml.

Der Client stürzt mit einer Ausnahme, die im Grunde sagt, es gibt keine Xml-Header, was natürlich wahr ist.

In meinem IClientMessageInspector stürzt die App ab, bevor AfterReceiveReply aufgerufen wird.

Einige weitere Hinweise:

(1) Ich kann den WCF-Dienst oder Client nicht ändern, da sie von einer dritten Partei geliefert werden. Ich kann jedoch Verhaltensweisen und/oder Nachrichteninspektoren über die Konfiguration hinzufügen, wenn dies die richtige Richtung ist.

(2) Ich möchte nicht nur den Seifenkörper komprimieren/dekomprimieren, sondern die gesamte Nachricht.

Irgendwelche Ideen/Lösungen?

* GELÖST *

Es war nicht möglich, eine WCF-Erweiterung zu schreiben, um diese Ziele zu erreichen. Stattdessen folgte ich diese Codeproject article, die eine Hilfsklasse vertreten:

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

und auch eine Ergänzung der Anwendungskonfigurationsdatei:

<configuration> 
    <system.net> 
    <webRequestModules> 
     <remove prefix="http:"/> 
     <add prefix="http:" 
      type="Pajocomo.Net.CompressibleHttpRequestCreator, Pajocomo" /> 
    </webRequestModules> 
    </system.net> 
</configuration> 

Was passiert zu sein scheint, ist, dass WCF schließlich eine Fabrik fragt oder tief in system.net, um eine HttpWebRequest-Instanz bereitzustellen, und wir stellen den Helper zur Verfügung, der aufgefordert wird, die erforderliche Instanz zu erstellen.

In der WCF-Clientkonfigurationsdatei ist lediglich ein einfaches basicHttpBinding erforderlich, ohne dass benutzerdefinierte Erweiterungen erforderlich sind.

Wenn die Anwendung ausgeführt wird, enthält die Client-HTTP-Anforderung den Header "Accept-Encoding: gzip, deflate", der Server gibt eine Webantwort mit gzip zurück und der Client dekomprimiert die HTTP-Antwort transparent, bevor sie an WCF übergeben wird.

Als ich versuchte, diese Technik auf Web Services anzuwenden, fand ich, dass es nicht funktionierte. Obwohl die Hilfsklasse im gleichen Zustand ausgeführt wurde, in der sie vom WCF-Client verwendet wurde, enthielt die HTTP-Anforderung nicht den Header "Accept-Encoding: ...".

Um diese Arbeit für Web Service zu machen, hatte ich die Web-Proxy-Klasse zu bearbeiten, und fügen Sie diese Methode:

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

Beachten Sie, dass es nicht darum, ob war der CompressibleHttpRequestCreator und Block aus der Anwendung Konfigurationsdatei war egal Gegenwart oder nicht. Bei Webdiensten hat nur das Überschreiben von GetWebRequest im Web-Service-Proxy funktioniert.

+6

Warum posten Sie Ihre Lösung nicht als Antwort, sondern als Teil der Frage, damit Sie sie akzeptieren können? –

+4

Was bedeutet das? "Damit dies für Web Services funktioniert, musste ich die Web Proxy-Klasse bearbeiten und diese Methode hinzufügen:"? Was ist die Web-Proxy-Klasse? – Naor

Antwort

1

Here's an answer I gave zu einer anderen Frage zu dem Thema. Diese Frage wurde aus der Perspektive von ADO.NET Data Services gestellt, aber meine Antwort lautete rein auf WCF.

2

Danke für Ihren WCF-Tipp! Wir werden die IIS-Komprimierung für Dienste in meinem Geschäft aktivieren, und ich hoffe, dass Ihre Lösung funktioniert. Mit "Um dies für Web Services arbeiten" - meintest du Old School SoapHttpProtocol Clients? Da die SoapHttpProtocol-Klasse über eine integrierte EnableDecompression-Eigenschaft verfügt, die automatisch den Header und die Antwortbehandlung der Komprimierung behandelt.

+0

Während die Antwort des OP direkt in seiner Frage funktioniert, ist dies die beste und richtige Lösung. Sollte als Antwort akzeptiert werden. Danke, dass du das unterstrichen hast! – Marek