2010-12-07 5 views
9

Ich habe eine asp.net .asmx Webservice geschrieben, um Anfragen von einem Drittanbieter-Tool zu behandeln. Das Third-Party-Tool stellt eine HTTP-POST-Anfrage an den Webservice, um Benutzerinformationen zu erhalten. Ich benutze IIS7asp.net webservice handling gzip komprimierte Anfrage

Running Fiddler mit "Remove All Encodings" aktiviert, kann ich den Webservice-Aufruf sehen und alles funktioniert ordnungsgemäß. Wenn ich "Remove All Encodings" deaktivieren, schlägt der Webservice-Aufruf mit einer 400 Bad Request fehl. Der Unterschied, den ich sehe, ist, dass der Header "Content-Encoding: gzip" von Fiddler entfernt wird und der Inhalt dekomprimiert wird.

Wenn also der Content-Encoding-Header entfernt und der Inhalt dekomprimiert wird, funktioniert mein Webservice einwandfrei. Wenn der Header vorhanden ist und der Inhalt komprimiert ist, schlägt der Webservice fehl.

Wie kann ich entweder:

  1. mein Webservice Konfigurieren Sie den Client zu sagen, dass es keine Druck Anforderungen annimmt (und hoffen, dass die Drittanbieter-Tool respektiert, dass)
  2. Dekomprimieren der Inhalt in den frühen asp.net Handhabung
  3. meine Webservice ändern mit komprimierten Daten

-Update zu arbeiten: um es klar, ich brauche nicht Um die Gzip-Kodierung in der Response zu konfigurieren, muss ich mich mit einer Anfrage an meinen Webservice beschäftigen, der Gzip-kodiert ist.

Update 2: Das Tool von Drittanbietern ist das Salesforce.com Outlook-Plug-in. Also, ich habe keinen Zugriff darauf, es zu ändern und es wird von vielen anderen Firmen ohne Probleme verwendet. Es muss etwas sein, ich tue (oder nicht zu tun)

Update 3: ich einen Beitrag here gefunden, die besagen, dass IIS keine eingehenden POST-Anfragen mit komprimierten Daten nicht unterstützt, es unterstützt nur komprimierte Antworten. Kann das immer noch wahr sein?

Antwort

1

Ich habe eine Teilantwort here gefunden.

class DecompressStream : Stream 
{ 
    ... 

    public override int Read(byte[] buffer, int offset, int count) 
    { 
     GZipStream test = new GZipStream(_sink, CompressionMode.Decompress); 

     int c = test.Read(buffer, offset, count); 

     return c; 
    } 

    ... 
} 

dann kann ich den Filter auf das Request-Objekt wie folgt an:

void Application_BeginRequest(object sender, EventArgs e) 
    { 
     string contentEncoding = Request.Headers["Content-Encoding"]; 
     Stream prevCompressedStream = Request.Filter; 

     if(contentEncoding == null || contentEncoding.Length == 0) 
      return; 

     contentEncoding = contentEncoding.ToLower(); 

     if(contentEncoding.Contains("gzip")) 
     { 
      Request.Filter = new DecompressStream(Request.Filter); 
     } 
    } 

I Teil Antwort sagen, denn auch wenn ich jetzt die eingehende Anforderung verarbeiten kann, ist die Antwort eine bekommen " Content-Encoding: gzip "header, obwohl die Antwort nicht codiert ist. Ich kann in Fiddler überprüfen, dass der Inhalt nicht codiert ist.

Wenn ich die Antwort verschlüsseln, schlägt der Client für den Webservice fehl. Es sieht so aus, als würde es "Accept-Encoding: gzip" senden, aber es akzeptiert keine gzip komprimierte Antwort. Ich kann in Fiddler überprüfen, dass die Antwort komprimiert ist und Fiddler wird es erfolgreich dekomprimieren.

So, jetzt stecke ich fest, versuchen, eine verirrte "Content-Encoding: Gzip" Header aus der Antwort entfernt zu bekommen. Ich habe alle Verweise, die ich finden kann, aus der Anwendung, web.config und IIS, zur Komprimierung entfernt.

+0

Ich habe schon seit einigen Jahren nicht mehr mit ASP-Webdiensten (.asmx) gearbeitet, konnte aber nicht auf die Antwortheader mit HttpContext.Current.Response.Headers zugreifen? –

+0

@Florin, Sie haben Recht. Ich konnte den störenden Header in der PostRequestHandlerExecute-Funktion entfernen UND den Accelpt-Encoding-Header aus der eingehenden Anfrage in der BeginRequest-Funktion entfernen. Musste beides tun, damit es funktioniert. – Geoff

1

GZIP-Komprimierung ist eine Funktion des Servers.

Wenn Sie IIS6 verwenden, wenden Sie sich an this link.

Wenn Sie IIS7 verwenden, können Sie gzip mit ISAPI_Rewrite deaktivieren. Siehe this link.

Da gzip eine Funktion von IIS ist, sollten Sie wirklich nichts "Spezielles" tun müssen, damit es mit einem Webdienst funktioniert (IIS sollte die Dekomprimierung und Komprimierung von Anforderungen übernehmen). Hoffentlich wird diese Information Sie weiter zur Problembehandlung und zur Lösung des Problems bringen.

