C# 在C中向WCF REST服务添加GZIP#

C# 在C中向WCF REST服务添加GZIP#,c#,.net,wcf,web-services,gzip,C#,.net,Wcf,Web Services,Gzip,我在C#.NET WCF web服务上启用GZIP压缩时遇到问题,希望有人知道我在App.conf配置文件中缺少了什么,或者在代码中调用启动web服务时需要额外的什么 我已经跟随了指向Microsoft添加GZIP示例下载的链接,但该示例与我如何设置web服务无关 //Some class class to start up the REST web service public class someClass(){ public static void runRESTWebservic

我在C#.NET WCF web服务上启用GZIP压缩时遇到问题,希望有人知道我在App.conf配置文件中缺少了什么,或者在代码中调用启动web服务时需要额外的什么

我已经跟随了指向Microsoft添加GZIP示例下载的链接,但该示例与我如何设置web服务无关

//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";
    }
}
所以我的App.conf看起来像


我只是将MS示例中的config和GZIP类复制到我的项目中,并添加了相关的web服务配置。 我用来启动windows服务的代码是:

WebServiceHost webserviceHost = new WebServiceHost(typeof(MyService.Service1));
webserviceHost.Open();
webservice运行良好,但Fiddler在从web浏览器进行调用时未检测到任何GZIP压缩返回的响应。我还尝试用GZIP编程设置和运行webservice,但失败惨重。由于是绿色的,我不确定我还需要配置什么,任何建议都非常有用

我对此进行了更深入的研究,发现由于我将webservice作为WebServiceHost对象运行,它必须使用WebServiceHost默认的WebHTTPBinding对象覆盖app.conf文件中的自定义GZIP绑定,这意味着任何来自web服务的内容都不会被编码。 为了解决这个问题,我想我应该以编程方式将自定义GZIP绑定写入代码中

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服务就会变得丑陋,并期望流对象作为我的契约中的输入。我不知道如何配置行为,因此任何帮助都是非常有用的。

如果您使用的是RestService和IIS(>=7.0),您将不必自己执行此操作

IIS 7支持动态压缩,允许自动压缩在您自己的应用程序(ASP.NET、MVC、WCF或其他)中创建的内容。该方案基于内容类型嗅探,因此适用于任何类型的Web应用程序框架


请找到完整的教程。

这是我花了几天的时间才想出的编程解决方案。请注意,我不知道如何在app.config文件中配置解决方案,但只能通过代码进行配置。 首先,按照此步骤获取并修复Microsoft编码示例中的GZIP类。然后使用下面的示例代码作为配置您自己的web服务的基础

//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";
    }
}
//启动REST web服务的某个类
公共类someClass(){
公共静态void runRESTWebservice(){
webserviceHost=新的webserviceHost(typeof(Service1),新的Uri(“http://localhost:8080));
webserviceHost.AddServiceEndpoint(typeof(IService),getBinding(),“webservice”).Behaviors.Add(newWebHttpBehavior());
webserviceHost.Description.Behaviors.Add(新ServiceMetadataBehavior{HttpGetEnabled=true});
}
//生成映射到获得的gzip类的自定义web服务绑定
私有静态绑定getBinding(){
CustomBinding CustomBinding=新的CustomBinding(新的WebHttpBinding());
对于(int i=0;i
我大部分都是按照这个来做的


注意:我有点困惑,为什么微软没有将GZIP本机构建到WCF中,而WCF是任何REST Web服务返回大数据集的重要组成部分。

对于您关于WCF本机不支持GZIP的评论,它已添加到.Net 4.5中。请参阅。

,由于某种原因,我无法使上述实现正常工作对于带有Json+压缩的自托管WCF REST,仅适用于XML

在沮丧地四处寻找了一段时间后,终于从下面的一个最近的博客中找到了解决方案。希望这能帮助那些仍然在寻找同样东西的人


我担心我没有使用IIS,而是将其作为自己的可执行windows服务应用程序分发,因此不必依赖客户端设置自己的IIS。最后,我通过代码解决了这个问题。我认为webServiceHost需要自定义绑定,但需要使用WebHttpBinding初始化在其