Poor Man's Shards in NHibernate

Another loosely coupled post on Going to Production with MonoRail.

One thing I haven't stressed in recent posts is the absolute necessity to thoroughly test and understand the implications of your modifications when you start pushing a framework outside of the box.  In my post on Advanced Dependency Injection with Castle Windsor I lightly touched on the lifestyle implications of my patch to the code.  The same warning covers today's post when we start jimmy jacking with a custom connection provider in NHibernate.

If you've been following along you know that for various reasons we host multiple clients on a single instance of our B2B web application.  For other various reasons we like to keep the data for each client segregated into separate databases.  We use NHibernate for persistence ignorance so that seemed to be the logical place to start when attempting to segregate client data.  When I was doing my research it became apparent that at a high level I was trying to implement a horizontally partitioned database.  In my case, partitioned by client.  Hibernate supports horizontal database partitioning through ShardsDario Quintana is in the process of porting Shards to NHibernate, but I don't believe it is quite ripe yet.  Shards appears to address all of the nuances and edge cases that would reveal themselves when attempting to logically split data.  My needs were much cruder and I was willing to sacrifice a fully functional implementation (see first paragraph above though).  

Each client hosted in our application has their own configuration file.  Within this file is a database connection string that points to the database for the particular client.  As long as the database structure of each database is identical, NHibernate is cool with that.  What I ended up implementing is a custom IConnectionProvider that would load the current client's configuration, read the connection string, and create a connection using that, rather than the connection string that would normally be read from your hibernate.cfg.xml file.  The sample code gets the job done.

namespace My.Application
{
  public class ClientConfigurationConnectionProvider : DriverConnectionProvider
  {
    public override IDbConnection GetConnection()
    {
      string clientId = ClientIdProvider.Get();

      if (null == clientId)
      {
        return base.GetConnection();
      }

      ClientConfiguration clientConfiguration = ClientConfigurationManager.GetByClientId(clientId);
      string dbConnectionString = clientConfiguration.DbConnectionString;
      if (string.IsNullOrEmpty(dbConnectionString))
      {
        return base.GetConnection();
      }

      IDbConnection conn = Driver.CreateConnection();
      conn.ConnectionString = dbConnectionString;
      conn.Open();
      return conn;
    }
  }
}

Very straight forward.  By inheriting from the built in DriverConnectionProvider, most of the hard work is done for us.  To tell NHibernate to use our connection provider, a small change to the configuration file is required:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <!-- <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property> -->
    <property name="connection.provider">My.Application.ClientConfigurationConnectionProvider, My.Application</property>
    <property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
    <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <property name="connection.connection_string">Server=(local);Database=MyApplication;Trusted_Connection=True;</property>
    <property name="show_sql">true</property>
    <mapping assembly="My.Application" />
  </session-factory>
</hibernate-configuration>

Remember what I said though, depending on your database structure, and the features of NHibernate you choose to take advantage of, bad and unexpected things could happen with this implementation, so do your testing.

Runtime Dynamic Actions in MonoRail with Windsor

Another loosely coupled post on Going to Production with MonoRail.

The ability to customize every aspect of an application Lego style is great, but there will always be client needs that are absolutely off the wall.  Not a customization of an existing component, but something so specific and unique to the client's domain that it cannot be encapsulated into something reusable.  My mind struggled with the paradox, how do I architect the ability to insert non-reusable functionality in a reusable way?  Mike Nichols put me on the path to my solution.

Dynamic Actions are a feature of MonoRail that allow you to decouple an action from a controller.  This sounds pretty simple but when you read through the documentation and the many ways that developers are putting them into practice, Dynamic Actions reveal their true power.  The first part of my solution: completely custom functionality is simply implemented by a class that implements IDynamicAction.  Each piece of custom functionality corresponds to a dynamic action.  The next question is how do I expose this functionality to the Client?  How do I ensure that this functionality is only exposed to the Client that paid for it?

I haven't yet posted about how we manage configuration for each client, but essentially we have an INI file (cringe! gasp! moan!) for each client hosted on a particular server.  A sample section of the INI file for the Contoso client would look like so:

[Actions]
DoWork=ContosoDoWorkAction
DoWork2=ContosoDoWork2Action

The key (DoWork) represents the name of the action, the value (ContosoDoWorkAction) is the name of a class that implements IDynamicAction and the logic for the custom functionality required by the client.  Actions are loaded into the child container for the Client during application startup.  Now we need a controller that we can attach these actions to at runtime.  This is achieved using the code sample below:

namespace My.Application
{
public class CustomController : Controller
{
public CustomController(IKernel kernel)
{
ClientConfiguration clientConfig = ClientConfigurationManager.GetCurrent();

NameValueCollection actions = clientConfig.Actions;

foreach (string actionName in actions.AllKeys)
{
string actionTypeName = actions[actionName];
Type actionType = Utility.GetImplType(actionTypeName);
DynamicActions[actionName] = (IDynamicAction)kernel.Resolve(actionType);
}
}
}
}

So simple it should be criminal.  With the configuration sample above and the CustomController implementation, we now have valid URLs of:

https://contoso.myb2bapplication.com/custom/DoWork.rails

https://contoso.myb2bapplication.com/custom/DoWork2.rails

At the same time, by the nature of our child container configuration magic, the following URLs would be invalid:

https://fabrikam.myb2bapplication.com/custom/DoWork.rails

https://fabrikam.myb2bapplication.com/custom/DoWork2.rails

This is because the actions are only available to the client for which they were configured.  By the same token I can disable an action by commenting out the line in the configuration file.

Who's your daddy paradox?

Advanced Dependency Injection with Castle Windsor

Another loosely coupled post on Going to Production with MonoRail.

Many moons ago I wrote a post about dynamically resolving a component from the Castle container based on runtime parameters.  There was some discussion about the limitations of the approach (the biggest is that all components that require customization or components that have dependencies that require customization must be Transient) but overall it accomplished my goals at the time.  To summarize, my implementation allowed you to load multiple components that implement the same service (say an IOrderValidator) and also allowed you to provided a predicate that would be invoked when your code resolved an IOrderValidator to allow you to choose which specific implementation to return.  The idea was that you could have multiple clients hosted on a single instance of your application, each requiring their own order validation logic.  Using a runtime parameter (like the host header) your provided predicate would resolve the IOrderValidator associated with the particular client's requirements.  This implementation worked for some time but had a few limitations, namely all components for all clients had to be loaded into the same container.  This ended up being a tad unruly to manage.  There were also some limitations on the order in which components were loaded into the container, which was problematic when auto configuring the container via code or something like Binsor.

I set out for a better solution that addressed my new requirements and ran into the related issue of scoped containers that had been proposed on the Castle mailing lists.  Scoped containers have a slightly different use case and requirements but overlapped some with the approach I ultimately settled upon.  My container contains over thirty (30) components that make up the core functionality of the application.  Some of these components have dependencies on other components and all of this management, injection, and resolution is handled nicely and elegantly by the container.  Lets say for a particular client I need to customize one of the these components.  But the component in question has dependencies on three other components, whose functionality I do not need to customize.  I need a way to add my customized component to the container, but still resolve its dependencies from the core set of components.  The answer to my problem came in the form of Child Containers.

A child container is just like your standard container only that it has an associated parent.  When you try to resolve a component from a child container, it looks at its own components to fulfil dependencies and if it doesn't find it, it asks the parent container if it can fulfil the dependency.  This sounds like just the solution I needed.  I can load all of my core components into the parent container, then load any custom components into a child container.  One glaring flaw though.  Lets say I have component A that has a dependency on component B.  I have a core implementation of both components in my parent container.  I have a custom implementation of component B in my child container.  I attempt to resolve component A from the child container.  It is not present so it is retrieved from the parent container.  When resolving the dependency of component B, the parent uses the core implementation, not the custom implementation in the child container.  I considered this a bug in the dependency resolution code and you can read about the ensuing discussion on the Castle mailing list.  This issue was also reported by Rinat Adbullin a few months back and prompted him to choose another container implementation.  I submitted a patch for my implementation but as far as I know it has not been applied.  I've heard Hammett say that child containers are the devil (my words, not his) I believe because they can introduce difficult to diagnose bugs and make dependency resolution more complicated.  For my problem they have provided an elegant solution.

To bring this implementation into MonoRail was simply a matter of crafting a custom HttpApplication that implements IContainerAccessor, and returning the appropriate child container based on the host header of the current request.  I have the base container that contains all of the core components.  I create a child container with the base as its parent for each client and load the appropriate components.  MonoRail can be configured to use Windsor to resolve all of its internal components (including your controllers).  MonoRail calls IContainerAccessor.Container to obtain the container to use for its resolution.  By providing the appropriate child container to this call, I can ensure that any custom components for the particular client are used in place of the core components.  By using the dependency resolution patch discussed above, I ensure that any core component dependencies are properly resolved against any existing customized components in the child container (code sample below).

To sweeten the deal, child containers are configured using a simple text file that can be modified at runtime to turn individual custom components on or off on a per client basis, without restarting the application.  More on that in my future post on managing configuration.

namespace My.Application
{
  public class CustomHttpApplication : HttpApplication, IContainerAccessor
  {
    private static IWindsorContainer _baseContainer;

