[英]GZip compression in WCF WebService
I have a .NET 3.5 Webservice Hosted on IIS7.5. 我在IIS7.5上有一个.NET 3.5 Webservice。
I have a client application who connects to this webservice. 我有一个连接到此Web服务的客户端应用程序。
I changed (in client application) the httpWebRequest.Create method to add automaticDecompression for GZip but it isn't working 我更改了(在客户端应用程序中)httpWebRequest.Create方法为GZip添加automaticDecompression但是它不起作用
WebRequest IWebRequestCreate.Create(Uri uri)
{
HttpWebRequest httpWebRequest =
Activator.CreateInstance(
typeof(HttpWebRequest),
BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null,
new object[] { uri, null },
null) as HttpWebRequest;
if (httpWebRequest == null)
return null;
httpWebRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
return httpWebRequest;
}
In this way the request is sent correctly, the answer is encoded in gzip (I see it from Fiddler), but an exception occurs: 通过这种方式正确发送请求,答案以gzip编码(我从Fiddler看到),但发生异常:
Response is not wellformed XML
(I think the client doesn't decode the answer) (我认为客户端没有解码答案)
If I remove this row, as in MSDN documentation 如果我删除此行,如在MSDN文档中
httpWebRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
The answer is not GZip encoded (and in the request there's no ACCEPT-ENCODING header) 答案不是GZip编码(在请求中没有ACCEPT-ENCODING标头)
I've done this to transfer DataTable objects using WCF with DataContract. 我这样做是为了使用带有DataContract的WCF传输DataTable对象。 You have to create the DataContract as follows:
您必须按如下方式创建DataContract:
[DataContract]
public class WCFDataTableContract
{
[DataMember]
public byte[] Schema { get; set; }
[DataMember]
public byte[] Data { get; set; }
}
Then I created a Binary Converter that will automatically convert any object to a byte array that I can then compress using GZip. 然后我创建了一个二进制转换器,它会自动将任何对象转换为字节数组,然后我可以使用GZip进行压缩。
public static class CompressedBinaryConverter
{
/// <summary>
/// Converts any object into a byte array and then compresses it
/// </summary>
/// <param name="o">The object to convert</param>
/// <returns>A compressed byte array that was the object</returns>
public static byte[] ToByteArray(object o)
{
if (o == null)
return new byte[0];
using (MemoryStream outStream = new MemoryStream())
{
using (GZipStream zipStream = new GZipStream(outStream, CompressionMode.Compress))
{
using (MemoryStream stream = new MemoryStream())
{
new BinaryFormatter().Serialize(stream, o);
stream.Position = 0;
stream.CopyTo(zipStream);
zipStream.Close();
return outStream.ToArray();
}
}
}
}
/// <summary>
/// Converts a byte array back into an object and uncompresses it
/// </summary>
/// <param name="byteArray">Compressed byte array to convert</param>
/// <returns>The object that was in the byte array</returns>
public static object ToObject(byte[] byteArray)
{
if (byteArray.Length == 0)
return null;
using (MemoryStream decomStream = new MemoryStream(byteArray), ms = new MemoryStream())
{
using (GZipStream hgs = new GZipStream(decomStream, CompressionMode.Decompress))
{
hgs.CopyTo(ms);
decomStream.Close();
hgs.Close();
ms.Position = 0;
return new BinaryFormatter().Deserialize(ms);
}
}
}
}
Dump this in your project and call like this in your Service to compress: 将其转储到您的项目中并在您的服务中调用以进行压缩:
dt.Data = CompressedBinaryConverter.ToByteArray(data);
Then call it like this on your client side to convert back to an object: 然后在客户端调用它来转换回对象:
dt = (DataTable)CompressedBinaryConverter.ToObject(wdt.Data);
如果您同时控制客户端和服务器,一种可能的方法是使用protobuf通过WCF服务实现压缩。
Solved!! 解决了!! The code in the question was enough for Service references.
问题中的代码足以用于服务引用。 If you are using Web references, add also the line
如果您使用的是Web引用,请同时添加该行
my_service_object.EnableDecompression = true;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.