In continuing to explore and document the cool new features of ASP.NET 5 and MVC 6, I stumbled across an interesting question from my friend Josh on Slack: how do I customize the razor view engine in ASP.NET 5 so that I can rename that Shared folder to _Shared? I knew I had seen this feature somewhere before and started digging.
The reasoning behind this change is quite simple, and one that I’m ashamed wasn’t implemented in the default templates: Shared is a “magic folder” that all Views in an MVC project can reference contents out of. As such, it should have special placement or be easy to find in the solution explorer. The simple solution is to prefix Shared with an underscore so that it is always at the top of the folder list. Brilliant!
In previous versions of ASP.NET MVC, we could subclass the RazorViewEngine to make it do tricky things with determining where and how to find and implement view files. Fun, but that’s just too complicated for just wanting to rename a folder. I want to find a simple configuration option that I can set to update the behavior of the view engine.
Introducing the IViewLocationExpander
In MVC 6, there is a new interface available called IViewLocationExpander that contains two methods to help define how the Razor view engine will locate and cache the view files that it finds. There are two methods in this interface that are trivial to implement:
- PopulateValues – this method is passed the context of the current view location when a view is requested. You can modify the context or add values appropriately to indicate if there is a change since the last time the view was requested.
- ExpandViewLocations – this method is called when the RazorViewEngine wants to determine the list of potential locations for a view. The second argument on this method is the list of current paths that will be searched for views.
That’s all I need to make my quick swap / rename of the Shared folder. I wrote a simple class to do this remapping for me:
That’s a very standardLinq select statement to do a string replace. The code to add this to our ASP.NET pipeline is easy, andcan be done with some dependency injection trickery in the Startup.ConfigureServices class:
Sweet… now MVC will look in all of the standard locations, and because I added this ViewLocationExpander to the collection it will update the existing view locations without disturbing them. I could have cleared and added just this one Expander with a whole different set of locations to search, but that would be a bit of overkill for this problem I wanted to solve.
A simple rename of a magic folder can be accomplished by adding configuration to MVC. Not bad, and something that was handled with a new configuration option in the ASP.NET pipeline. Big thanks to Imran Baloch whose blog post on ViewLocationExpanders answered some of my questions about how to implement this feature.