Wednesday, February 18, 2009

Beware when you upgrade ...

It's a real pity when you realize that you are truly disappointed by a new version of a software you use.

When Windows Media Player 11 came out, I've upgraded from WMP 10 immediately. To me, a new version always means new functions, enhanced compatibility, stability and security.

I got no problems with WMP 11 until I've bought two great soundtracks by Jeremy Soule from DirectSong. These soundtracks are protected by the DRM - you are required to obtain a valid license from the soundtrack provider to be able to play it with the Windows Media Player.

To be able to backup your downloads, DirectSong says that:

Our current licensing is set up to allow unlimited Soundtrack CDs to be burned per machine download.

Great, this does not work in WMP 11 - you learn from the WMP that the license does not allow you to burn, synchronize or even play the music (which does not stop the music from actually playing!).

After few nervous hours spent trying to find out what's the problem, I've learned from someone's blog that you have to downgrade to WMP 10 to get this to work.

I don't remeber beeing so disappointed by a new version of the Microsoft's software for a long time. A new version which breaks the backward compatibility is not something which I could accept.

Friday, February 6, 2009

Inject application-specific code into ASP.NET module

We often write ASP.NET modules to customize ASP.NET processing pipeline - extend security, etc.

   1: public class ExampleModule : IHttpModule
   2:  {
   3:      #region IHttpModule Members
   5:      public void Dispose() { }
   7:      public void Init( HttpApplication context )
   8:      {
   9:          context.BeginRequest += new EventHandler( context_BeginRequest );
  10:      }
  12:      void context_BeginRequest( object sender, EventArgs e )
  13:      {
  14:          // extend the processing pipeline by providing
  15:          // custom code for particular events, in this case
  16:          // the BeginRequest event
  17:      }
  18: }

However, as modules are static, in a sense that a module is active or inactive in processing pipeline, applications which "host" modules are dynamic, in a sense that different applications work under different conditions.

The issue we've faced recently was to inject a custom, application specific code into module:

   1: void context_BeginRequest( object sender, EventArgs e )
   2: {
   3:     // how to call an application-defined code
   4:     // but do it so that the module is not
   5:     // rewritten everytime application changes
   7:     // ?
   8: }

The solution we've came up with was rather simple: we've used a custom provider to provide application-specific code.

   1: <system.web>
   2:     <specificProvider defaultProvider="ApplicationSpecificProvider">
   3:         <providers>
   4:             <add name="ApplicationSpecificProvider" type="Namespace.ApplicationSpecificProvider" />
   5:         </providers>
   6:     </specificProvider>

This way we can configure different providers on the application level but still be able to write generic module code:

   1: void context_BeginRequest( object sender, EventArgs e )
   2: {
   3:     HttpApplication app = (HttpApplication)sender;
   5:     SpecificProvider.DoSpecificOperation( app );
   6: }