2013-05-21 9 views
10

Wie kann ich die Komprimierung für POST-Daten aktivieren, die auf einen .NET WebService hochgeladen werden (SOAP, nicht WCF)? Ich dachte, es wäre eine einfache Sache von enabling dynamic compression in IIS aber nach der Aktivierung, es ist nur die Antwort, nicht die POST Anfrage.Wie aktiviere ich die GZIP-Komprimierung für POST (Upload) -Anfragen an einen SOAP WebService auf IIS 7?

Ich habe es als Service-Referenz hinzugefügt und ich kann keine Einstellungen auf dem generierten SOAPClient finden, um die Komprimierung von Anfragen zu ermöglichen.

Es scheint, dass ich eine Konfigurationseinstellung oder Code auf der Client-Seite fehlt, um die Anfrage vor dem Senden an den Server zu komprimieren? Oder wird was ich versuche zu tun (GZippen von POST-Daten) nicht einmal unterstützt?

Weitere Informationen: Ich verwende .NET 4.0 auf dem Client und Server.

+0

Bitte auf diese SO Post (http://stackoverflow.com/questions/4416177/how-to-compress-http-requests-from-wcf-net-at-the-transport-level) – Rajesh

Antwort

13

Ich habe auf diese 4 Jahren gebloggt vor

http://netpl.blogspot.com/2009/07/aspnet-webservices-two-way-response-and.html

Ich frage mich, warum diese durch googeln nicht gefunden. Wie auch immer, das sollte für Sie funktionieren, wir arbeiten seit 4 Jahren in einer Produktionsumgebung.

+0

Eigentlich habe ich diesen Code bereits benutzt, aber er hatte ein paar Bugs, die ich nicht beheben konnte. Allerdings habe ich mehr Zeit damit verbracht und die Fehler behoben. Meine Version behebt die folgenden Probleme: Setzen Sie den Content-Encoding-GZIP-Header, wenn eine Ausnahme auf dem Server auftritt. Zweiter Fix: Versuchen Sie nicht, den GZIP-Anforderungsstream zu entschlüsseln, wenn die Anfrage nicht GZIPed war. Ich habe die aktualisierte Version des Codes hier veröffentlicht: http://pastebin.com/Aak9FUiw – NickG

+0

Vielen Dank für die ursprüngliche Lösung. Ich werde Ihnen das Kopfgeld vergeben :) – NickG

+0

Die dritte Lösung bestand darin, die Verdoppelung des Headers "content-encoding" zu unterdrücken, so dass es zu "gzip, gzip" wurde. Nicht sicher, ob das wirklich notwendig ist, aber es ist nicht korrekt. – NickG

6

Am Ende habe ich die Antwort von Wiktor Zychla benutzt, bin aber auf ein paar Bugs gestoßen (auch in den Kommentaren zu diesem Artikel erwähnt). Der Vollständigkeit halber werde ich meine feste Version des HttpCompression-Moduls hier veröffentlichen, aber der Rest des Codes (und der Implementierungsrichtlinien), die Sie benötigen, sind in Wiktor's article.

UPDATE:

Ich habe mit diesem Code tatsächlich musste aufhören, da es einen Fehler hat, kann ich nicht (auch nicht mit meiner verbesserten Version weiter unten) beheben. Für viele Leute hinter Proxy-Servern kommt es zu einem Fehler, der besagt: "Die magische Nummer im gzip-Header ist falsch" und ich kann nicht herausfinden, wie ich das beheben kann. Ich denke, das liegt daran, dass Proxy-Server GZIP dekomprimieren und dieser Code nicht erlaubt, sowohl gezippte als auch nicht gezippte Antworten in seiner aktuellen Form zu empfangen.

using System; 
using System.IO.Compression; 
using System.Web; 
using System.Web.Security; 

/// <summary> 
/// Implement two way HTTP compression for the SOAP API 
/// Code taken from: http://netpl.blogspot.co.uk/2009/07/aspnet-webservices-two-way- response-and.html 
/// Fix: Set Content-encoding: gzip header when an Exception occurs on the server. 
/// Fix: Do not attempt to decrypt GZIP request stream when request was not GZIPed. 
/// </summary> 
public class HttpCompressionModule : IHttpModule 
{ 
    private bool isDisposed = false; 

