2012-10-02 15 views
7

Ich habe Probleme beim Aktivieren der GZIP-Komprimierung für meinen C# .NET WCF-Webdienst und hoffte, dass jemand wüsste, was ich in meiner App.conf-Konfigurationsdatei vermisse oder welches Extra erforderlich, wenn der Aufruf zum Starten des Webdienstes im Code ausgeführt wird.Hinzufügen von GZIP zum WCF-REST-Service in C#

Ich habe den Link Applying GZIP Compression to WCF Services gefolgt, der auf den Download von Microsoft Beispiel des Hinzufügens von GZIP zeigt, aber das Beispiel korreliert nicht mit, wie ich meinen Webservice einrichte.

So sieht mein App.conf wie

<?xml version="1.0"?> 
<configuration> 
    <system.serviceModel> 
    <services> 
     <service name="MyService.Service1"> 
     <endpoint address="http://localhost:8080/webservice" binding="webHttpBinding" contract="MyServiceContract.IService"/> 
     </service> 
    </services> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior> 
      <webHttp /> 
     </behavior> 
     </endpointBehaviors> 
    </behaviors> 
    <extensions> 
     <bindingElementExtensions> 
     <add name="gzipMessageEncoding" type="MyServiceHost.GZipMessageEncodingElement, MyServiceHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
     </bindingElementExtensions> 
    </extensions> 
    <protocolMapping> 
     <add scheme="http" binding="customBinding" /> 
    </protocolMapping> 
    <bindings> 
     <customBinding> 
     <binding> 
      <gzipMessageEncoding innerMessageEncoding="textMessageEncoding"/> 
      <httpTransport hostNameComparisonMode="StrongWildcard" manualAddressing="False" maxReceivedMessageSize="65536" authenticationScheme="Anonymous" bypassProxyOnLocal="False" realm="" useDefaultWebProxy="True"/> 
     </binding> 
     </customBinding> 
    </bindings> 
    </system.serviceModel> 
    <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> 
    </startup> 
</configuration> 

ich einfach die Config und GZIP Klassen aus dem MS Beispiel in mein Projekt kopiert und hinzugefügt meine relevent Web-Service-Konfigurationen. Der Code, den ich mit dem Windows-Dienst zu starten ist:

WebServiceHost webserviceHost = new WebServiceHost(typeof(MyService.Service1)); 
webserviceHost.Open(); 

Der Webservice läuft gut, aber Fiddler erkennen keine Reaktion mit GZIP der Komprimierung zurückkommen, wenn ein Anruf von einem Web-Browser zu machen. Ich habe auch versucht, programmatisch den Webservice mit GZIP einzurichten und auszuführen, scheiterte aber kläglich. Ich bin nicht sicher, was ich noch konfigurieren muss, ist jeder Rat dankbar

Ich habe tiefer in diese und habe herausgefunden, dass, da ich den Webservice als WebServiceHost-Objekt ausführen, dass es überschrieben werden muss Benutzerdefinierte GZIP-Bindung in der app.conf-Datei mit dem WebHTTPBinding-Objekt, das WebServiceHost standardmäßig verwendet, was bedeutet, dass alles, was aus dem Web-Service herauskommt, nicht codiert wird. Um dies zu umgehen dachte ich, dass ich programmatisch die benutzerdefinierte GZIP in den Code-Bindung

var serviceType = typeof(Service1); 
var serviceUri = new Uri("http://localhost:8080/webservice"); 
var webserviceHost = new WebServiceHost(serviceType, serviceUri); 
CustomBinding binding = new CustomBinding(new GZipMessageEncodingBindingElement(), new HttpTransportBindingElement()); 
var serviceEndPoint = webserviceHost.AddServiceEndpoint(typeof(IService), binding, "endpoint"); 
webserviceHost.Description.Endpoints[0].Behaviors.Add(new WebHttpBehavior { HelpEnabled = true }); 
webserviceHost.Open(); 

Das Problem ist, schreiben würde, dass es nicht eine individuelle Bindung mit dem WebHttpBehavior ermöglichen. Aber wenn ich das Verhalten entferne, wird mein REST-Webservice hässlich und erwartet Stream-Objekte als Eingaben in meinen Verträgen. Ich bin mir nicht sicher, wie ich Verhaltensweisen konfigurieren soll, damit jede Hilfe hilfreich ist.

Antwort

4

Also hier ist die programmatische Lösung, die ich nach Tagen auf diesem Thema gefunden habe. Beachten Sie, dass ich nicht weiß, wie Sie die Lösung in der Datei app.config konfigurieren, sondern nur über Code. Folgen Sie zunächst dieser Link, um die GZIP-Klassen in Microsofts Coding Samples zu erhalten und zu reparieren. Verwenden Sie den folgenden Beispielcode als Grundlage für die Konfiguration Ihres eigenen Web-Service.

