RFI Keeping Open Source Dependencies Up To Date

We just deployed the first phase of a new project that uses a large number of open source components including Castle (Windsor & MonoRail), NHibernate, and Rhino Commons to name the big players.  As with any project as much as I know about programming I learned even more when the rubber met the road.  Many right decisions were made, some wrong decisions were made, and the code has only been deployed for a month and I'm already making a long list of how I can do it better next time. 

One particular area that I want to get better at is staying current with dependencies.  Most OSS projects are constantly being improved and still remain stable.  Here is how my project began...I downloaded a debug build of Castle RC3, picked out the assemblies I needed, and added them to my /trunk/lib folder (What I look back on as my first mistake).  I built the latest trunk revision of Rhino Commons, and added those assemblies to my lib folder (at least I was consistent).  I then happily worked on my application, writing code, unit tests, a build script, life was good.  As we progressed in development there was a few things we needed to do in MonoRail that just didn't jive with MR conventions.  So, I synced to the RC3 branch, changed two lines of code, rebuilt, and updated my libs (second BIG mistake).  Life was good again, but then ran into a small snag with Rhino Commons.  Ok, I was able to tweak MR just a bit, so I can do the same with Rhino (see consistent, but I shoulda learned :).   Hmmm...the AI Sourcing machine has been busy and Rhino Commons has changed quite a bit since I grabbed the source last.  So I had to do some digging and diffing to find out what rev I had built from previously.  Finally I get back to the right rev (I right it down this time) make my changes, rebuild, and update my libs.  Coding progresses, but eventually I run into the same situation again, this time I actually commit a copy of the relevant (read only the projects that I need to tweak) code into our source repo (which isn't SVN to make things even more interesting) and begin to diligently comment explicitly the lines I change.  Just call me Sofa King Screwed :)

I'm a half way decent coder but I make dumb decisions sometimes.  I acknowledge that, and I want to get better.  At some point I will need to re-up my dependencies or be forever locked into an out dated version.  What I'm looking for is a better way.  What do you do with your OSS dependencies?  I've read posts where devs refer to a "private branch" which I presume to be a more organized approach to what I ended up doing.  Do you merge with the projects trunk?  How often do you merge with the projects trunk?  Are your dependencies built with your application or do you build them separately and only reference the assemblies?  Dan's post on How to Branch Properly got me thinking that may be the way to go.  Grab a trunk copy of the dependencies to be used, add them into my application's solution/build process, and merge with the trunk on a scheduled basis.  If appropriate the changes I make to my private branch can be refactored into patches to be submitted.  Is this an approach any of you have used?  Does it work?  Have you automated the trunk merge process?  We don't use SVN, but our source control solution is touted as king of merging, so I presume it would be fairly straightforward.  The other issue is when my dependencies depend on each other.  Oren makes it look easy.  This leads me to believe that the right approach is to stick with the build/reference as lib approach.  I'm willing to earn my paycheck, but if somebody already has a working solution, I'd love to hear about it.

Lazy Loading with nHibernate Under Medium Trust

Medium Trust is the Devil.  If you do not know what Medium Trust is in the context of ASP.Net, then I will leave you with one request and you can skip the rest of this post.  I entreat you to please mark all of your assemblies with AllowPartiallyTrustedCallers unless you have a compelling reason not to.  By adding this single attribute you remove the first of many hurdles that users of your software must contend with when running under Medium Trust.  If Medium Trust is such a pain, why would you ever subject your application to it?  Most third party hosting companies (GoDaddy, 1and1, WebHost4Life, etc.) lock down their servers to Medium Trust.  If you own a box or rent your own dedicated/virtual private server, then you don't have to deal with the pain that all of the other budget hosters are subjected to.

