Tuesday 19 June 2012

Classic vs. Integrated mode in IIS 7

IIS 6.0 and previous versions allowed the development of .NET application components via the ASP.NET platform. ASP.NET integrated with IIS via an ISAPI extension, and exposed its own application and request processing model. This effectively exposed two separate server pipelines, one for native ISAPI filters and extension components, and another for managed application components. ASP.NET components would execute entirely inside the ASP.NET ISAPI extension bubble and only for requests mapped to ASP.NET in the IIS script map configuration.

IIS 7.0 integrates the ASP.NET runtime with the core web server, providing a unified request processing pipeline that is exposed to both native and managed components known as modules.

The many benefits of integration include:
  • Allowing services provided by both native and managed modules to apply to all requests, regardless of handler. For example, managed Forms Authentication can be used for all content, including ASP pages, CGIs, and static files.
  • Empowering ASP.NET components to provide functionality that was previously unavailable to them due to their placement in the server pipeline. For example, a managed module providing request rewriting functionality can rewrite the request prior to any server processing, including authentication.
  • A single place to implement, configure, monitor and support server features such as single module and handler mapping configuration, single custom errors configuration, single url authorization configuration.
Follow this link to read more on this

Classic mode is where IIS only works with ISAPI extensions and ISAPI filters directly. This is how IIS 6 and below behaved. Using classic mode, ASP.NET is simply an ISAPI extension (aspnet_isapi.dll) and an ISAPI filter (aspnet_filter.dll). When using classic mode the server uses two piplines to handle requests, one for native code and the other for managed code. In this mode the application doesn't take full advantage of everything IIS 7.X has to offer.

Integrated mode handles all requests through a unified pipeline for IIS and is tightly integrated with ASP.NET through that same pipeline. ASP.NET sees every relevant request and manipulates things along the way rather than acting as an external plugin. With integrated mode ASP.NET runs much more efficiently in IIS and will yield greater performance for your site.

Thursday 14 June 2012

ASP.NET MVC - Domain specific routes using RouteConstraint

I’ve come across using different routes depending upon the domain that the end user is browsing. That might be different based on language (browsing your “.co.uk” site gets English URLs, browsing “.fr” gets French), or perhaps based on brand. Maybe some functionality on your web site is only available to certain sub-brands. Or perhaps you want to direct users that visit uat.mydomain.com to new functionality so they can test it. All of this becomes possible with a Route Constraint. These are simply used to validate whether a route should match a particular incoming URL.

HostConstraint

To apply this kind of filtering based on the host in the URL (i.e. the domain the user is browsing) is such a simple piece of code;
public class HostConstraint : IRouteConstraint
{
    private readonly Regex _host;
 
    public HostConstraint(string pattern)
    {
        _host = new Regex(pattern, 
                RegexOptions.Compiled | RegexOptions.IgnoreCase);
    }
 
    public bool Match(
        HttpContextBase httpContext, 
        Route route, 
        string parameterName, 
        RouteValueDictionary values, 
        RouteDirection routeDirection)
    {
        return _host.IsMatch(httpContext.Request.Url.Host);
    }
}
You can see this constraint takes a Regular Expression pattern to describe host names that it should match, and simply checks the Url.Host on the current HttpContext for success.

Using HostConstraint

Using our new class is really simple - we add it to an anonymous type in the MapRoute call;
routes.MapRoute(
    "Default_us",
    "ussitemap",
    new { controller = "Home", action = "SiteMap" },
    new { host = new HostConstraint("\\.com$") }
);
 
routes.MapRoute(
    "Default_fr",
    "frenchsitemap",
    new { controller = "Home", action = "SiteMap" },
    new { host = new HostConstraint("\\.fr$") }
);