Released RequestReduce.SassLessCoffee: Now have RequestReduce compile your .less, .sass, .scss and .coffee files before minifying and bundling them by Matt Wrock

I’ve been wanting to get this post out for a few days since I launched this last Friday. I have to make this quick before I hop in the shower to go to work. I owe at least that to my coworkers.

Less, Sass and Coffee script compiling

I’ve had a few RequestReduce users asking me about adding Less, Sass and Coffee script compiling to RequestReduce. Technically, this has been doable for some time along side DotLess and SassLessCoffee.AspNet. However, I wanted to optimize the integration since by default, using the handlers provided by those two excellent projects bring in their own caching and, in the case of SassAndCoffee, its own bundling and an issue with setting “near” future caching headers (which is now fixed in the latest source code). This extra caching and bundling just adds unnecessary processing time and possibly disk space consumption.

RequestReduce.SassLessCoffee, available at http://RequestReduce.com and via Nuget now calls into the APIs exposed by both DotLess and SassAndCoffee.Core to have them simply compile the contents of your .less, .sass, .scss and .coffee files. RequestReduce then takes over with its own minification, bundling and caching logic.

To get this simply requires adding the RequestReduce.SassLessCoffee Dll and those of its dependencies to your project. No handler config entries are necessary in your web.config. This is because RequestReduce will map these extensions to its own handlers at run time.

Hopefully this is what the Less/Sass/Coffee users have been looking for in RequestReduce. Please let me know if you run into issues here.

New Look on the RequestReduce Homepage

I gave RequestReduce.com a facelift last weekend. A couple weeks ago Zach Holman gave me some good advice on my github readme. He commented that my headline and the first paragraph was too wordy. I had felt the same way for a while but this weekend finally did something about it. I shortened up my github headline and readme and took it a step further and totally revamped the homepage. It looked more like an essay than a pitch for RequestReduce. When I’m looking for OSS solutions, I typically don’t like essays as my introduction to the project. So now the first thing you see are basically bullet points highlighting what's important and some before and after images from www.webpagetest.org waterfall tests.

I’d really be interested in hearing your feedback on the new look. I already shrunk the huge Getting Started font based on some early comments. Does this quickly “bring the message home?” I did get a comment about the waterfall images appearing out of context and that the reader may not know what they are or why they are important. Their importance seem clear to me but then I do perf testing every day unlike a lot of other devs and web folk.

Unit Testing ASP.Net Http Handlers and a discussion of Auto Mocking and the Testable pattern by Matt Wrock

This post was originally entitled Unit Testing ASP.Net Http Handlers and my intent was a quickie (5 minute) post on overriding ProcessRequest in a test friendly manner. Then, struck by diarrhea of the fingers, I found myself going off on unit testing practices and discussing a pattern I don’t hear a lot about but that provides a lot of value to me and the teams I work with. I hope you will find it of value too.

A test friendly IHttpHandler

The default Http Handler template that Visual Studio provides is not very Unit Test friendly. The key problem is here:

public void ProcessRequest(HttpContext context){

}

 

HttpContext is not your friend and it will eat your children if left unattended. Thankfully there is HttpContextBase who loves you and has a wonderful plan for your life. If you are not familiar with HttpContextBase, it provides everything that HttpContext has to offer wrapped up in mockable abstract classes.

Its really quite simple to transform the default visual studio HttpHandler template to a unit test friendly template. Use this instead:

using System.Web;

namespace RequestReduce.SassLessCoffee{    public class IISHandler1 : IHttpHandler    {        public bool IsReusable        {            get { return true; }        }

        public void ProcessRequest(HttpContext context)        {            ProcessRequest(new HttpContextWrapper(context));        }

        public void ProcessRequest(HttpContextBase context)        {            //write your handler implementation here.        }

    }}

Now your unit tests can call ProcessRequest and pass in a mocked context which in turn will call the IHttpHandler contractual ProcessRequest.

As an example of a full fledged real world set of unit tests, I’ll use a handler that I am creating and will very soon release in my RequestReduce project which compiles .less dynamic css to plain old css.

Here is the Handler:

using System.Web;using RequestReduce.Utilities;using dotless.Core;using dotless.Core.configuration;

namespace RequestReduce.SassLessCoffee{    public class LessHandler : IHttpHandler    {        private readonly IFileWrapper fileWrapper;