I am a big fan of nHibernate and am currently working on a little application in my free time that uses it.  It is a small time application and I don't have a lot of spare scratch so I started researching some shared hosting environments.  That is when I ran into Medium Trust and began investigating what that meant for nHibernate.  There are a lot of posts and forum entries out there on the topic so make sure and do your homework.  Mike Gavaghan has a nice chronicle on his Medium Trust adventure.  I compiled a list of what was needed to determine the feasibility of running nHibernate in Medium Trust.

  1. Add 'requirePermission="false"' to your nHibernate configuration section in your web.config file.  Ok, no big deal, nice and easy.
    <configSections>   
    <section name="hibernate-configuration" requirePermission="false" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"/>
    </configSections>
  2. Disable the Reflection Optimizer.  The docs say you may see a performance boost during initialization but see a performance hit over the long term operation of your app.  Run your own tests to determine the impact.  Again a simple configuration change.
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <reflection-optimizer use="false" />
    <session-factory>
    ...
    </session-factory>
    </hibernate-configuration>
  3. Disable all lazy loading of entities.  Whoa!  Big deal!  No Way!  Can't do it!

nHibernate saves me a lot of coding and pain by abstracting my datastore and provides a sweet Criteria API.  It also lets me structure my object associations to transparently retrieve entities from my data store in an 'on demand' fashion.  That statement glosses over a lot of details that you really need to familiarize yourself with if you decide to start using nHibernate.  But suffice it to say I consider it a critical feature. 

Why can't I use lazy loading in Medium Trust?  Lazy loading requires the generation of 'proxy' classes that delay the retrieval of associated entities from the data store until they are actually accessed in code.  I tried to find a better explanation but the best I could come up with is a dated Server Side.net article.  The generation of proxy classes requires Reflection permissions that are not granted in a Medium Trust environment.

After all this research it looked like I wouldn't be able to use nHibernate the way I wanted to in a Medium Trust environment.  I cried for a while and my wife comforted me and said maybe I should try Linq to SQL which made me cry even more.  Eventually I settled down and started thinking some more.  nHibernate needs to make a proxy for my entity.  OK, I've come to terms with that.  My entities do not change during the execution of my app, so I would think that the proxies wouldn't change.  Is there a reason why the proxies need to be generated at run-time?  Why couldn't they be pre-generated and deployed with the app?  Hmm...I need to do some spelunking in the nHibernate sources.  What creates the proxies?  A ProxyFactory of course.  OK, I will need to make one of those.  How do I tell nHibernate to use my ProxyFactory?  Well, I need a ProxyFactoryFactory and a small configuration addition...let's escape from the dark inner workings of my mind and cut to the chase.

I labored for a few hours and came up with a free tool that will allow you to generate an assembly containing pre-generated proxies for the purpose of enabling lazy loading in a Medium Trust environment.  That's right, free.  Not free as in speech.  Free as in I did all of the hard work so you wouldn't have to.  This tool is creatively named NHibernate Proxy Generator (NPG.exe) and it should be a nice addition to your nHibernate tool chest (right next to NHibernate Query Generator).  The implementation is quite...ghetto...the reason is due to the fact that my programming skills are sick, not IL, and I failed weaving in Home Ec.  My immediate plans are some refactorings that remove some of the dependencies that were used out of expediency (Boo Compiler and ILMerge).

NPG is currently of a quality between Meware and Alpha.  I want to stress that it is still very raw but I have tested it with both nHibernate mappings and ActiveRecord entities.  The command line syntax is very basic and it integrates nicely as an AfterBuild target with MSBuild.  Here is what you need to get started.

  1. Download the binaries or sources.
  2. Follow steps one and two above.
  3. Build the assembly containing your nHibernate or ActiveRecord entities.
  4. Run from the command line, passing the name of the input assembly from step two, and the name you would like to use for your output assembly.
    NPG.exe /in:My.Entities.dll /out:My.Entities.Proxies.dll /lazy:+
  5. --or--   You could add something similar to the following in the project file for your entities project:
    <Target Name="AfterBuild" Inputs="$(OutputPath)$(AssemblyName).dll" Outputs="$(OutputPath)$(AssemblyName).Proxies.dll">
    <Exec Command="..\..\tools\NHibernate.Proxy.Generator\NPG.exe /in:$(OutputPath)$(AssemblyName).dll /out:$(OutputPath)$(AssemblyName).Proxies.dll /lazy:+" />
    </Target>
  6. Add the following to your nHibernate configuration:
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <reflection-optimizer use="false" />
    <session-factory>
    ...
    <property name="proxyfactory.factory_class">StaticProxyFactoryFactory, My.Entities.Proxies</property>
    ...
    </session-factory>
    </hibernate-configuration>