    ~HttpCompressionModule() 
    { 
      Dispose(false); 
    } 

    public void Init(HttpApplication context) 
    { 
      context.BeginRequest += new EventHandler(Context_BeginRequest); 
      context.PreSendRequestHeaders += new EventHandler(context_PreSendRequestHeaders); 
    } 

    void context_PreSendRequestHeaders(object sender, EventArgs e) 
    { 
      // Fix headers having been lost if an exception occurred. 
      HttpApplication app = sender as HttpApplication; 
      HttpContext ctx = app.Context; 
      if (app.Response.Filter is GZipStream) SetEncoding("gzip"); 
      else if (app.Response.Filter is DeflateStream) SetEncoding("deflate"); 

      // Fix double header 
      if (ctx.Response.Headers["Content-encoding"] == "gzip,gzip") 
        ctx.Response.Headers.Set("Content-encoding", "gzip"); 
    } 

    public void Context_BeginRequest(object sender, EventArgs e) 
    { 
      HttpApplication app = sender as HttpApplication; 
      HttpContext ctx = app.Context; 

      // Currently only enable for the Uploader API webservice 
      if (!ctx.Request.Url.PathAndQuery.ToLower().Contains("uploaderapi.asmx")) 
      { 
        return; 
      } 

      // Add request filter if request was GZIP encoded 
      string requestEncoding = ctx.Request.Headers["Content-encoding"]; 
      if (requestEncoding != null && requestEncoding == "gzip") 
      { 
       app.Request.Filter = 
        new System.IO.Compression.GZipStream(app.Request.Filter, CompressionMode.Decompress); 
      } 

      // Add response compression filter if the client accepts compressed responses 
      if (IsEncodingAccepted("gzip")) 
      { 
        app.Response.Filter = new GZipStream(app.Response.Filter, CompressionMode.Compress); 
        SetEncoding("gzip"); 
      } 
      else if (IsEncodingAccepted("deflate")) 
      { 
        app.Response.Filter = new DeflateStream(app.Response.Filter, CompressionMode.Compress); 
        SetEncoding("deflate"); 
      } 
    } 

    private bool IsEncodingAccepted(string encoding) 
    { 
      return HttpContext.Current.Request.Headers["Accept-encoding"] != null && 
        HttpContext.Current.Request.Headers["Accept-encoding"].Contains(encoding); 
    } 

    private void SetEncoding(string encoding) 
    { 
      HttpContext ctx = HttpContext.Current; 
      string responseEncodings = ctx.Response.Headers.Get("Content-encoding"); 
      if (responseEncodings == null || !responseEncodings.Contains(encoding)) 
        HttpContext.Current.Response.AppendHeader("Content-encoding", encoding); 
    } 

    public void Dispose() 
    { 
      Dispose(true); 
    } 

    private void Dispose(bool dispose) 
    { 
      isDisposed = dispose; 
    } 
} 
+2

Nick, denken Sie daran, dass dies keine vollständige Antwort ist.Sowohl HttpResponseDecompressed und HttpRequestCompressed sind ebenfalls erforderlich. –

+0

@WiktorZychla Danke - Ich habe meine Antwort aktualisiert, um klarzustellen, dass Ihr Artikel den gesamten Code/Anweisungen enthält.Ihre Antwort ist nur, um die Bugs/Kompatibilitätsprobleme, die ich gefunden habe, zu beheben (und wird redundant sein, wenn Sie sie in Ihre integrieren – NickG

+0

Nick, wegen Ihrer klaren Erklärung werde ich keine Änderungen an dem Eintrag vornehmen Ich nehme an, dass jeder, der versucht, davon Gebrauch zu machen, Ihre Kommentare findet und Ihren aktualisierten Ansätzen folgt CH. Froh, dass die Lösung geholfen hat und danke für Ihre Korrekturen. –