添加GZIP到WCF REST服务在C#GZIP、WCF、REST

2023-09-04 01:15:34 作者:她说我未进她心/

我无法使GZIP COM pression在我的C#.NET WCF Web服务,并希望有人会知道我在App.conf配置文件是缺少,或者是额外的制作时,需要呼吁在code启动Web服务。

I'm having trouble enabling GZIP compression on my C#.NET WCF web service and was hoping someone might know what I'm missing in my App.conf configuration file, or what extra is needed when making the call to start the web service in the code.

我跟着链接应用GZIP的COM pression到WCF服务的那个点,增加GZIP的微软例子下载,但这个例子不与我如何设置我的web服务相关。

I've followed the link Applying GZIP Compression to WCF Services that points to the download of Microsoft example of adding GZIP but the example does not correlate with how I'm setting up my web service.

所以,我的App.conf看起来像

So my App.conf looks like

<?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>

我只是复制从MS例如在配置和GZIP类到我的项目,并添加我的相应和Web服务的configs。 在code我用来启动Windows服务是:

I simply copied the config and GZIP classes from the MS example into my project and added my relevent web service configs. The code I'm using to start the windows service is:

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

web服务运行正常,但菲德勒没有检测实现从Web浏览器呼叫时回来用gzip COM pressesion任何回应。我也试图通过编程方式来设置和运行与GZIP的web服务,但惨遭失败。作为绿色的,我不知道还有什么我需要配置,任何的建议是感激

The webservice runs fine but Fiddler does not detect any response coming back with GZIP compressesion when making a call from a web browser. I also tried programmatically to setup and run the webservice with GZIP but failed miserably. Being green I'm not sure what else I need to configure, any advice is greatful

我已经钻研深入到这一点,并发现了,因为我跑,它必须是压倒一切的习俗GZIP与的WebHttpBinding对象app.conf文件WebServiceHost默认为,结合web服务作为WebServiceHost对象,意味着什么现身Web服务不会是连接codeD。 为了解决这个问题我想我会写编程自定义GZIP绑定到code

I've delved deeper into this and found out that since I'm running the webservice as a WebServiceHost object that it must be overriding the custom GZIP binding in the app.conf file with the WebHTTPBinding object that WebServiceHost defaults to, which means anything coming out of the web service will not be encoded. To get around this I figured that I would programmatically write the custom GZIP binding into the code

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();

的问题是,它不会允许与WebHttpBehavior自定义绑定。但是,如果我删除的行为,然后我的REST Web服务变成丑陋,预计流对象在我的合同投入。我不知道如何配置行为,所以任何的帮助感激。

The problem is that it won't allow a custom binding with the WebHttpBehavior. But if I remove the behavior then my REST webservice turns ugly and expects Stream objects as inputs in my contracts. I'm not sure how to configure behaviours so any help is greatful.

推荐答案

因此​​,这里的编程解决方案,我想出了这个花天后。请注意,我不知道如何配置app.config文件,但只能通过code中的解决方案。 首先按照此链接获取和修复微软的编码样本中的GZIP类。然后用下面的例子code作为配置自己的Web服务的基础。

So Here's the programmatic solution I've come up with after spending days on this. Note that I do not know how to configure the solution in the app.config file but only through code. Firstly follow this Link to obtain and fix the GZIP classes in Microsoft's coding samples. Then use the below example code as a basis for configuring your own 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";
    }
}

我的工作大多了这一点,通过以下方法的链接。

请注意:这有点令我感到困惑怎么微软还没有建立GZIP本身为WCF是任何REST Web服务返回的大型数据集的这样一个重要组成部分。

Note: It somewhat baffles me how Microsoft haven't built GZIP natively into WCF being such an essential part of any REST webservice returning large sets of data.