How GZIP compression will take place inside asp.net application? - asp.net

I was working on page optimization in my asp.net application using PageSpeed Insights and came across that i need to compress all request to Gzip format to reduce size and load time.
However when i have checked requests in network it's shows me that in Request-header & Response-Header there is already Accept-Encoding:gzip,deflate,sdch and Content-Encoding:gzip respectively. That means encoding is automatically take place for aspx page!
How this was happened? Is it by default?
For js and css there is no encoding and in PageSpeed Insights it shows me that you need to compress all js and css as well in High Priority section. How can i achieve it for my asp.net application?

IIS is able to do gzip compression for you, example below goes into your web.config
<system.webServer>
<!-- enable gzip compression -->
<urlCompression doStaticCompression="true" doDynamicCompression="true" dynamicCompressionBeforeCache="true" />
</system.webServer>

Related

Gzip compression doesn't work in IIS7.5 for classic application pool

I am trying to figure out why one site using classic application pool won't get compressed. This application pool has 32bit enabled. I have the following settings in applicationHost.config.
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" dynamicCompressionLevel="4" staticCompressionLevel="9"/>
<scheme name="deflate" dll="%Windir%\system32\inetsrv\gzip.dll" dynamicCompressionLevel="4" staticCompressionLevel="9"/>
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="application/xaml+xml" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/javascript" enabled="true" />
<add mimeType="*/*" enabled="false" />
</dynamicTypes>
</httpCompression>
And in global.asax file
Sub Application_PreRequestHandlerExecute(ByVal sender As Object, ByVal e As EventArgs)
Dim app As HttpApplication = TryCast(sender, HttpApplication)
Dim acceptEncoding As String = app.Request.Headers("Accept-Encoding")
Dim prevUncompressedStream As Stream = app.Response.Filter
If app.Context.CurrentHandler Is Nothing Then
Return
End If
If Not (TypeOf app.Context.CurrentHandler Is System.Web.UI.Page) OrElse app.Context.CurrentHandler.[GetType]().Name = "SyncSessionlessHandler" OrElse app.Request("HTTP_X_MICROSOFTAJAX") IsNot Nothing Then
Return
End If
If acceptEncoding Is Nothing OrElse acceptEncoding.Length = 0 Then
Return
End If
acceptEncoding = acceptEncoding.ToLower()
If acceptEncoding.Contains("gzip") Then
' gzip
app.Response.Filter = New GZipStream(prevUncompressedStream, CompressionMode.Compress)
app.Response.AppendHeader("Content-Encoding", "gzip")
ElseIf acceptEncoding.Contains("deflate") OrElse acceptEncoding = "*" Then
' deflate
app.Response.Filter = New DeflateStream(prevUncompressedStream, CompressionMode.Compress)
app.Response.AppendHeader("Content-Encoding", "deflate")
End If
End Sub
I doubled checked that I have dynamicCompression feature installed. In the final output Content-Encoding header was removed all the time. What else should I look at? I read that some functions won't work for classic application pool. Is this causing the problem?
IIS 7 improves internal compression functionality dramatically making it much easier than previous versions to take advantage of compression that’s built-in to the Web server. IIS 7 also supports dynamic compression which allows automatic compression of content created in your own applications (ASP.NET or otherwise!). The scheme is based on content-type sniffing and so it works with any kind of Web application framework.
While static compression on IIS 7 is super easy to set up and turned on by default for most text content (text/*, which includes HTML and CSS, as well as for JavaScript, Atom, XAML, XML), setting up dynamic compression is a bit more involved, mostly because the various default compression settings are set in multiple places down the IIS –> ASP.NET hierarchy.
Let’s take a look at each of the two approaches available:
Static Compression
Compresses static content from the hard disk. IIS can cache this content by compressing the file once and storing the compressed file on disk and serving the compressed alias whenever static content is requested and it hasn’t changed. The overhead for this is minimal and should be aggressively enabled.
Dynamic Compression
Works against application generated output from applications like
your ASP.NET apps. Unlike static content, dynamic content must be
compressed every time a page that requests it regenerates its
content. As such dynamic compression has a much bigger impact than
static caching.
How Compression is configured
Compression in IIS 7.x is configured with two .config file elements in the <system.WebServer> space. The elements can be set anywhere in the IIS/ASP.NET configuration pipeline all the way from ApplicationHost.config down to the local web.config file. The following is from the the default setting in ApplicationHost.config (in the %windir%\System32\inetsrv\config folder) on IIS 7.5 with a couple of small adjustments (added json output and enabled dynamic compression):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" staticCompressionLevel="9" />
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/json" enabled="true" />
<add mimeType="*/*" enabled="false" />
</dynamicTypes>
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="application/xaml+xml" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
</httpCompression>
<urlCompression doStaticCompression="true" doDynamicCompression="true" />
</system.webServer>
</configuration>
You can find documentation on the keys here respectively:
httpCompression
urlCompression
The httpCompression Element – What and How to compress
Basically httpCompression configures what types to compress and how to compress them. It specifies the DLL that handles gzip encoding and the types of documents that are to be compressed. Types are set up based on mime-types which looks at returned Content-Type headers in HTTP responses. For example, I added the application/json to mime type to my dynamic compression types above to allow that content to be compressed as well since I have quite a bit of AJAX content that gets sent to the client.
The urlCompression Element – Enables and Disables Compression
The urlCompression element is a quick way to turn compression on and off. By default static compression is enabled server wide, and dynamic compression is disabled server wide. This might be a bit confusing because the httpCompression element also has a doDynamicCompression attribute which is set to true by default, but the urlCompression attribute by the same name actually overrides it.
The urlCompression element only has three attributes: doStaticCompression, doDynamicCompression, and dynamicCompressionBeforeCache. The doCompression attributes are the final determining factor whether compression is enabled, so it’s a good idea to be explcit! The default for doDynamicCompression='false”, but doStaticCompression="true"!
Static Compression is enabled by Default, Dynamic Compression is not
Because static compression is very efficient in IIS 7 it’s enabled by default server wide and there probably is no reason to ever change that setting. Dynamic compression however, since it’s more resource intensive, is turned off by default. If you want to enable dynamic compression there are a few quirks you have to deal with, namely that enabling it in ApplicationHost.config doesn’t work. Setting:
<urlCompression doDynamicCompression="true" />
in applicationhost.config appears to have no effect and I had to move this element into my local web.config to make dynamic compression work. This is actually a smart choice because you’re not likely to want dynamic compression in every application on a server. Rather dynamic compression should be applied selectively where it makes sense. However, nowhere is it documented that the setting in applicationhost.config doesn’t work (or more likely is overridden somewhere and disabled lower in the configuration hierarchy).
So: Remember to set doDynamicCompression=”true” in web.config!!!
How Static Compression works
Static compression works against static content loaded from files on disk. Because this content is static and not bound to change frequently – such as .js, .css and static HTML content – it’s fairly easy for IIS to compress and then cache the compressed content. The way this works is that IIS compresses the files into a special folder on the server’s hard disk and then reads the content from this location if already compressed content is requested and the underlying file resource has not changed. The semantics of serving an already compressed file are very efficient – IIS still checks for file changes, but otherwise just serves the already compressed file from the compression folder.
The compression folder is located at:
%windir%\inetpub\temp\IIS Temporary Compressed Files\ApplicationPool\
If you look into the subfolders you’ll find compressed files:
CompressedFileFolder
These files are pre-compressed and IIS serves them directly to the client until the underlying files are changed.
As I mentioned before – static compression is on by default and there’s very little reason to turn that functionality off as it is efficient and just works out of the box. The one tweak you might want to do is to set the compression level to maximum. Since IIS only compresses content very infrequently it would make sense to apply maximum compression. You can do this with the staticCompressionLevel setting on the scheme element:
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" staticCompressionLevel="9" />
Other than that the default settings are probably just fine.
Dynamic Compression – not so fast!
By default dynamic compression is disabled and that’s actually quite sensible – you should use dynamic compression very carefully and think about what content you want to compress. In most applications it wouldn’t make sense to compress all generated content as it would generate a significant amount of overhead. Scott Fortsyth has a great post that details some of the performance numbers and how much impact dynamic compression has. Depending on how busy your server is you can play around with compression and see what impact it has on your server’s performance.
There are also a few settings you can tweak to minimize the overhead of dynamic compression. Specifically the httpCompression key has a couple of CPU related keys that can help minimize the impact of Dynamic Compression on a busy server:
dynamicCompressionDisableCpuUsage
dynamicCompressionEnableCpuUsage
By default these are set to 90 and 50 which means that when the CPU hits 90% compression will be disabled until CPU utilization drops back down to 50%. Again this is actually quite sensible as it utilizes CPU power from compression when available and falling off when the threshold has been hit. It’s a good way some of that extra CPU power on your big servers to use when utilization is low. Again these settings are something you likely have to play with. I would probably set the upper limit a little lower than 90% maybe around 70% to make this a feature that kicks in only if there’s lots of power to spare. I’m not really sure how accurate these CPU readings that IIS uses are as Cpu usage on Web Servers can spike drastically even during low loads. Don’t trust settings – do some load testing or monitor your server in a live environment to see what values make sense for your environment.
Finally for dynamic compression I tend to add one Mime type for JSON data, since a lot of my applications send large chunks of JSON data over the wire. You can do that with the application/json content type:
<add mimeType="application/json" enabled="true" />
What about Deflate Compression?
The default compression is GZip. The documentation hints that you can use a different compression scheme and mentions Deflate compression. And sure enough you can change the compression settings to:
<scheme name="deflate" dll="%Windir%\system32\inetsrv\gzip.dll" staticCompressionLevel="9" />
to get deflate style compression. The deflate algorithm produces slightly more compact output so I tend to prefer it over GZip but more HTTP clients (other than browsers) support GZip than Deflate so be careful with this option if you build Web APIs.
I also had some issues with the above value actually being applied right away. Changing the scheme in applicationhost.config didn’t show up on the site right away. It required me to do a full IISReset to get that change to show up before I saw the change over to deflate compressed content. Content was slightly more compressed with deflate – not sure if it’s worth the slightly less common compression type, but the option at least is available.
IIS 7 finally makes GZip Easy
In summary IIS 7 makes GZip easy finally, even if the configuration settings are a bit obtuse and the documentation is seriously lacking. But once you know the basic settings I’ve described here and the fact that you can override all of this in your local web.config it’s pretty straight forward to configure GZip support and tweak it exactly to your needs.
Static compression is a total no brainer as it adds very little overhead compared to direct static file serving and provides solid compression. Dynamic Compression is a little more tricky as it does add some overhead to servers, so it probably will require some tweaking to get the right balance of CPU load vs. compression ratios. Looking at large sites like Amazon, Yahoo, NewEgg etc. – they all use
Reference :
http://weblog.west-wind.com/posts/2011/May/05/Builtin-GZipDeflate-Compression-on-IIS-7x

Set cache expiration date in asp.net

I am currently working to make my page optimized.I came across the cache expiry.I studied about it and how it works.I got the following code to be added in web.config file.
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="14.00:00:00" />
</staticContent>
</system.webServer>
But when i test my web page with yslow ,it still says set expiry header for css,js,image files.Infact addding this code brings no change in the yslow grade.I tried other example as well such as
`<%# OutputCache Duration="60" VaryByParam="None" VaryByCustom="browser" %>`
And it does affect the rating,rating increase by one.But still the css,image,js files are not getting the expiry date.
Do i need to change anything else then the webconfig file to add expiry header to css,js files.?
DO i need to make change in iis?
I am testing my offline localhost site by the way?
Please help!
The reason why that happens is, ASP.Net does not serve the CSS, JS, images, etc files. Those are static files and ASP.Net processing pipeline just ignores them leaving those for the IIS server to serve. If you want to achieve caching on those files, you should set Caching properties in your Web server. That would be in addition to the settings you have already done in the web.config.
Depending upon which version of IIS Server you are using, the Caching headers can be set differently.

IIS and Static content?

According to Ultra-Fast ASP.NET: Chapter 3 - Caching:
Files that the browser retrieves from the server should be stored in
the browser’s cache as long as possible to help minimize server
round-trips.
But how does IIS know what a static content actually is and is not?
Is it just images, CSS, JS and not ASPX, ashx...?
Where can I see in IIS what is already considered to be static and what is not ?
What about the scenario where a page has been declared with <%# OutputCache header (without location)? Are the images, CSS and JS source files inside of it also being output cached with the same properties?
As a best practice, I should set one year into the future as the maximum expiration time. I should use that as the default for all static content on the site
So I did this :
But later, after pressing OK, I can't find any summary menu which shows me: to whom I already put a response header (in this case: the css folder).
Currently, in order to see that css folder has been applied with response headers - I have to go to the css folder again --> Http Response Header-->Set Common Headers --> and then I see it. It isn't written in the web.config.
But if I do it for a file (Login.aspx for example): I do see it in web.config:
<configuration>
<location path="Login.aspx">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseExpires" cacheControlMaxAge="1.00:00:00" httpExpires="Fri, 15 Feb 2013 00:00:00 GMT" />
</staticContent>
</system.webServer>
</location>
</configuration>
I understand your situation. Sometime its confusing how IIS handles a file. Its also different for IIS 6 vs IIS 7 and different for Classic App Pools and Integrated mode app pools. My experience is mostly with Integrated App Pools on IIS 7.5, so thats the environment I can comment on most accurately.
First Question
But how does IIS knows what is actually a static content and what is
not?
Is it just images , css , js and not ASPX , ashx...?
Where can I see in the IIS what is already considered to be static and
what not ?
You can inspect the list of file handlers in IIS by navigating to your website and then click 'Handler Mappings'. By default these are inherited from the .Net base web.config which is in a different location depending on your .Net framework version.
C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config
If a file being requested isn't already explicitly mapped to another handler it falls to a catch all handler (*) as the last option (System.Web.DefaultHttpHandler) which determines if it is a static file or a directory browsing request. So Static files are simply files not bound to another handler already. For example you'll see that *.aspx is already mapped to System.Web.UI.PageHandlerFactory prior to this default handler. So its going to be processed by that handler and not be considered a static file. If you removed that mapping you could technically serve *.aspx as a static file if you really wanted to (just for proof of how it works).
But you can also explicitly list a file type as a static file by adding an entry in your web.config's httpHandlers section mapping the file extensions to System.Web.StaticFileHandler in IIS. For example:
<configuration>
<system.webServer>
<handlers>
<add name="StaticHandler" verb="*" path="*.zip" type="System.Web.StaticFileHandler" preCondition="integratedMode" />
</handlers>
</system.webServer>
</configuration>
This example is using the <system.webServer> config section, so its for an App Pool running in Integrated Mode.
Second Question
What about the scenario where a page has been declared with <%#
OutputCache header(without location) . does the images,css,js src
files inside of it , are also being output cached with the same
properties?
No. Because the page is being server as a separate request (maybe even by a separate handler) it can have totally different cache headers/hints. The host page and the resources it may use are not related from a caching perspective.
In fact you may even want to have a shorter cache period for *.html and a longer cache period for *.jpg or *.png? Something to consider.
Third Question
As a best prcatice , I should set one year into the future as the
maximum expiration time.I should use that as the default for all
static content on the site
Hmm... I might not go as far as one year. How about one month? I would set a global policy like this:
<configuration>
<system.webServer>
<staticContent>
<!-- Set expire headers to 30 days for static content-->
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="30.00:00:00" />
</staticContent>
</system.webServer>
</configuration>
This is the same as the sample you showed above, but is not inside a <location> element, instead it is right in the root <configuration> element so it is the default policy. Again this is for an App Pool running in Integrated Mode. Sometimes you also need to turn on:
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<!-- stuff -->
</modules>
</system.webServer>
<system.webServer>
This just makes sure that static files are processed through the managed static file handler which respects the above configuration elements.
Edit to Address Comments
The documentation for the configuration dialog you posted above is located here: Configure the HTTP Expires Response Header (IIS 7)
Apparently these settings are saved in C:\Windows\System32\inetsrv\config\applicationHost.config
I do not have IIS7 and personally develop on IIS 7.5 now. So please post a comment if you can verify this location is accurate!
The static content is the one that IIS is read and send to the browser with out any processing. There you can setup IIS to include some Cache-Control Header to cache it on clients browser computers.
You can do that ether by direct setup IIS, ether by commands on web.config as you say. The commands that you add on web.config and concern the IIS, did not have to do with asp.net it self, but the IIS, and IIS saves his configuration on a different file, so when you change that cache control headers direct on IIS you do not see them on web.config.
Now for the static content like images, CSS, JavaScript, and other similar files they say that you can follow the "never expire" policy by adding 10 years expire.
The issue here is that if you can not change the content of the static file, if for example you cache a javascript file with 10 years, and you make a small change on it, then you need ether to change the file name, ether to add some parameter at the end of it.
Now the <%# OutputCache on a control is referred to the server cache and not to the client, and what is actually do is to cache the render of the control on the server so the next time you ask it to not lose time to renders it again but read it from cache - is still send it to the browser.
And you can also read this answer for some more: What are difference between IIS (Dynamic and Static) cache,OutPutCache and browser cache

GZip compression on IIS 7 is NOT working (COMPRESSION_DISABLED) - how can I fix this?

Can't get the gzip to work with my IIS7 webserver.
I have Windows 2008 64bit running IIS 7(.NET Web app). I've enabled Gzip via the IIS module and I have the following line in my webconfig:
urlCompression doStaticCompression="true" doDynamicCompression="true" />
Every time I check the FailedReqLogfiles this is what i get:
DYNAMIC_COMPRESSION_START
-DYNAMIC_COMPRESSION_NOT_SUCCESS
Reason 2
Reason COMPRESSION_DISABLED
Any ideas?
Thanks in advance
Mate, it took me ages to get this working a while back.
So far, you've done the right thing asking IIS7 to use GZIP compression by adding in the correct element to the
<system.webServer>
<urlCompression doDynamicCompression="true" dynamicCompressionBeforeCache="true" />
....
</system.webServer>
NOTE: system.webServer is for IIS7 + settings.
Now .. the kicker is this: by default, IIS7 DISALLOWS gzip compression (for all web sites on that server) regardless if a user has asked to turn it on via the web.config. Why? Imagine a massive Web Hoster (eg. Discount ASP.NET, etc..) that allows people to turn on GZIP compression .. and hundreds of sites do that .. and the server CPU starts to (possibly) sky rocket.
So unless the server admin changes the setting for urlCompression on the server level (aka. in the application.config file) .. then IIS7 will ignore this setting.
So - lets fix this (assuming u have access to the application.config file).
First, start IIS and click on the main server name, then click on Config Editor. This allows us to change settings for the ENTIRE server (app.config stuff).
Now, select the element system.webServer and then choose urlCompression.
Now -> notice how you can now UNLOCK a section or an attribute? I just unlock this entire section. In my picture below, it says LOCK .. because I've already unlocked it. So unlock that section and then give it a go. If it still doesn't work, try restarting the WWW service.
and tell me if that starts to work for you :)
OOOK! The following tag was missing from applicationHost.config...aargh!
<httpCompression directory="D:\gzip" minFileSizeForComp="256">
After adding this accordingly it worked.
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
I enabled Gzip compression by just using
<urlCompression doDynamicCompression="true" doStaticCompression="true" /> in between <system.webServer> in web.config file. By the way your suggestion is also helpful and useful.

