Thursday, March 12, 2015

.Net Web API Compression

Intro

Web API projects are great. But hopefully I've already convinced you of that in past blogs :)  What could make them better? Optimization of course! As you can guess by the title, I'm specifically going to talk about compression. Compression has a dual-purpose: it can optimize bandwidth, and as a result on many devices it optimizes speed as well from the user's point of view. Out of the box, your Web API's don't accept compressed requests and won't send back compressed responses. Lazy API! But we've got an easy way to make this happen, so read on fellow optimizers!


Example

First, let's create a Web API project in C#. We'll go without web optimization for now just so you can see the difference. Fire up Visual Studio and create a new project. Make it a c# web project.



Make it a empty project and give it Web API and Web Forms capabilities:

 Now give your site a new web API controller. Name it TestController. 






Your Web API doesn't need much in it, just set your code to this:

using System.Net.Http;
using System.Web.Http;

namespace BlogWebApiCompress.Controllers
{
    public class TestController : ApiController
    {
        public HttpResponseMessage Get(string id)
        {
            var result = new List();
            for (int i = 0; i < 10; i++)
                result.Add(id);
            return Request.CreateResponse(result);
        }
    }
}


If you run your web api by hitting your base url plus "/api/test/hi", the web api will return back the list of strings string containing "hi" (10 times) to you. Not much to that. Now let's pretend you sent up a 100 page pamphlet worth of text. You'd have not only a large request, you'd have a very large response as well. Compression can lessen the burden on your systems.

How do we get compression? It turns out there's already a NuGet package for that. NuGet kind of reminds me when iPhones were still pretty new and people kept saying "there's an app for that". Well with Visual Studio and NuGet, "there's a package for that". The one we want is named Microsoft.AspNet.WebApi.MessageHandlers.Compression. Good luck memorizing that. I'll assume you have some familiarity with NuGet by now, but if not drop me a line in the comments below. Fire up the package manager and install the above package.

Now open up the file App_Start/WebApiConfig.cs. At the end of your Register() method, copy in this line of code:

GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new ServerCompressionHandler(new GZipCompressor(), new DeflateCompressor()));

You may also have to add "using"s for these:

using Microsoft.AspNet.WebApi.MessageHandlers.Compression;
using Microsoft.AspNet.WebApi.MessageHandlers.Compression.Compressors;


Believe it or not, that's all you have to do on the server! Let's do another test of our Web Api using FireFox to see the compression in action. This time I'll put a much longer string into the request:



Notice how FireFox sent up the request header "Accept-Encoding: gzip, deflate" and the server sent back down gzip-encoded content? Sweet! That's all there is to it.



What's Next?

  • Go to the website of the NuGet package and see how to:
    • Only compress requests and responses that are above a certain size threshold, and
    • Write client-side code that tells the server you can accept a compressed response (hint, most browsers do this for you already if you are using JavaScript, but for C# clients you have a small amount of extra coding to do).


Resources

 Microsoft.AspNet.WebApi.MessageHandlers.Compression

2 comments:

  1. When I am trying to Only compress requests and responses that are above a certain size threshold, and with the following line of code:
    config.MessageHandlers.Insert(0, new ServerCompressionHandler(4096, new GZipCompressor(), new DeflateCompressor()));

    it is not working for me.Can you please help me to know is there anything I am missing out ?

    ReplyDelete
  2. Hi Santosh, when you say it isn't working for you, what exactly to you mean? For instance, is it always compressing the response no matter the size of the response, is it not compressing the response at all anymore, or other?

    ReplyDelete