//Some class class to start up the REST web service 
public class someClass(){ 
    public static void runRESTWebservice(){ 
     webserviceHost = new WebServiceHost(typeof(Service1), new Uri("http://localhost:8080)); 
     webserviceHost.AddServiceEndpoint(typeof(IService), getBinding(), "webservice").Behaviors.Add(new WebHttpBehavior()); 
     webserviceHost.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true }); 
    } 

    //produces a custom web service binding mapped to the obtained gzip classes 
    private static Binding getBinding(){ 
     CustomBinding customBinding = new CustomBinding(new WebHttpBinding()); 
     for (int i = 0; i < customBinding.Elements.Count; i++) 
     { 
      if (customBinding.Elements[i] is WebMessageEncodingBindingElement) 
      { 
       WebMessageEncodingBindingElement webBE = (WebMessageEncodingBindingElement)customBinding.Elements[i]; 
       webBE.ContentTypeMapper = new MyMapper(); 
       customBinding.Elements[i] = new GZipMessageEncodingBindingElement(webBE); 
      } 
      else if (customBinding.Elements[i] is TransportBindingElement) 
      { 
       ((TransportBindingElement)customBinding.Elements[i]).MaxReceivedMessageSize = int.MaxValue; 
      } 
     } 
     return customBinding; 
    } 
} 

//mapper class to match json responses 
public class MyMapper : WebContentTypeMapper{ 
    public override WebContentFormat GetMessageFormatForContentType(string contentType){ 
     return WebContentFormat.Json; 
    } 
} 

//Define a service contract interface plus methods that returns JSON responses 
[ServiceContract] 
public interface IService{ 
    [WebGet(UriTemplate = "somedata", ResponseFormat = WebMessageFormat.Json)] 
    string getSomeData(); 
} 

//In your class that implements the contract explicitly set the encoding of the response in the methods you implement 
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] 
public class Service1 : IService 
{ 
    public string getSomeData() 
    { 
     WebOperationContext.Current.OutgoingResponse.Headers[HttpResponseHeader.ContentEncoding] = "gzip"; 
     return "some data"; 
    } 
} 

Ich arbeitete das meiste aus, indem ich diesem link folgte.

Hinweis: Es verunsichert mich, dass Microsoft GZIP nativ nicht in WCF integriert hat, da es ein wesentlicher Bestandteil eines REST-Webservice ist, der große Datenmengen zurückgibt.

0

Wenn Sie RestService und IIS (> = 7.0) verwenden, müssen Sie dies nicht selbst tun!

IIS 7 unterstützt dynamische Komprimierung, die die automatische Komprimierung von Inhalten ermöglicht, die in Ihren eigenen Anwendungen erstellt wurden (ASP.NET, MVC, WCF oder anders!). Das Schema basiert auf Sniffing vom Inhaltstyp und funktioniert daher mit jeder Art von Webanwendungs-Framework.

Finden Sie ein komplettes Tutorial here.

+0

Ich habe Angst, dass ich mit IIS nicht, sondern es als seine eigenen ausführbaren Windows-Dienst-Anwendung zu verteilen, mit so nicht auf Kunden ihre eigenen IIS angewiesen einrichten. –

+1

Endlich habe ich das Problem durch Code gelöst. Ich hatte Recht, dass eine benutzerdefinierte Bindung für den webServiceHost benötigt wird, aber in einem WebHttpBinding in seinem Konstruktor initialisiert werden muss, dann ordnen Sie ihm das gzip-Bindungselement und einen Mapper zu. Als nächstes müssen Sie in jeder der Methoden, die den Webserververtrag implementieren, die Inhaltscodierung der Antwortheader explizit in "gzip" ändern. Dieser Link half http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/8c3eafae-b6a1-441f-85ef-90721d941a1a –

3

Als Reaktion auf Ihren Kommentar zu GZIP, das nicht nativ von WCF unterstützt wird, wurde es in .Net 4.5 hinzugefügt. Siehe here.

0

Aus irgendeinem Grund konnte ich die obige Implementierung nicht für selbst gehosteten WCF REST mit Json + -Komprimierung, nur für XML arbeiten.

Nachdem wir uns eine Zeit lang frustriert umsahen, fanden wir endlich die Lösung aus einem sehr aktuellen Blog. Hoffe das hilft jedem, der immer noch nach dem gleichen sucht.

https://blogs.msdn.microsoft.com/carlosfigueira/2016/02/23/using-automatic-format-selection-with-a-compression-encoder-in-self-hosted-scenarios/

Verwandte Themen