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 ViewLocationFormats and PartialViewLocationFormats are declared the same:

~/Views/{1}/{0}.aspx

~/Views/{1}/{0}.ascx

~/Views/Shared/{0}.aspx

~/Views/Shared/{0}.ascx

In other words, for the Index action on the Home controller, the following paths are searched:
~/Views/Home/Index.aspx

~/Views/Home/Index.ascx

~/Views/Shared/Index.aspx

~/Views/Shared/Index.ascx

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 Search controller with an Items action:
~/Views/Search/Items.aspx

    (the view page for the Items action)

~/Views/Home/Index.ascx

    (possibly an items partial view customized just for this controller/action)

~/Views/Shared/Items.ascx

    (the shared partial view to render items in many controllers/actions/views)

This is where the problems start. By default, a call to RenderPartial("Items") within the Items.aspx page is going to find the Items.aspx file 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 ViewLocationFormats and PartialViewLocationFormats. I my case I decided to force the issue explicitly. ViewLocationFormats only looks for aspx files and PartialViewLocationFormats only look for ascx files. Now we can override shared partial views locally in controller folders without worrying about name collisions.

See more posts about: All Categories