        public LessHandler(IFileWrapper fileWrapper)        {            this.fileWrapper = fileWrapper;        }

        public void ProcessRequest(HttpContext context)        {            ProcessRequest(new HttpContextWrapper(context));        }

        public void ProcessRequest(HttpContextBase context)        {            var localPath = context.Request.Url.LocalPath;            var response = context.Response;

            try            {                var source = fileWrapper.GetFileString(localPath);

                response.ContentType = "text/css";                response.Write(new EngineFactory(new DotlessConfiguration                                                     {                                                         CacheEnabled = false                                                     }                                   ).GetEngine().TransformToCss(source, localPath));            }            catch (System.IO.FileNotFoundException ex)            {                response.StatusCode = 404;                response.Write("/* File Not Found while parsing: " + ex.Message + " */");            }            catch (System.IO.IOException ex)            {                response.StatusCode = 500;                response.Write("/* Error in less parsing: " + ex.Message + " */");            }        }

        public bool IsReusable        {            get { return true; }        }    }}

As you can see there is not much going on here in my code thanks to the DotLess compiler. I simply want to expose my own handler instead of the DotLess handler which does pretty much the exact same thing but I turn off the caching since RequestReduce has its own. This handler will ship as part of my own Nuget package providing Sass and Coffee compiling as well that will automatically wire up the handler mapping configuration from within the core RequestReduse assembly.

There are really four things I want to test here:

  1. Make sure I am setting Content type to text/css.
  2. Make sure that I am successfully calling out to the compiler with .less and getting back css.
  3. Ensure I return a 404 if there is no .less file associated with the .less URL being called.
  4. Return a 500 if something wrong happens in the compile.

Here is my Test Class:

using System;using System.IO;using System.Web;using Moq;using RequestReduce.SassLessCoffee;using RequestReduce.Utilities;using Xunit;

namespace RequestReduce.Facts.SassLessCoffee{    public class LessHandlerFacts    {        class TestableLessHandler : Testable<LessHandler>        {            public TestableLessHandler()            {

            }        }

        [Fact]        public void WillSetCorrectContentType()        {            var testable = new TestableLessHandler();            var context = new Mock<HttpContextBase>();            context.Setup(x => x.Request.Url)                .Returns(new Uri("http://localhost/RRContent/css.less"));            var response = new Mock<HttpResponseBase>();            response.SetupProperty(x => x.ContentType);            context.Setup(x => x.Response).Returns(response.Object);

            testable.ClassUnderTest.ProcessRequest(context.Object);

            Assert.Equal("text/css", response.Object.ContentType);        }

        [Fact]        public void WillWriteCompiledLess()        {            var testable = new TestableLessHandler();            var context = new Mock<HttpContextBase>();            context.Setup(x => x.Request.Url)                .Returns(new Uri("http://localhost/RRContent/css.less"));            var response = new Mock<HttpResponseBase>();            context.Setup(x => x.Response).Returns(response.Object);            testable.Mock<IFileWrapper>().Setup(x => x.GetFileString(It.IsAny<string>()))                .Returns("@brand_color: #4D926F;#header {color: @brand_color;}");            var result = string.Empty;            response.Setup(x => x.Write(It.IsAny<string>())).Callback<string>(s => result = s);            const string expected = "#header {\n  color: #4d926f;\n}\n";

            testable.ClassUnderTest.ProcessRequest(context.Object);

            Assert.Equal(expected, result);        }

        [Fact]        public void WillReturn404IfFileNotFound()        {            var testable = new TestableLessHandler();            var context = new Mock<HttpContextBase>();            context.Setup(x => x.Request.Url)                .Returns(new Uri("http://localhost/RRContent/css.less"));            var response = new Mock<HttpResponseBase>();            context.Setup(x => x.Response).Returns(response.Object);            testable.Mock<IFileWrapper>().Setup(x => x.GetFileString(It.IsAny<string>()))                .Throws(new FileNotFoundException());            response.SetupProperty(x => x.StatusCode);

            testable.ClassUnderTest.ProcessRequest(context.Object);

            Assert.Equal(404, response.Object.StatusCode);        }

