Enable the Web Service request compression
I had to enable the request compression for an ASP.NET 2.0 Web Service (no Web Service Enhancements for that client.. ), so here is my solution: I created a CompressionSoapExtension attribute. This attribute was added to the web service methods (for the web service and the web service proxy). Plus, on the client side we added the line:
proxy.EnableDecompression = true;
Here is the code for the attribute:
[AttributeUsage(AttributeTargets.Method)]
public class CompressionSoapExtensionAttribute : SoapExtensionAttribute
{
public override Type ExtensionType
{
get { return typeof (CompressionSoapExtension); }
}
public override int Priority
{
get { return 1; }
set { }
}
}
}
And here is the main class:
public class CompressionSoapExtension : SoapExtension
{
#region "Private Variables"
const int _bufferSize = 4096;
Stream _oldStream;
Stream _newStream;
bool _isOutgoing = false;
#endregion
#region "Public Methods"
///
/// we use our stream for buffering
///
public override Stream ChainStream(Stream stream)
{
if (_isOutgoing)
{
_oldStream = stream;
_newStream = new MemoryStream();
return _newStream;
}
return stream;
}
///
/// GetInitializer1
///
public override object GetInitializer(Type serviceType)
{
return null;
}
///
/// GetInitializer2
///
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
return null;
}
///
/// Initialize
///
public override void Initialize(object initializer)
{
_isOutgoing = true;
}
///
/// process each message
///
public override void ProcessMessage(SoapMessage message)
{
try
{
if (_isOutgoing)
{
switch (message.Stage)
{
case SoapMessageStage.AfterSerialize: //from the client
// compress
_newStream.Seek(0, SeekOrigin.Begin);
Compress(_newStream, _oldStream);
_isOutgoing = false;
break;
case SoapMessageStage.BeforeDeserialize: //arrive to the server
if (IsCompressed (_oldStream))
{
// decompress
Decompress(_oldStream, _newStream);
}
else
{
//simple copy, no unzip
CopyStream (_oldStream, _newStream);
}
_newStream.Seek(0, SeekOrigin.Begin);
_isOutgoing = false;
break;
}
}
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region "Private Methods"
///
///compress stream
///
private void Compress(Stream from, Stream to)
{
GZipStream gzipStream = new GZipStream(to, CompressionMode.Compress);
StreamReader reader = new StreamReader(from);
byte[] b = Encoding.ASCII.GetBytes(reader.ReadToEnd ());
gzipStream.Write(b, 0, b.Length);
gzipStream.Close();
}
///
/// decompress stream
///
private void Decompress(Stream from, Stream to)
{
byte[] buffer = new byte[_bufferSize];
int count;
GZipStream gzipStream = new GZipStream(from, CompressionMode.Decompress);
BinaryWriter writer = new BinaryWriter (to);
while (true)
{
count = gzipStream.Read(buffer, 0, _bufferSize);
if (count == 0)
break;
writer.Write(buffer, 0, count);
}
writer.Flush();
}
///
/// check if it is compressed
///
private bool IsCompressed (Stream from)
{
try
{
byte [] buffer = new byte[2];
from.Position = 0;
int count = from.Read(buffer, 0, 2);
from.Position = 0;
return ((count == 2) && (buffer[0] == 0x1F) && (buffer[1] == 0x8B));
}
catch (Exception ex)
{
throw ex;
}
}
///
/// copy stream
///
private void CopyStream(Stream src, Stream dest)
{
StreamReader reader = new StreamReader(src);
StreamWriter writer = new StreamWriter(dest);
writer.Write (reader.ReadToEnd());
writer.Flush();
}
#endregion
}