Mr *_*owe 7 .net c# wcf gzip web-services
我在C#.NET WCF Web服务上启用GZIP压缩时遇到了麻烦,并希望有人可能知道我在App.conf配置文件中缺少的内容,或者在调用启动Web服务时需要多少额外费用代码.
我已经按照将GZIP压缩应用到WCF服务的链接指向下载Microsoft添加GZIP的示例,但该示例与我如何设置我的Web服务无关.
所以我的App.conf看起来像
<?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>
Run Code Online (Sandbox Code Playgroud)
我只是将配置和GZIP类从MS示例复制到我的项目中,并添加了我相关的Web服务配置.我用来启动Windows服务的代码是:
WebServiceHost webserviceHost = new WebServiceHost(typeof(MyService.Service1));
webserviceHost.Open();
Run Code Online (Sandbox Code Playgroud)
webservice运行正常,但是当从Web浏览器拨打电话时,Fiddler没有检测到任何带有GZIP压缩的响应.我还尝试以编程方式使用GZIP设置和运行Web服务,但失败了.绿色我不知道还需要配置什么,任何建议都很棒
我深入研究了这一点并发现,因为我将Web服务作为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();
Run Code Online (Sandbox Code Playgroud)
问题是它不允许与WebHttpBehavior进行自定义绑定.但是如果我删除了这个行为,那么我的REST Web服务变得丑陋,并期望Stream对象作为我合同中的输入.我不确定如何配置行为,所以任何帮助都很棒.
这是我花了几天时间想出的程序化解决方案。请注意,我不知道如何在 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";
}
}
Run Code Online (Sandbox Code Playgroud)
我通过点击此链接解决了大部分问题。
注意:让我有些困惑的是,Microsoft 为何没有将 GZIP 原生构建到 WCF 中,使其成为任何返回大量数据的 REST Web 服务的重要组成部分。
归档时间: |
|
查看次数: |
7418 次 |
最近记录: |