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

13. November 2011 05:40 by Matt Wrock in   //  Tags:   //   Comments (6)
DotNetShoutout
DotnetKicks

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?

Comments (6) -

Jeff Putz
Jeff Putz
11/13/2011 6:15:12 AM #

Wow, just seeing "MTPS" makes me cringe, even knowing I never have to think about it ever again!

Regarding your concerns, think about it this way. The alternative is to have to explicitly declare the module in config. What you're suggesting is that it lives in its own assembly, and automagically registers itself. It stands to reason that if you don't want to use it, you won't have the assembly in your bin. In the times of NuGet, who doesn't know what's in their bin? I think it's a great approach.

rey rahadian
rey rahadian
11/13/2011 1:21:01 PM #

in my opinion it has more positive impact than negative. As you point out it becames fairly easy to add in new modules without editing the web.config. What you fear about the problem in maintenance can be avoided by providing some kind of agreement or common understanding of how the dynamic module should be added, for eq: use special prefix for the module, or something a long that line

Paul Vaillant
Paul Vaillant
11/13/2011 10:20:04 PM #

I think it's a great idea and while it's true that in a very large project it could get lost in the shuffle, what if the code "announces" that it has autoregistered itself via an entry in the event log?

Lars Outzen
Lars Outzen
11/14/2011 2:22:40 AM #

Do proceed to also reduce our config work.

Trust you or anyone else will NOT piggy-bag this fictive feature; AutoReg-ed HttpModule that ships validated authentication requests. Guess that could be 'the' reason to remove the PreApplicationStartMethod. Maybe a mandatory warning-level system-EventLog-entry is enough pr invoke.

BTW RequestReduce will be somewhat obsoleted by msdn.microsoft.com/library/system.web.optimization.bundlecollection.enabledefaultbundles.aspx except for the sprits: https://github.com/mwrock/RequestReduce/issues/54

To continue MS-momentum try to promote a RequestReduce-rule in Forefront. Do open-source for Fiddler2/other (reverse-)proxies.

Anyway it is probably also possible to do a dynamic check of browser-rendering with/out reduce and then compare => in/valid reduction or not. InProxy+AutoTests => Easy to test your changes against world-wide-sites, that use more and more cross-site-JS, and e.g. auto-optimize buttom/top-page-loads like code.google.com/.../rtt.html

Nice that you have open-sourced your unique skills - sorry that you are doing it in your "free" time.

Matt Wrock
Matt Wrock
11/14/2011 8:48:12 AM #

Paul,

Yes. I had considered something like this too. Perhaps logging a html comment in the head stating something like "Image Spriting and CSS and Javascript Merging and Minification provided by RequestReduce. It might seem a bit overly self promoting but I'd provide an optional config setting to turn it off. If someone does turn it off, simply having that config in the web.config may be discoverable enough.

Matt Wrock
Matt Wrock
11/14/2011 9:06:58 AM #

Hi Lars,

I'm not sure RequestReduce will be made obsolete by the new bundling feature in .net 4.5. While the functionality of merging and minification provided by both is clearly similar they are implemented differently in that RequestReuce performs the reductions at runtime via a response filter allowing it to:
- Include css and javascript hosted outside of your domain
- take control of serving the reduced content with optimized caching headers
- Can include dynamically generated scripts and css like WebResource.axd and ScriptResource.axd
- Requires no config or code to find and reduce static resources. RequetReduce knows how to find everything. You only need to use the RequetReduce api if you want certain content to be excluded.
- Will support the ability to load css and javascript asynchronously via a loader and support browser specific optimization APIs depending  on the user's user agent.

I don't believe the .net bundler will do any of that. I think the new bundler is great and will provide some good functionality to alot of sites but if you have alot of dynamically included js/css or want to leverage some cutting edge perf techniques, RequestReduce provides some nice features.

Pingbacks and trackbacks (3)+

Add comment

biuquote
  • Comment
  • Preview
Loading

About Me

Hey thats me!

I'm Matt Wrock with over thirteen years of experience architecting scalable, distributed, high traffic web applications. I currently live in Woodinville, WA with my wife, two daughters, three dogs and cat. I work for Microsoft as a Sr. Software Engineer working in Cloud Developer Services. I'm also project founder and owner of http://www.requestreduce.org and a committer to http://chocolatey.org.

Month List