JSON webservice response compression in IIS 7

I have trouble with JSON response compression. I look to response headers after uploading website to production server (Windows 2008, IIS 7) and found uncompressed response. Turning on "Enabled static compression" and ""Enable dynamic compression" in IIS control panel does not effect. ASPX pages was responsed gzipped, but webservice response uncompressed.
I looked to google, but no answer found about this trouble. Also, I try this json ihttpmodule compression way (and adding to web.config this module) - but this source is excellent working at development machine with ASP.NET development server (and have seven times response size reduced) and totally ignored at IIS7.
How I can apply gzip compression to json responses from my webservice? Thanks.
PS .NET 3.5
I stumbled across the same problem with JsonCompressionModule. It was working on the development server but not on IIS 7. I figured out that under IIS 7 it isn't enough to add the handle under system.web but also under system.webServer (see below). After this change it works fine on IIS 7.
<system.web>
<httpModules>
<add name="JsonCompressionModule" type="JsonCompressionModule"/>
</httpModules>
</system.web>
<system.webServer>
<modules>
<add name="JsonCompressionModule" preCondition="managedHandler" type="JsonCompressionModule"/>
</modules>
</system.webServer>
IIS dynamic compression uses the response content type header to determine if it should compress the content or not. The default settings do not compress "application/json". You can find more information at http://www.iis.net/configreference/system.webserver/httpcompression
To add it, open an admin command prompt, run the commands below then restart the IIS service.
cd \Windows\System32\inetsrv
appcmd.exe set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json',enabled='True']" /commit:apphost
You may want to add a few other content types. The only application/* types the default dynamic settings compress is application/x-javascript.
Please try and examine what are the request headers which the client sends. Accept-Encoding should have gzip or deflate value.
Make sure though that the client is able to decompress JSON.
There is a solution which is able to set Accept-Encoding and perform GZIP compression all together—Helicon Ape (http://www.helicontech.com/ape/). The following configuration will do both the tricks:
# Manually set required request header
RequestHeader append Accept-Encoding gzip early
# Enable high-level (9) comression for JSON files
SetEnvIf mime application/json gzip=9

Resources