The tool should work with any nHibernate Trunk build at revision 3090 or better.  When you run into issues with the tool, have suggestions for improvement, or want to add functionality please let me know.

Question for Generic Specialists

This is not a quiz, I would genuinely like some help here.

Can some explain to me why this compiles:

IEnumerable<int> ints = new int[0];

And this compiles:

IList<int[]> ints = new List<int[]>();

But this does not compile:

IList<IEnumerable<int>> ints = new List<int[]>();

And subsequently this does not compile:

public void Generic_List_Of_GenericType()
{
  List<int[]> ints = new List<int[]>(); 
  MyMethod( ints ); 
}

public void MyMethod(IEnumerable<IEnumerable<int>> test)
{
}

It is not clear to me why the compiler can figure out the first two cases but not the latter two.

[NonTechnical] Harsh Times

With the impending recession and the weakening dollar, I'm cracking the whip and forcing my son to get a job.  He and his mother have teamed up to take on FireDog and Geek Squad directly.  Don't struggle with an ailing computer any longer.  Call today!

AWP_Computer_Services

Is WebForms Right for You?

@Phil:  Turn off Central Heating

Please read Phil's post to determine if MVC is Right for You before proceeding.

Phil On MVC:

"It's true, MVC is not the model for people who want the freedom to be creative with their code. It's the pattern you follow if you want to conform with a particular doctrine of programming. There is (if you follow it to the letter of the law) not a huge degree of flexibility."

"That's the theory anyway. In reality, you as a developer can still put code in the wrong place, you can still make bad decisions on how to structure your application and you can still essentially cock the whole thing up."

I'm confused, with MVC am I forced to write one way or am I not?

Phil On WebForms:

"With Web Forms as a developer, you're pretty much free to follow the path which suits you best."

"I strongly support the Web Forms model and believe that the majority of the flaws in Web Forms that MVC purports to overcome are easily solvable by following the guidance and advice of experienced ASP.NET developers."

"Those of us who have been building ASP.NET professionally for years are now in a position where it is easy. We have our pattern to follow and we know how to build good maintainable ASP.NET applications."

"Structure and form becomes an integral part of our Web Forms applications."

If you are an experienced ASP.Net developer you write WebForms with the same pattern as all of the other experienced developers.  So, I can write WebForms following any path that suits me best, but in reality there is only one best path. 

It's the Convention Stupid

MVC is all about conventional web development.  By convention, your code is logically split into three categories: Models, Views, and Controllers.  By convention, your Controller has one or more Views and orchestrates the interaction between users and business logic.  By convention, a Controller action will render a View with the same name as the Action.  By convention, Views contain only rendering logic.  By convention, Views are stored in a folder with the name of its respective Controller.  By convention, that folder is stored in a root folder called Views.  By convention, layouts (master pages) are stored in a folder called Layouts.  By convention you flame anyone who talks bad about MVC.

I am three weeks from releasing a medium sized application written using MVC.  Guess what, I needed to store my Views in a folder that wasn't called Views.  So I broke convention.  My framework of choice supported the ability to change this convention.  I broke several other conventions in the course of development.  When you say that "There is not a huge degree of flexibility" with MVC, that is complete FUD.  What you meant to say was that the framework you are using to achieve MVC has limited flexibility. 

ASP.Net has the same concept of a convention, it's called Patterns & Practices.  I only wish this convention had preceded the release of ASP.Net, rather than being born years later out of a prevalent lack of "guidance and advice of experienced ASP.Net developers."

MVC Makes Testing Your Applications Possible Easy

"I'd agree testing is hard with Web Forms. In fact, I found it so difficult I abandoned trying to unit test my ASP.NET code and moved to a process of using Watir and testing the rendered HTML instead." 

Phil postulates that less than 1% of all .Net developers unit test.  I will give him the benefit of the doubt and interpret this to mean that less than 1% of .Net developers unit test non-business logic code.  He goes on to say that it's great the MVC makes this possible but it doesn't really matter because people who didn't unit test before will not unit test now.  Phil, did you ever think that the reason that ASP.Net developers do not unit test their code is because it is so difficult they choose to abandon it?  Perhaps if it were simple and straight forward and part of the guidance and advice of experienced ASP.Net developers, that number would be higher?  Just a crazy theory of mine.

