I am currently working on migrating few of my MVC3 Controllers to MVC4 Api Controllers.
I have implemented Compression mechanism for MVC3 controller Get Method Responses by inherting ActionFilterAttribute
and overriding OnActionExecutiong
method. After some Research I found that I need to use ActionFilterMethod
from System.Web.HttpFilters
. It would be great if somebody can share piece of sample code to get me started for this compressing HTTP response using GZip
There are many ways in which you can compress content that is sent over the wire from your Web API. One way to compress content is by using IIS compression. Using IIS compression, you can perform compression of both static and dynamic content.
HTTP data is compressed before it is sent from the server: compliant browsers will announce what methods are supported to the server before downloading the correct format; browsers that do not support compliant compression method will download uncompressed data.
Yes. For most cases, you should use data compression for your API result.
This results in a unique Gzip data format, also named Gzip, which wraps DEFLATE compressed data with a checksum and header. Due to early problems with DEFLATE, some users prefer to only use Gzip. Typically, HTTP headers are not compressed, as HTTP content-encoding based compression applies to the response body only.
The easiest is to enable compression directly at IIS level.
If you want to do it at the application level you could write a custom delegating message handler as shown in the following post:
public class CompressHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>((responseToCompleteTask) =>
{
HttpResponseMessage response = responseToCompleteTask.Result;
if (response.RequestMessage.Headers.AcceptEncoding != null)
{
string encodingType = response.RequestMessage.Headers.AcceptEncoding.First().Value;
response.Content = new CompressedContent(response.Content, encodingType);
}
return response;
},
TaskContinuationOptions.OnlyOnRanToCompletion);
}
}
public class CompressedContent : HttpContent
{
private HttpContent originalContent;
private string encodingType;
public CompressedContent(HttpContent content, string encodingType)
{
if (content == null)
{
throw new ArgumentNullException("content");
}
if (encodingType == null)
{
throw new ArgumentNullException("encodingType");
}
originalContent = content;
this.encodingType = encodingType.ToLowerInvariant();
if (this.encodingType != "gzip" && this.encodingType != "deflate")
{
throw new InvalidOperationException(string.Format("Encoding '{0}' is not supported. Only supports gzip or deflate encoding.", this.encodingType));
}
// copy the headers from the original content
foreach (KeyValuePair<string, IEnumerable<string>> header in originalContent.Headers)
{
this.Headers.AddWithoutValidation(header.Key, header.Value);
}
this.Headers.ContentEncoding.Add(encodingType);
}
protected override bool TryComputeLength(out long length)
{
length = -1;
return false;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
Stream compressedStream = null;
if (encodingType == "gzip")
{
compressedStream = new GZipStream(stream, CompressionMode.Compress, leaveOpen: true);
}
else if (encodingType == "deflate")
{
compressedStream = new DeflateStream(stream, CompressionMode.Compress, leaveOpen: true);
}
return originalContent.CopyToAsync(compressedStream).ContinueWith(tsk =>
{
if (compressedStream != null)
{
compressedStream.Dispose();
}
});
}
}
All that's left now is to register the handler in Application_Start
:
GlobalConfiguration.Configuration.MessageHandlers.Add(new CompressHandler());
If you are using IIS 7+, I would say leave the compression to IIS as it supports GZIP compression. Just turn it on.
On the other hand, compression is too close to the metal for the controller. Ideally controller should work in much higher level than bytes and streams.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With