:::: MENU ::::

Tuesday, February 19, 2013

I was trying to add SSL to one of my local sites, but the site was always stopped, the issue was that skype was taking over the ports, see below hoe to fix it.

When trying to start an IIS7 website, you can get the following message: “The process cannot access the file because it is being used by another process. (Exception from HRESULT: 0×80070020)”:


 It’s saying it can’t access the file, but actually IIS can’t bind the ports you’ve configured in Bindings configuration. But which port?
Usually I use the following procedure to find out which application occupies the port:
  1. run netstat –ano –p tcp to get the list of opened ports, find the port that’s been taken and see which PID the port is bound to
  2. run tasklist /FI "PID eq XXX" where XXX is the found PID
So in my case the 80 and 443 ports were taken by Skype. Whenever you start Skype, it tries to bind 80 and 443 ports, and so if you start your web server later, it won’t be able to work as ports are occupied. This Skype behaviour can be turned off by deselecting “Use port 80 and 443 as alternatives for incoming connections” here:
 

Thursday, February 7, 2013

The bundling and minification that arrived with the latest .Net 4.5 framework is a great tool. For those web applications that are using the WebForms App_Themes folder to style an application, it won't quite work as well as it is capable of. The App_Themes folder will automatically render down all CSS files it finds in the folder and sub directories, so if you register these files in your bundle config you will end up with two versions of the stylesheet rendered down to the client.

So how do we dynamically register some CSS files in an App_Theme folder without the default files being rendered down to the client? The short answer is, you can't. The long answer is, we can with a bit of a work around.

If we take out the CSS files (including any images etc referenced by the style sheets) and move them to another folder, say AppTheme, put our files into a directory under the AppTheme folder with the same theme name, let's go with Default. We can now go and register these files in our bundle config. The default method for registering style sheets isn't quite going to cut it as that defines all the file locations at application load time and we're going to want to dynamically change this folder depending on the theme selected for the current request.

Luckily, we already have this capability in the default web optimisation library. We just need to use the DynamicFolderBundle class as follows:
 
bundles.Add(new DynamicFolderBundle("Style", "*.css"));
 
And then on the page where you register the bundle, you can just register it with the following:
 
<%: System.Web.Optimization.Styles.Render("~/AppThemes/" + this.Theme + "/Style") %>
 
Which tells the bundler to look under the AppThemes/{ThemeName} folder and register all the css files under the one bundle. It's also possible for the DynamicFolderBundle to search all the sub-directories for CSS files, but you'll want to be careful with that if you have styles that reference external files such as background images.
 
Cool C# Snippets - Dynamically GZIP compress the HTML response of your website in code, without having to configure IIS directly. Make massive savings on your websites bandwidth.

Dynamic GZIP Compression in Code

I recently found a way to GZIP compress the HTML, CSS and Javascript output from an ASP.NET website, dynamically in code. GZIP compression can drastically reduce the file sizes for any text based file served to the client. This includes the raw HTML, CSS, Javascript files, even plain XML or CSV, but it can't compress images, media and binary files. Normally, you'd set this on the server, but what if you dont have access to the server.
First create a Global.asax file in your web root and put the following line in it, deleting everything thats there currently...
<%@ Application Language="C#" Inherits="Global" %>
Then create a Global.cs file in your APP_CODE folder and put the following code in...
using System;
using System.IO.Compression;

public class Global : System.Web.HttpApplication
{
    public Global()
    {
        InitializeComponent();
    }

    private void InitializeComponent()
    {
        this.PostReleaseRequestState +=
            new EventHandler(Global_PostReleaseRequestState);
    }

    private void Global_PostReleaseRequestState(
        object sender, EventArgs e)
    {
        string contentType = Response.ContentType;

        if (contentType == "text/html" ||
            contentType == "text/css")
        {
            Response.Cache.VaryByHeaders["Accept-Encoding"] = true;

            string acceptEncoding =
                Request.Headers["Accept-Encoding"];

            if(acceptEncoding != null)
            {
                if (acceptEncoding.Contains("gzip"))
                {
                    Response.Filter = new GZipStream(
                        Response.Filter, CompressionMode.Compress);
                    Response.AppendHeader(
                        "Content-Encoding", "gzip");
                }
                else if (acceptEncoding.Contains("deflate"))
                {
                    Response.Filter = new DeflateStream(
                        Response.Filter, CompressionMode.Compress);
                    Response.AppendHeader(
                        "Content-Encoding", "deflate");
                }
            }
        }
    }
}
The browser will tell the server whether it supports GZIP or DEFLATE compression (via the Accept-Encoding header). If its an older browser that doesn't support compression, it will just be sent as uncompressed HTML and your site will still work.
The magic happens with the following lines...
Response.Filter = new GZipStream(
    Response.Filter, CompressionMode.Compress);
Response.AppendHeader("Content-Encoding", "gzip");
Response.Filter (also available from your ASPX pages) exposes a Stream which you override with a GZipStream object, this will cause the raw text response to get compressed, while telling the browser this the response is compressed with the second line Response.AppendHeader.
The reason we put this in the Global_PostReleaseRequestState event is because it allows us to target all files, not just ASPX pages.
Pay attention to the line if (contentType == "text/html" || contentType == "text/css"), I had an issue where I was using the ASP.NET AJAX extensions Control Toolkit which was supplying it's own external javascript files that were already GZIP compressed, and since it was trying to compress an already compressed file, it was screwing it up causing issues and throwing script errors on the client, because the browser couldn't read the script files. So be aware of this, if you have complete control over your external JavaScript files then could probably add the code...
|| contentType == "application/x-javascript" || contentType == "text/javascript"
...to that IF statement.
FYI, I tried adding this code to an application I was working on at Conscia. The client wouldn't let us turn GZIP compression on their own servers, and we didn't have any access to them. Page sizes were around 150-200KB but after adding this code they now sit at around 20-30KB, a massive improvement which would benefit the particular slow network this application was being made to run on.
Page loads times were quicker and the application seemed noticably more responsive. So your benefits are lowered costs and an improved user experience.