Learning Swerve

If you are designing a serious web application using ASP.Net, you better know the Page Event Lifecycle forwards and backwards (the overview alone is eight (8) printed page).  You better be intimately familiar ViewState, SessionState, Server Controls, User Controls, and INamingContainer.  You better be causally familiar with the Application Event Lifecycle.  Don't even bother trying to use rich third party libraries like Prototype or jQuery, unless you want to write ASP.Net wrappers for everything.  But oh yeah, you can use MS AJAX for all that.  Better put that on your intimate familiarity list too.  Unless you are writing an online guest book for your mom you better know your stuff.

Phil really pushed my hot button with this quote (I do not know if these are his words or if he is quoting someone else):

"Programmers more than nearly any other demographic, despise change. Programmers not only despise change, they run from it and tell other people that change will kill them as they trample innocent bystanders."

HELLO PHIL!  ASP.Net was the single largest changes to web development since CGI.  We went from writing HTML with classic ASP to a complete freaking object model for everything down to Literal text.  So don't spout this FUD about trampling innocent bystanders.  Don't cry to me because you feel you've wasted years learning about ASP.Net and that it doesn't apply to MVC.  Maybe if you had studied HTTP and HTML instead of this leaky abstraction that attempts to 'simplify' and already simple protocol, you'd be in a better position today.

I will admit, to be effective with MVC, you must be comfortable with HTML.  HTML, that is HyperText Markup Language.  Are you familiar with it?  It is relatively new, only came out about 25 years ago.  I think they start teaching it in elementary (primary) school nowadays.  If you aren't familiar with it, luckily:

"With the mass of technical articles, blog posts and snippets out there around HTML ASP.NET Web Forms one other great advantage is that almost any problem you can face with HTML ASP.NET will be documented and the solutions listed somewhere on the Web, it's just a matter of searching for them."

What is the first thing you learn in a programming course?  Variables, flow control, and loops.  Combine those three concepts with an understanding of HTML and you have 75% of the knowledge necessary to create a user interface using MVC.  Next you will learn about functions and maybe an object.  If you can write an object with a function then you can invoke an Action on a Controller.  The curve doesn't look so steep now does it.

Control Over your HTML and JavaScript with MVC

This seems to come up a lot in discussions about MVC.  We always spout off about separations of concerns and such, and somebody points a finger at code in your view and says "..the separation of markup from code is completely disregarded as a non issue."  It is disregarded as a non issue because it is a non issue.  Just because your asp:GridView and asp:Repeater represent code via XML doesn't mean you aren't mingling markup and code.

Let me leave no room for confusion: your View contains view logic.  This is again where Phil misleads you by saying MVC leaves little room for flexibility.  Some people like to design their Views with absolutely no logic, the Controller does all of the thinking right down to the color of a table row.  Others like the Controller to specify the logic (line item 26 is backordered) and let the View handle the presentation (if lineItem.IsBackorderd then tr.BackColor = 'Yellow').  I personally subscribe to the latter but the flexibility is there for you to choose what works.  And as I mentioned before, have fun integrating something like jQuery with your ASP.Net app.

In Summary

Use What Works.  If you are happily developing with ASP.Net and it causes you no pain, then there is absolutely nothing MVC can offer you.  I have developed ASP.Net applications.  They have caused me pain.  I chose to explore other options.  I find myself more productive with MVC.  If you had developed those same ASP.Net applications, you may very well have not felt the pain I did and would happily continue to use ASP.Net.  Use What Works.

Do not attempt to say WebForms is better than MVC or that MVC is better than WebForms.  I have not attempted to say that MVC is better than WebForms in any respect (with the exception of unit testing).  I have vigorously attempted to counter the FUD from Phil's article. 

I find that MVC Works.

@Phil:  Turn on Central Heating.

Extension Methods are the Devil