        [Fact]        public void WillReturn500IfIOExceptionIsThrown()        {            var testable = new TestableLessHandler();            var context = new Mock<HttpContextBase>();            context.Setup(x => x.Request.Url)                .Returns(new Uri("http://localhost/RRContent/css.less"));            var response = new Mock<HttpResponseBase>();            context.Setup(x => x.Response).Returns(response.Object);            testable.Mock<IFileWrapper>().Setup(x => x.GetFileString(It.IsAny<string>()))                .Throws(new IOException());            response.SetupProperty(x => x.StatusCode);

            testable.ClassUnderTest.ProcessRequest(context.Object);

            Assert.Equal(500, response.Object.StatusCode);        }    }}

Here are a few things I’ll call out here that may be of interest:

The three A’s: Arrange, Act and Assert

This is a common paradigm in unit testing and provides an initial and very basic way of framing your tests. Start with Arranging your tests, then Act by calling the method you are testing and lastly Assert that what you expect to be true (or false) really is as it should be. Now, for some reason the code snippet editor I use in Live Writer, my blog editor of choice, has decided that I really did not need the extra line breaks that I typically insert between my arrange, act, and assert code. So for clarity:

//ARRANGEvar testable = new TestableLessHandler();var context = new Mock<HttpContextBase>();context.Setup(x => x.Request.Url)    .Returns(new Uri("http://localhost/RRContent/css.less"));var response = new Mock<HttpResponseBase>();response.SetupProperty(x => x.ContentType);context.Setup(x => x.Response).Returns(response.Object);

//ACTtestable.ClassUnderTest.ProcessRequest(context.Object);

//ASSERTAssert.Equal("text/css", response.Object.ContentType);

XUnit and Moq are my TDD tools of choice

You will certainly note the using statements referencing these libraries at the top. Over the years I have used different tools for testing and mocking and these are the ones that have stuck because they are simple and just feel natural to me. I encourage you to try them as well.

Dependency Injection, the Testable pattern, and Auto Mocking

Dependency Injection

Both at work and here at play, I make heavy use of Dependency Injection. In short, this is a pattern whereby you inject services into a class often, but not always, via a constructor and usually in the form of interfaces or abstract classes that are wired up through an IOC container like StructureMap (what I use) or one of many other containers with similar quality and functionality. If you are not familiar with Dependency Injection (DI) or IOC (Inversion of Control) containers, please stop reading this and go to your favorite search engine (mine is google and, who are we kidding, so is yours) to find out more.

I use dependency injection for several reasons and one of those reasons is testability. By injecting the interfaces of services that I need I accomplish two (probably several more) things:

  1. The logic included in those services can be tested elsewhere in their own test classes and isolating them in this way allows me to focus just on the logic executed by the class I am currently testing.
  2. By using interfaces, I can easily mock the expected behavior of those services. This way I don’t have to call those services directly which would require me to possibly set up all sorts of other stuff like files and database connections (yuck).

This handler demonstrates an extremely simple use of DI:

private readonly IFileWrapper fileWrapper;

public LessHandler(IFileWrapper fileWrapper){    this.fileWrapper = fileWrapper;}

My concrete implementation of IFileWrapper has all sorts of methods that do all sorts of fun and wonderful things with files. But who wants to deal with actual files in a unit test? I don’t.

The Testable Pattern

The Testable pattern, which I believe was coined by Brad Wilson (@bradwilson) co creator of XUnit, provides a nice structure for testing classes that use DI. Brad writes about it here. Essentially it involves creating a sort of wrapper class that derives from the actual class you are testing and exposes mocked, stubbed or faked implementations of its injectable services. The unit test class then works directly with this “Testable” class. A nice naming convention here is to call this testable class Testable[Your class under test name here]. Hence the class name I use: TestableLessHandler.

Auto Mocking

You may wonder why my testable class is so sparse. Well, they did not used to be. They used to look something like this:

class TestableLessHandler : LessHandler{    public Mock<IFileWrapper> MoqFileWrapper { get; set; }