    private static readonly Hashtable _configToContainer = new Hashtable();

    protected virtual void Application_Start(object sender, EventArgs e)
    {
      _baseContainer = new CustomContainer();
    }

    public IWindsorContainer Container
    {
      get { return GetContainer(); }
    }

    protected virtual IWindsorContainer GetContainer()
    {
      string clientId = ClientIdProvider.Get();

      if (string.IsNullOrEmpty(clientId))
      {
        return _baseContainer;
      }

      ClientConfiguration clientConfig = ClientConfigurationManager.GetByClientId(clientId);

      IWindsorContainer clientContainer = null;

      if (!_configToContainer.ContainsKey(clientConfig.Path))
      {
        clientContainer = new CustomContainer(clientConfig, clientId, _baseContainer);
        _configToContainer.Add(clientConfig.Path, clientContainer);
      }
      else
      {
        clientContainer = (IWindsorContainer)_configToContainer[clientConfig.Path];
      }

      return clientContainer;
    }
  }
}

Going to Production with MonoRail

We went to production with our B2B e-commerce product going on three months ago.  I've waited this long to write anything about it because I wanted to include in my documentation the process we used to address bugs we found after we went to the field as well as all of the interesting nooks and crannies of the architecture, what worked, what didn't, what I will do again, what I will be changing through careful refactoring, etc.  Over the next few weeks look for posts covering in some detail the topics outlined here.

Setting the Stage

This is a small application written by myself and one other dev over the course of three months.  This is not a COTS product nor is it written for a single client.  Our application provides a hosted set of core "out of the box" functionality that can facility B2B e-commerce as is, but all of our customers require some amount of customization.  When I said small, I meant small.  We average six (6) requests per second during business hours and spike to about forty (40) requests per second during peak times (moving the mouse on the server causes more CPU utilization than than the app itself :) The core application is only forty-three (43) models, six (6) controllers, forty-two (42) actions (including overloads), nineteen (19) views, and twenty-seven (27) services.  We integrate with five (5) third parties for things like credit card authorization and capture, real time shipping quotes, inventory availability, customer profile management, and order fulfillment.  We use a private build of  MonoRail RC3 with Windsor integration and Helen Keller's view engine of choice.  We use NHibernate 2 wrapped with Rhino Commons for persistence and log4net for all our logging needs.  This was a legacy application that has been in production for approximately four (4) years that originated as a classic ASP application, was ported to ASP.Net 2.0 Web Forms, then was refactored to a home grown ASP.Net 2.0 MVP framework, and is now in its current incarnation.

High Level Overview

I will be talking in volumes about the ability to customize nearly every aspect of our small application.  The reason is because all of our customers need the ability to receive an order from an end user, perform some sort of validation on the order information, then feed that order into their order fulfillment system.  The problem is that every customer has a slightly different take on end user, validation, and fulfillment system :)  Rather than write separate products for each customer or make a branch of the code for each customer we sign, our goal was to provide a core application that can be kept current, with new core features added as time goes on, and still allow any level of customization a specific customer requires.  This could be anything from re-arranging user interface elements on one or more screens, to making email address an optional field, to authorizing a credit card, but not capturing it, to feeding an order into SAP or into a legacy AS/400 order system via custom web services.  Some customizations become configuration options in the next release of the core product.  Others are so far out there they they will always remain customizations.  We also have the rare customer that happily uses the core product as is.  This model allows us to provide a tiered customization path: configuration changes can be made by operations monkey, view customizations can by made by any html monkey, and service customizations can be made by any code monkey (that's me).  So rather than giving our customer the brush off of "we will look at incorporating that in our next version", they flash us the cash and we do the deed, without affecting or breaking the core product or any other hosted customers.

The Highlights

Here are the topics I plan to touch on in no particular order.  Some will be brief others might span a few posts.  As I write the posts I will come back here and update the links and I might add other topics as I think of them.

  • Managing Configuration - Me: "Check out this new feature in v5", Marketing: "That's configurable right?"
  • Managing Customization - Marketing: "Customer wants to sell stuff without displaying prices", Me: "Ha ha, good one.  No...you're serious?...seriously?...are you kidding me?...are your f***king kidding me!"
  • Post Production - Patching, hot fixing, and tracking down bugs
  • NHibernate Tricks - Poor Man's Shards
  • Windsor Tricks - My Golden Swiss Army Knife
  • Layout Tricks - Handling Popup Windows, Sidebars, and Error Notification
  • jQuery Tricks - How do I love thee? Let me count the ways.
  • Brail Tricks - I have an Orange Belt in Quack Fu

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.

«July»
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789