This post is about 60% fact and 40% opinion. Not a bad ratio. I’ve been working a lot in ASP.NET MVC lately building up a set of classes to be reused across multiple sites in the near future. A few of these legos are small view classes that inherit from
WebFormViewEngine. They all do small things, like adding additional file search paths, loading views from resources and fetching views from remote storage. Since you can stack view engines in
ViewEngines.Engines, you can add and number of these engines together to get the functionality you want on a site per site basis. First engine to claim it can service a view wins. Nothing special there really.
I stumbled across something today that seems obvious in retrospect that leads me to the opinion that the default view/partial view search patterns are broken. If you crack open Reflector.NET and point it towards
WebFormViewEngine, you’ll see that
PartialViewLocationFormats are declared the same:
In other words, for the
Indexaction on the
Homecontroller, the following paths are searched:
This all seems well and good until you happen to have a partial view that has the same name as an action that either happens to be shared, or the parti is being overridden in the local controllers folder. Here’s a somewhat plausible example: A
Searchcontroller with an
(the view page for the Items action)
(possibly an items partial view customized just for this controller/action)
(the shared partial view to render items in many controllers/actions/views)
This is where the problems start. By default, a call to
Items.aspxpage is going to find the
Items.aspxfile first and not the
Items.ascx. I’ve never ever seen anyone in the wild put partial views in an aspx file nor have I ever seen anyone put a full action view in an ascx file. So why on earth did they all them to be interchangeable in the location paths? Broken I say. Broken.
The good news is that it’s super easy to tweak these kinds of things in ASP.NET MVC. Inherit from
WebFormViewEngine and set your own
PartialViewLocationFormats. I my case I decided to force the issue explicitly.
ViewLocationFormats only looks for aspx files and
only look for ascx files. Now we can override shared partial views locally in controller folders without worrying about name collisions.