    public TestableLessHandler(Mock<IFileWrapper> moqFileWrapper)        : base(moqFileWrapper.Object)    {        MoqFileWrapper = moqFileWrapper;    }

    public static TestableLessHandler Create()    {        return new TestableLessHandler(new Mock<IFileWrapper>());    }}

Well after writing about a hundred of these and often with many more than one dependency, I began thinking there has got to be a better way. And there is! Its called Auto Mocking, Something I have truly grown to love in an HR friendly sort of a way. My new testables look like this:

class TestableLessHandler : Testable<LessHandler>{    public TestableLessHandler()    {        //place for default mock setups    }}

I use StructureMap’s StructureMap.AutoMocking utility to accomplish this. You don’t have to use the full blown StructureMap IOC to use this. It is available as a separate Nuget package you can pull into your VS project and has a MoqAutoMocker class that works nicely with Moq. What auto mocking does is it looks at the dependencies that your class under test use and automatically creates Mocked implementations of the dependencies. Isn’t that nice?

I wrap up the auto mocking wire up in a class called Testable:

using System;using StructureMap.AutoMocking;using Moq;

namespace RequestReduce.Facts{    public class Testable<TClassUnderTest> where TClassUnderTest : class    {        protected MoqAutoMocker<TClassUnderTest> autoMocker =             new MoqAutoMocker<TClassUnderTest>();

        public Testable()        {

        }

        public Testable(Action<Testable<TClassUnderTest>> setup)        {            setup(this);        }

        public Mock<TDependencyToMock> Mock<TDependencyToMock>()             where TDependencyToMock : class        {            var a = autoMocker.Get<TDependencyToMock>();            return Moq.Mock.Get(a);        }

        public void Inject<T>(T type)        {            autoMocker.Inject(type);        }

        public void InjectArray<T>(T[] types)        {            autoMocker.InjectArray(types);        }