+0

Danke, aber so weit hilft das nicht. Ich kann die Komprimierung in IIS7 deaktivieren, indem ich die Kontrollkästchen in den Konfigurationseinstellungen deaktivieren. Dies scheint jedoch nur die Antwort vom Server zu beeinflussen. Ich muss mit einer Anfrage zu dem Server umgehen, der komprimiert wird. – Geoff

+0

Hier ist die gzip Client/Server-Konversation funktioniert normalerweise: http://www.websiteoptimization.com/speed/tweak/compress/ –

+0

Es kann sein, dass Ihr Drittanbieter-Tool nicht nett spielt. –

2

Da der 3rd Party Service Ihnen nur einen POST sendet, glaube ich nicht, dass es möglich ist, ihnen zu sagen, dass sie nicht komprimiert senden sollen.

Sie könnten versuchen, GetWebRequest außer Kraft zu setzen und sie auf dem Weg zu dekomprimieren in

public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol 

{ 
protected override WebRequest GetWebRequest(Uri uri) 
{ 
    base.GetWebRequest(uri);request.AutomaticDecompression = System.Net.DecompressionMethods.GZip; 
    return request; 
} 
} 
+0

Danke. Leider kommt die Anfrage nie so weit. Ihre Antwort führte mich dazu, herauszufinden, dass der letzte Aufruf in der Kette, der Erfolg hat, PreRequestHandlerExecute ist, und das führte mich zu dem Versuch, die Eingabe zu filtern, wie in meiner Antwort beschrieben. – Geoff

1

Ich bin nicht sicher, dass IIS dekomprimiert eingehende Anfragen unterstützt, so könnte dies weiter unten das Rohr durchgeführt werden müssen.

Shiraz 'Antwort hat das Potenzial zu arbeiten und es wäre das erste, was ich versuchen würde.

Wenn das nicht funktioniert, können Sie den Server asmx-Dienst auf WCF umstellen, was zwar etwas schwieriger ist, aber auch mehr Flexibilität bietet.

Auf der WCF-Seite gibt es zwei Dinge, die ich vorschlagen kann. Die erste ist relativ einfach zu implementieren und basiert auf dem Festlegen des WebRequest-Objekts, das von WCF verwendet wird, um die Komprimierung automatisch zu akzeptieren. Sie finden die Details here. Dies ist der WCF, der der von Shiraz vorgeschlagenen Lösung entspricht.

Die zweite ist komplizierter, da es die Erstellung von benutzerdefinierten Message Encoders beinhaltet, aber wenn keine der oben genannten Methoden funktioniert, sollte dies das Problem lösen. Das Erstellen eines Nachrichtenkompressions-Codierers wird beschrieben unter here. Vielleicht möchten Sie auch die Antwort in here überprüfen, die eine Beispielkonfiguration für den Nachrichtenencoder präsentiert.

Bitte lassen Sie mich wissen, ob dies geholfen hat oder Sie weitere Hilfe benötigen.

5

Die einfachste Methode besteht darin, einen HttpModule zu erstellen, der den Anforderungsfilter ersetzt. Es ist wiederverwendbar und vermeidet eine Global.asax. Es ist auch nicht notwendig, eine neue Dekomprimierungs-Stream-Klasse zu erstellen, da die GZipStream dafür bereit ist. Hier ist der vollständige Code, die auch die Content-Encoding: gzip entfernt, die nicht benötigt wird, nicht mehr:

public class GZipRequestDecompressingModule : IHttpModule 
{ 
    public void Init(HttpApplication context) 
    { 
     context.BeginRequest += (sender, e) => 
     { 
      var request = (sender as HttpApplication).Request; 

      string contentEncoding = request.Headers["Content-Encoding"]; 

      if (string.Equals(contentEncoding, "gzip", 
       StringComparison.OrdinalIgnoreCase)) 
      { 
       request.Filter = new GZipStream(request.Filter, 
        CompressionMode.Decompress); 
       request.Headers.Remove("Content-Encoding"); 
      } 
     }; 
    } 
    public void Dispose() 
    { 
    } 
} 

dieses Modul zu aktivieren, den folgenden Abschnitt in Ihrer web.config hinzufügen:

<system.webServer> 
    <modules runAllManagedModulesForAllRequests="true"> 
     <add name="AnyUniqueName" 
      type="YourNamespace.GZipRequestDecompressingModule, YourAssembly" 
      preCondition="integratedMode" /> 
    </modules> 
</system.webServer> 
+0

Kann dieses Modul nur auf bestimmten Wegen aktiviert werden, um mögliche Nebenwirkungen zu vermeiden? Dh aktivieren Sie es nur für ASMX-Dateien? – NickG

+1

Verwenden Sie das [location element] (http://msdn.microsoft.com/en-us/library/b6x6shw7 (v = vs.100) .aspx) in der Datei web.config, in der Sie ein Pfadattribut angeben erforderlich. – Mart

+0

BTW: anstelle von string.Equals (contentEncoding, "gzip", StringComparison.OrdinalIgnoreCase) können Sie contentEncoding.ToLower() == "gzip" das ist viel schneller zu schreiben :) – NickG