There are a few instances where I see extension methods being valuable and saving you from excess typing.  The biggest one would be a set of extensions that bring all of the lovely members of List to their respective IEnumerable/ICollection/IList brethren.  Along the lines of:

public static void AddRange<T>(this ICollection<T> col, IEnumerable<T> collection)

public static ReadOnlyCollection<T> AsReadOnly<T>(this ICollection<T> col)

public static ICollection<T> ConvertAll<T, TOutput>(this IEnumerable<T> col, Converter<T, TOutput> converter) etc...

Any other use of extension methods will force me to stab you in the eye and cut off your right pinky finger, making it impossible for you to type the semi-colon (;) character and relegating you to the ranks of VB.Net programmers the resulting humiliation of which should cause you to finish the job yourself.

Let me summarize the short comings of extension methods and pick on the MvcToolkit as an abusing offender.  Read more bloggers (Derik, John, and Karl)  who agree with me in spirit if not in eye-stabbing, pinky severing practice.

Extension Methods...

  • Should be used sparingly. (Wear goggles and a gauntlet while you make your case to me, just to be safe)
  • Are nothing more than a compiler trick.
  • Are achievable through more discoverable means.
  • Are NOT mixins.
  • Are not overrideable.
  • Are not discoverable at run-time.
  • Will cause you pain.
  • Should absolutely NOT be used to add methods to classes for which you own the source code.

Consider the following code which compiles:

namespace Pain
{
  using ExtensionMethods.AreThe;

  public enum Eye { Left, Right }

  public class ExtensionMethodUserPunisher
  {
    public void StabEye()
    {
      this.StabEye(Eye.Left);
    }

    public void SeverPinky()
    {
    }
  }
}

namespace ExtensionMethods.AreThe
{
  using Pain;

  public static class Extensions
  {
    public static void StabEye(this ExtensionMethodUserPunisher subject, Eye eye)
    {
    }
  }
}

Now consider this almost identical code, which does not compile:

namespace Pain
{
  using ExtensionMethods.AreThe;

  public enum Eye { Left, Right }

  public class ExtensionMethodUserPunisher
  {
    public void StabEye()
    {
      StabEye(Eye.Left);
    }

    public void SeverPinky()
    {
    }
  }
}

namespace ExtensionMethods.AreThe
{
  using Pain;

  public static class Extensions
  {
    public static void StabEye(this ExtensionMethodUserPunisher subject, Eye eye)
    {
    }
  }
}

Now consider what happens if you modify your using statement:

namespace Pain
{
  using ExtensionMethods.AreThe.Devil;

  public enum Eye { Left, Right }

  public class ExtensionMethodUserPunisher
  {
    public void StabEye()
    {
      this.StabEye(Eye.Left);
    }

    public void SeverPinky()
    {
    }
  }
}

namespace ExtensionMethods.AreThe
{
  using Pain;

  public static class Extensions
  {
    public static void StabEye(this ExtensionMethodUserPunisher subject, Eye eye)
    {
    }
  }
}

namespace ExtensionMethods.AreThe.Devil
{
  using Pain;

  public static class Extensions
  {
    public static void StabEye(this ExtensionMethodUserPunisher subject, Eye eye)
    {
      subject.SeverPinky();
    }
  }
}

You code still compiles just fine, but you will get different behavior and it should be fun tracking down why.

Oh but you can abuse any language feature, and you would never do something like this, and this is never going to happen to you, and you are going to extend the crap out of System.Object because you can.  Fine, but when the time comes I'm not even going sully my pen with your ocular juices.

Back to the MvcToolkit.  Rob's eye get a grace period, because this is only a CTP.  I'm not privy to the internal workings of the MVC team so I'm not sure why this was initially developed as a separate assembly.  I know that the plan is to move it into System.Web.Extensions.  I hope that when it is moved that all of the 75+ HtmlHelper extension methods become first class members.  Here's why:  Not all consumers of HtmlHelper are compiled, making extension methods pretty useless.  And maybe I want to override the output of TextBox without re-writing the whole method and without resorting to the mess demonstrated above.

Please feel free to flame me with your comments exhorting the virtues of extension methods.

Updated: A Better Dictionary Initializer