        public TClassUnderTest ClassUnderTest        {            get { return autoMocker.ClassUnderTest; }        }    }}

This is the first class that I add to any test assembly I create. I cannot take credit for writing this class. I’m not sure exactly who wrote it but it came from a team lead by my colleague Tim Shakarian (aka tshak). This class uses a combination of StructureMap.AutoMock and Moq to allow me to create a testable instance of my class that automatically exposes all of its dependencies via Moq Mocks.

So my test method uses TestableLessHandler like so:

//Create the testablevar testable = new TestableLessHandler();...//Access my depencency via Mock methodtestable.Mock<IFileWrapper>().Setup(x => x.GetFileString(It.IsAny<string>()))    .Returns("@brand_color: #4D926F;#header {color: @brand_color;}");...

//call method I want to test via the ClassUnderTest propertytestable.ClassUnderTest.ProcessRequest(context.Object);

After creating the testable, I can access its mocked dependencies via the Mock method. Not shown here, but something I often use, is the Inject method. I can say:

testable.Inject<IFileWrapper>(new SomeOtherFakeorRealFileWrapperImplementation())

When all the mock setups, callbacks, etc. are just as I want them to be and I’m ready to actually test my class, I can access the true class via the ClassUnderTest property.

Perhaps I’ll wrap up this testable into a Nuget package to make it easy for others (and me) to pull it into their test projects.

So hopefully this is useful to others. Ooops. spent too much time writing this and now I won’t be finishing my RequestReduce.SassLessCoffee Nuget package before work. Oh well…maybe tomorrow or tonight.

Track Nuget Downloads using OData, RSS and Ifttt.com by Matt Wrock

In this post I am going to show you how you can be notified of new downloads of any Nuget package via email from a service that will poll Nuget every 15 minutes. If email sounds overly intrusive, there are other options. So If this sounds interesting, read on.

If you have open source projects hosted on Nuget and you are a bit on the OCD (obsessive compulsive disorder) side, you are frequently tempted to wander over to Nuget.org and check out your download stats. Well, I have finally started to notice that I spend a fair amount of time every day, checking the Nuget site as well as other sites that may provide key indicators of my projects’ health. For instance I like to check for new followers or twitter mentions. Unfortunately, a lot of this time is spent simply waiting for a web page to load and reveal to me that there is no new information. So not only is this unproductive but it can lead to negative thoughts and emotions.

There are many pharmaceutical options available here, but I am not a Medical doctor and it would be unwise for me to give advise of a psychiatric nature. However I do have some technical solutions that simply require a computer with access to the world wide web. If you lack either of these, I have nothing to offer and you should now leave this page.

Ok. good. It’s just you and me now….hmm…this is uncomfortably intimate. No matter…

Switch from a Pull to a Push model

What I found myself craving was a way to let all of this information come to me and announce to me that there is new data rather than me having to spend time pinging several sources for what is likely to be no new information. In my case, I really wanted my phone to beep or vibrate when I get a new download, follower or mention. For me, this would not be a nuisance given the small amount of data. If you owned jQuery, you may want a more unobtrusive notification. Fortunately the solution I am about to propose can channel notifications through a variety of mediums.

Enter If-this-then-that ifttt.com

A few months ago I noticed a new referring link on my blog from a domain called ifttt.com. I visited the link and perused the site and discovered that it provided a way of creating sort of mash ups of various social media. ifttt stands for If This Then That. And the site simply allows you to create rules of If something occurs (new tweet, RSS feed item, DropBox item, etc.) Then some other thing should be triggered such as an email sent or a tweet or facebook update, etc. I have to admit my initial impression was “That’s dumb.” Then about a week later Scott Hanselman blogged about this service having been duly impressed by its offerings. I still didn’t really get it.

Not sure why I didn’t see the value right away but I see it now. Last week I setup a number of tasks that have freed me of the constant compulsion to check these various web sites for new data. I have a rule that will send me an email whenever my project has a new Github follower or a new mention on twitter. I have tasks that tell me when I have new stack overflow comments or new stack overflow points. All of these tasks were relatively easy to set up using ifttt.com. ifttt’s very friendly GUI provides an extremely simple way to send an email to yourself triggered by a new tweet or RSS feed item.

Here is an example of the task that sends me an email when my project RequestReduce is mentioned on twitter:

image

It is honestly trivial to set this up.

But Nuget Has no RSS Feed with items representing downloads

Currently Nuget provides no RSS feed or any notification option for subscribing to download stats beyond what is displayed on the project search results and individual project details pages. I don’t know if there are plans to implement this by the Nuget team in the near future, but I wanted something up and running soon that didn’t need to be polished.

All Nuget data iavailable from the website is exposed through an OData feed

I knew that the data I was interested in was available via OData. There are a few posts out there that talk about this. I found that David Ebbo’s post had the detail I deeded to get started. With the name of any Nuget package Id, you can get its total download count via the public Nuget OData endpoint at http://packages.nuget.org/v1/FeedService.svc.

Here is an example query using LinqPad:

image

 

Creating a custom RSS Feed to broadcast new downloads

Currently as far as I can tell, there is no facility built into ifttt to consume this OData format. Yes, you can expose OData as an ATOM feed but given the Nuget schema, this would only be useful if you wanted to be notified of new versions. Essentially each version is a child entity of the master Packages entity. DownloadCount is simply a property associated with each version. Note that a version has both a VersionDownloadCount and a DownloadCount. The first is simply the count for a single version and the latter is the aggregate count of all combined versions released in a single package.

At first I tried playing with Yahoo Pipes and some other online RSS builder apps but none of these was going to work. At least not simply. I didn’t want to spend a lot of time on this since what I wanted was really quite simple and could be coded up fairly trivially. So I ended up just writing my own feed generator and I took the opportunity to create my first Azure application. I plan to blog more specifically on the azure specific details later and how they differed from my work with an AppHarhor application.

Here is the RSS Generator code:

public class FeedHandler : IHttpHandler{    private const string NugetServiceUri = "http://packages.nuget.org/v1/FeedService.svc";    private readonly IDictionary<string, IList<SyndicationItem>>         packageDownloadCounts = new ConcurrentDictionary<string, IList<SyndicationItem>>();

