how to gzip content in asp.net MVC?
Asked Answered
C

3

42

how to compress the output send by an asp.net mvc application??

Capricorn answered 27/9, 2010 at 8:22 Comment(2)
Why not just set <urlCompression doDynamicCompression="true" /> or even <urlCompression doStaticCompression="true" doDynamicCompression="true" /> in web.comfig iis.net/configreference/system.webserver/httpcompression #9235837?Falls
You can also increase the performance by using compression and caching for the response data. Have a look at the following link :- weblogs.asp.net/rashid/…Epigrammatist
I
94

Here's what i use (as of this monent in time):

using  System.IO.Compression;

public class CompressAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {

        var encodingsAccepted = filterContext.HttpContext.Request.Headers["Accept-Encoding"];
        if (string.IsNullOrEmpty(encodingsAccepted)) return;

        encodingsAccepted = encodingsAccepted.ToLowerInvariant();
        var response = filterContext.HttpContext.Response;

        if (encodingsAccepted.Contains("deflate"))
        {
            response.AppendHeader("Content-encoding", "deflate");
            response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
        }
        else if (encodingsAccepted.Contains("gzip"))
        {
            response.AppendHeader("Content-encoding", "gzip");
            response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
        }
    }
}

usage in controller:

[Compress]
public class BookingController : BaseController
{...}

there are other varients, but this works quite well. (btw, i use the [Compress] attribute on my BaseController to save duplication across the project, whereas the above is doing it on a controller by controller basis.

[Edit] as mentioned in the para above. to simplify usage, you can also include [Compress] oneshot in the BaseController itself, thereby, every inherited child controller accesses the functionality by default:

[Compress]
public class BaseController : Controller
{...}
Inodorous answered 27/9, 2010 at 9:17 Comment(16)
actually, looked at your example - very similar indeed - spooky :). i've been using this code for over a year, so can verify that it works very well ...Inodorous
is is possible i can do some settings in web.config to do the compression. one more thing i want to know, how to check howmuch overhead is added to server by compression code we are running here.Capricorn
praveen- unfortunately, a web.config solution isn't one that i'm aware of (i also think it would be too course grained to be flexible). as for memory usage, i think you may have to use some tool outside of IIS to measure that.Inodorous
Could you include how you add it to your Base Controller?Berck
Hi mark - it's actually as simple as just moving the [Compress] attribute down from the child controller to decorate the BaseController instead. I've added an amendment to show thisInodorous
@jimtollan And then have every controller derive from your BaseController? Does this work for CSS and Javascript files? or just dynamic content?Berck
Hi mark, yes, every controller that derives from BaseController will inherit this logic. this works for any content that can be gzipped, tho of course, some css and images etc may by default be pulled from local cache anyway.Inodorous
Why not just use IIS urlCompression ? #9235837Falls
hey there, good point, tho the above, as mentioned in my answer (and actually also mentioned in the comments above re web.config being too course grained!!), gives an alternative for those who prefer to be able to roll in compression at a fine grained, individual controller level on a needs must basis (rather than across the board, which may not be desirable for the use case). :). happy new year when the hour approaches, wherever you are. hoots mon the noo...Inodorous
I added it as a global filter, in my startup class I added GlobalFilter.Filters.Add(new CompressionAttribute()); and it works #1! Also inverted the if clause to make sure gzip is used instead of deflate when both encodings are supported.Bellied
Just wanted to add, that in case you didn't start by deriving from a base controller, don't be scared. You can always use an IoC container that will handle that. For example, in Ninject (MVC 5) you can use: "kernel.BindFilter<CompressAttribute>(FilterScope.Controller, 0);" under the "RegisterServices(IKernel kernel)" method!Harlene
Jose, so glad that this little Attribute approach is still working, 5 years later and 4 versions of MVC... I just love this tech for that reason, build and consolidate!!Inodorous
Great answer. But why you put deflate option first, I change order so gzip is first and now give around 10% more compresionBrinn
The one issue IU had with this solution is that it doesn't honour the order of the accept-encoding header. If you receive gzip, deflate the priority is GZIP?Arthrospore
Thanks for a nice solution! I just ran into the problem that response.Filter is null - see this question for the solution to that: #15067549Phonogram
Important! You should check response.Filter for null before putting it in stream! I encountered issue, when locally everything is OK, but when deployed to Azure service it fails.Goodhen
L
4

Have a look at this article which outlines a nifty method utilizing Action Filters.

For example:

[CompressFilter]
public void Category(string name, int? page)

And as an added bonus, it also includes a CacheFilter.

Launch answered 27/9, 2010 at 9:8 Comment(3)
okie, testing this, one more thing i want to know , how can i check whether the data iam getting from server is gzipped or not??Capricorn
Use Firebug as in the article and look at response headerLaunch
Not working on MVC5, IIS 8.5 and .Net 4.5, any help will be appreciated.Larentia
A
3

For .NET Core 2.1 there is a new package that can be used ( Microsoft.AspNetCore.ResponseCompression )

Simple sample to get going, after installing the package:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCompression();

        services.AddResponseCompression(options =>
        {
            options.Providers.Add<GzipCompressionProvider>();
            options.EnableForHttps = true;
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseResponseCompression();
    }
}

You can read more about it here: https://learn.microsoft.com/en-us/aspnet/core/performance/response-compression?view=aspnetcore-2.1&tabs=aspnetcore2x

Auguste answered 26/7, 2018 at 8:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.