Alex Henderson tactfully commented on my last post that he had already been there, done that, and got the tee shirt.  Based on his work, a refactored Hash.Init would go like this:

public static IDictionary Init(params Func<object, object>[] funcs)
{
  IDictionary values = new Hashtable(funcs.Length, StringComparer.OrdinalIgnoreCase);

  foreach (Func<object, object> func in funcs)
  {
    string key = func.Method.GetParameters()[0].Name;
    object value = func(null);
    values.Add(key, value);
  }

  return values;
}

That'll teach me for thinking I'm being innovative :)

A Better Dictionary Initializer

Collection initializers are one of the new language features for C# 3.0.  They are meant to give your wrists a break by allowing you to instantiate and populate a collection in one fell swoop.  ScottGu has a nice post that shows off the new syntax for Lists and Wriju shows you how to initialize a Dictionary.  The new syntax is nice but I think we can make a few improvements.  Dictionaries are heavily used in MonoRail/ASP.Net MVC for passing name/value pairs to functions.  One particular usage is to pass in additional attributes for methods that render html (class="text", size=15, title="Click Here", alt="[The Big Picture]", etc).  Let's take the following method:

public string TextBox(string name, object value, IDictionary attributes)
{
  // Generate html for an input[type=text] field
}

If we wanted to use this function using the Dictionary initializer syntax, we would end up with something like:

TextBox("name", string.Empty, new Hashtable() { { "class", "text" }, { "size", 15 } });

That is awfully verbose, especially for those who come from the land of dynamic languages like Ruby and Boo.  Let's see if we can do a little better using another new feature for C# 3.0: Anonymous Types.  Our code above turns into:

TextBox("name", string.Empty, new{ @class = "text", size = 15 });

This is quite an improvement.  We've eliminated nearly twenty characters and our wrists feel much better.  For this code to work we must add a TextBox overload:

public string TextBox(string name, object value, object attributes)
{
  return TextBox( name, value, Hash.Init( attributes ) );  
}

And a static Hash class with Init method:

public static IDictionary Init(object anonymous)
{
  IDictionary values = new Hashtable(StringComparer.OrdinalIgnoreCase);

  if (anonymous == null) return values;

  foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(anonymous))
  {
    values.Add(property.Name, property.GetValue(anonymous));
  }

  return values;
}

But this is nothing new you cry!  Rob Conery bespoke something similar earlier this month.  Let's see if we can do a little better using another new feature for C# 3.0: Lamda Expressions.  Our code above turns into:

TextBox("name", string.Empty, @class => "text", size => 15);

This is a slight improvement, only a savings of a three characters, but it has some sex appeal.  Your inner Rubyist is nodding with approval.  For this code to work we must add another TextBox overload:

public string TextBox(string name, object value, params Expression<Func<object, object>>[] expressions)
{
  return TextBox(name, value, Hash.Init(expressions));
}

And an overload to our Hash.Init:

public static IDictionary Init(params Expression<Func<object, object>>[] expressions)
{
  IDictionary values = new Hashtable(expressions.Length, StringComparer.OrdinalIgnoreCase);

  foreach (Expression<Func<object, object>> expression in expressions)
  {
    string key = expression.Parameters[0].Name;
    Func<object, object> function = expression.Compile();
    object value = function(null);
    values.Add(key, value);
  }

  return values;
}

Pretty sweet and only a little bit of voodoo.  Proponents of lambda expressions say it makes your code more readable.  Whether or not that's the case, I think in this example the code is more expressive and saves you some typing.  Now, go refactor all of your IDictionary parameters :)

ASP.Net MVC is Easier to Test than Model-View-Presenter

David Hayden's experience leads him to believe that Model-View-Presenter Seems Easier to Test Than ASP.NET MVC.  He asks for some insight from the inter-web to help him see the light.  He uses the following example to highlight the simplicity of testing MVP:

[Test]
public void EmptyCustomerNameShouldCauseInvalidCustomerMessage()
{
MockRepository mocks = new MockRepository();

IAddCustomerView mockView = mocks.CreateMock<IAddCustomerView>();
AddCustomerPresenter presenter = new AddCustomerPresenter(mockView);

Expect.Call(mockView.CustomerName).Return(string.Empty);
Expect.Call(mockView.CustomerTitle).Return("Jester");
Expect.Call(mockView.PhoneNumber).Return("555-1212");
mockView.Message = "Invalid Customer...";

mocks.ReplayAll();
presenter.onAddCustomer();
mocks.VerifyAll();
}