    public bool IsReusable    {        get { return true; }    }

    public void ProcessRequest(HttpContext context)    {        var packageName = context.Request.QueryString["packageId"];

        var nugetContext = new Nuget.GalleryFeedContext(new Uri(NugetServiceUri));        var last = (            from x in nugetContext.Packages             where x.Id == packageName && x.IsLatestVersion             select new { x.DownloadCount, x.Version }).First();

        var items = GetSyndicationItems(packageName, last.DownloadCount);        var nugetUrl = string.Format(            "{0}/Packages(Id='{1}',Version='{2}')", NugetServiceUri, packageName, last.Version);

        var feed = new SyndicationFeed("Nuget Download Count Feed",           "Provides the current total download count for a Nuget Package",           new Uri(nugetUrl), nugetUrl, items.Last().LastUpdatedTime,           items);        using (var xmlWriter = XmlWriter.Create(context.Response.OutputStream))        {            feed.SaveAsRss20(xmlWriter);            xmlWriter.Flush();            xmlWriter.Close();        }

        context.Response.ContentType = "text/xml";        context.Response.End();    }

    private IList<SyndicationItem> GetSyndicationItems(string packageName, int count)    {        IList<SyndicationItem> items;        lock (packageName)        {            if (packageDownloadCounts.ContainsKey(packageName))                items = packageDownloadCounts[packageName];            else            {                items = new List<SyndicationItem>();                packageDownloadCounts.Add(packageName, items);            }            var title = string.Format("{0} has {1} total downloads", packageName, count);

            if (!items.Any(x => x.Title.Text == title))                items.Add(new SyndicationItem(                   title,                   "",                   new Uri(string.Format("http://nuget.org/packages/{0}",                                         packageName)), Guid.NewGuid().ToString(),                   new DateTimeOffset(DateTime.UtcNow)));            while (items.Count > 20)                items.RemoveAt(0);        }

        return items;    }}

You can grab the full Visual Studio Solution from https://github.com/mwrock/NugetDownloadFeed. Not much happening here. Its just a handler that takes a packageId in the query string and then checks the odata feed to see if there are more downloads than there were since the last time it checked. If there are, it creates a new feed item.

ifttt.com will poll this feed every 15 minutes. I currently have this feed up and running at http://wrock.cloudapp.net/downloadFeed.axd. Anyone is free to use it but I provide no guarantee for stability or longevity. That said, I have no plan to change the endpoint or bring it down. However, I may clean the code up a bit and offer it as a Nuget package so that anyone can host their own feed.

Consuming the feed from an ifttt.com Recipe

Beyond the creation of “one off” tasks. ifttt provides a means of encapsulating common task logic into a reusable “Recipe.” These are handy if you find yourself creating the same task again and again with the only difference being a single variable. In my case here, I wanted to create three tasks. One for each of my Nuget projects. It also seemed reasonable that others may want to make use of this as well. So I created a recipe that anyone can use in order to create their own Nuget Download Notification task. Simply create an ifttt account (Super fast and easy to do) and go here: http://ifttt.com/recipes/9302.

image

As the directions state, simply replace my Package Id RequestReduce with the Package Id that you are interested in.

If you do not want to be notified by email, you have several different options. You could have it tweet from a specific account, send an SMS message or create an Evernote entry. And there are many more options than that.

I’d really like to hand it to the folks at @ifttt for creating this ingenious service and wish them the best of success!

Adding CSS Inheritance Resolution to RequestReduce Sprite Generation Process by Matt Wrock

UPDATE: This functionality was released on 1/9/12 in v1.7.0.

Currently RequestReduce is unable to sprite alot of background images because of its limitation of treating each css class as an atomic unit. Inheritable dimensions and padding is lost which either makes an image unspritable by RequestReduce or the sprite is malformed because of improperly calculated dimensions.

Further, pre-sprited images in a document about to be reduced are often malformed and rendered in a distorted fashion because it is common practice to place the background url in one widely inherited class and have more specific classes define just the background-position of the individual image in the sprite. This makes many initial renderings using RequestReduce give a bad first impression especially if the user does not read the wikis on preparing the sprites and spriting requirements here and here. It can also make the exercise of converting docs to be compatible with RR spriting a time consuming and tedious endeavor.

I had initially thought this was a small edge case but it is proving to be an all too common problem and I think the adoption story could be dramatically improved by adding this feature. This is the one feature that can break the RequestReduce golden rule: do not break the page I am reducing. The addition of this feature can prevent this.

Unfortunately it is not a small effort. However it is not monumental either.

Installing an HttpModule via Dropping in the bin without Editing Web.config by Matt Wrock

Last week another team wanted to use an HttpModule I had written. The problem is that they had no access to the hosting platform of their content. Their DLLs are consumed via MEF by a rather large infrastructure affectionately known as MTPS or what the world knows as the MSDN Library.

Unfortunately, the functionality provided by this DLL requires that it be run as an HttpModule. So I remembered reading a post of David Ebbo that described how to load an HttpModule dynamically at run time.The topic suddenly seemed relevant to this issue so I revisited his blog and applied his instructions to my assembly and wow…sure enough, just drop my dll in the bin and BAM! it loads and runs. If you would like to see a very small example app that does this please see my code sample on the MSDN Samples Gallery.

Technically, to accomplish this the code involved couldn’t be more trivial. Here is a quick walk through.

Specify a PreApplicationStartMethod

In the Assembly.info of the assembly containing the HttpModule, the below attribute must be included:

[assembly: PreApplicationStartMethod(typeof(Loader), "LoadModule")]

This line points to a Method inside the assembly which should be envoked during Pre Application Startup. This event occurs even before the Application Start event in the ASP.NET lifecycle. The official MSDN Library reference for this attribute can be found here. Of course this is assuming that there is a class either inside the assembly or referencable to the assembly of type Loader and that it contains a method called "LoadModule."

Dynamically Register the Module

Inside the LoadModule method, you will use the Microsoft.Web.Infrastructure assembly to actually register the module. The Microsoft.Web.Infrastructure assembly is not included in the .net BCL but you can easily download and install via Nuget. Here is a look at the entire Loader class:

using Microsoft.Web.Infrastructure.DynamicModuleHelper; 

namespace HttpModule {     public class Loader     {         public static void LoadModule()         {             DynamicModuleUtility.RegisterModule(typeof (DynamicModule));         }     } } 
As you can see there is not a whole lot to this. Just one line simply tells the run time the type name of the HttpModule to be registered. Here the HttpModule is inside a class called DynamicModule. The type that you pass to RegisterModule must derrive from IHttpModule.

Is this a good practice?

At first glance this seems really cool. It removes one setup step that consumers of the HttpModule would normally have to go through to install a third party module. It appears that this would provide a more friction free installation story for any third party module. What can be bad about that?

Well maybe I'm over thinking this but my first concern here is discoverability. What if the module has heavy hitting impact on the markup of the page. I envision a new developer or team inheriting such an application and wonder just how long it will take for them to find where this "alteration" is coming from especially in a sophisticated application with perhaps 20 referenced DLLs and lots of internal code. Or perhaps a team member drops in such a module and forgets to tell the team she put it there. I'm thinking that at some point in this story some negative energy will be exerted. Perhaps even a tear shed?

As an author myself of an open source HttpModule that can transform the markup of a site, this is of particular interest to me. My RequestReduce project is a module that combines and minifies CSS and Javascript and sprites and optimizes CSS background images on the fly. Since the default behavior of the module simply requires the module to be registered in the user's web.confg, if I were to employ the technique used in this sample, the module installation would have a truly plug and play installation story which sounds very awesome and I am tempted to add it. But I worry.

I'd be interested in others feedback in this matter. Do you think it is a good idea in general practice? Do you think the perhaps limited discoverability poses a true risk? In the end, do you think consumers would be more or less attracted to such an installation story?