Here is the same unit test using MVC:

[Test]
public void EmptyCustomerNameShouldCauseInvalidCustomerMessage()
{
CustomerController controller = new CustomerController();

controller.Add(string.Empty, "Jester", "555-1212");

Assert.IsTrue(controller.ViewData.Contains("message"));
Assert.AreEqual("Invalid Customer...", controller.ViewData["message"]);
}

I hope this helps contrast the two approaches.  I will leave it up to you to decide which is simpler.

On the Extensibility of ASP.Net MVC

Much of the early hype surrounding the ASP.Net MVC framework revolved around the ability to use your dependency injection/inversion of control container of choice for resolving controllers at runtime.  The MvcContrib project already has implementations for Windsor, Spring, and StructureMap with ObjectBuilder soon to follow.  The framework also allows developers to use view rendering technologies other than the built in WebForms ViewPage.  The MvcContrib project already has an NVelocity view renderer thanks to Hammett.  I'm writing this post to try and influence, Scott, Phil, Rob, and Eilon to take the extensibility to the next level. 

What I am proposing is nothing radical and adds less than 10 lines of code to the existing implementation.  This is the right time to throw out suggestions since this is only the first CTP and there are areas that are obviously 'under construction.'  Even with all of the extensible points of the framework, I still see an awful lot of Activator.CreateInstance littered throughout the code.  Take the IControllerFactory for instance.  This is hailed as an extensibility point allowing you to supply your own implementation and thus have control over the creation of controllers.  It does deliver on its promise however, the framework instantiates a controller factory per request.  What if I want to reuse a controller factory?  Or what if my controller factory has dependencies on other classes or logic?  Why not let me, the developer, be in charge of providing you with an IControllerFactory when you need one?  But how, you ask, can this be achieved without disrupting the space-time continuum?  It's actually much simpler than you think.

The changes I propose affect HttpContextWrapper2.  You know this is a work in progress because (I seriously hope) Microsoft would not ship a class with that name (MvcContext maybe?).  As an aside, whatever you guys finally choose can you please not make it internal sealed?  Is that really necessary?  But I digress.  So here are my changes to HttpContextWrapper2:

Before:

object IServiceProvider.GetService(Type serviceType)
{
  return ((IServiceProvider) this._context).GetService(serviceType);
}

After:

object IServiceProvider.GetService(Type serviceType)
{
  IServiceProvider provider = this.ApplicationInstance as IServiceProvider;
  if( provider != null )
  {
    object service = provider.GetService(serviceType);
    if( service != null )
    {
      return service;
    }
  }

  return ((IServiceProvider)this._context).GetService(serviceType);
}

As promised, a very simple change to the existing implementation.  But what did we gain?  Well, we now give the ApplicationInstance a crack at providing the requested type, rather than just redirecting to the underlying HttpContext.  What is the ApplicationInstance?  In your run of the mill web application, this is the class housed in Global.asax.cs.  So, with the code snippet below, we could use the Windsor container as the service provider:

public class Global : HttpApplication, IServiceProvider
{
  private static WindsorContainer _container;

  public object GetService(Type serviceType)
  {
    if( _container.Kernel.HasComponent(serviceType) )
    {
      return _container.GetService(serviceType);
    }

    return null;
  }

  protected void Application_Start(object sender, EventArgs e)
  {
    // Initialize the container...
  }
}

Now the MVC framework can take advantage of the rich DI/IoC capabilities of Windsor (or any of the containers mentioned at the beginning of this article) without adding dependencies to it.  Just replace all of those Activator.CreateInstance(type) calls with context.GetService(type).  If the call to GetService returns null, then you can still resort to your own creation mechanisms.  But at least give us a chance to take control of the process if we so choose.

Unless I a missing something this should be a low impact, low risk modification to the existing framework with high rewards.

«May»
SunMonTueWedThuFriSat
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567