Tuesday, April 28, 2015

Change Areas folder convention to Plugins in ASP.Net MVC

ASP.Net MVC is mostly about convention. The controllers are inside Controller folder, cshtml files needs to be under views folder, the views are looked up from ActionResult by the action name etc...But whatever conventions are there, all those can be overridden. That is the beauty of MVC framework.

Recently we faced one scenario of overriding convention in one of the MVC projects. It uses MVC Areas to achieve plugin model. We deploy new plugins into the areas folder without recompiling the original framework web application. During one of the demo, there was a suggestion to rename the 'Areas' folder to 'Plugins' for better naming convention and readability. We tried to resist it as it adds unwanted code. But due to the pressure from leadership we decided to change it. It is good in one way that, we gets more chances to look inside the MVC framework.

Initially thought of having custom controller or ViewEngine. But after playing with MVC for some time, it became very easy as adding some lookup folder paths into RazorViewEngine. Files and folder hierarchy under the Plugins folder needs to be done manually. Right click and add area will not put new files into Plugins folder. Code below. The sub folder structure and files can be organized in side the Plugins folder in the same way how its seen in Area's folder.


        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AddPluginsFolderToAreaLocationFormatsOfRazorViewEngine();
        }

        private static void AddPluginsFolderToAreaLocationFormatsOfRazorViewEngine()
        {
            string[] PluginsLocationFormats = new string
                [] { "~/Plugins/{2}/Views/{1}/{0}.cshtml" };
            var razorEngine = ViewEngines.Engines.OfType<RazorViewEngine>().First();
            razorEngine.AreaMasterLocationFormats = 
                razorEngine.AreaMasterLocationFormats.Concat(PluginsLocationFormats).ToArray();
            razorEngine.AreaViewLocationFormats = 
                razorEngine.AreaViewLocationFormats.Concat(PluginsLocationFormats).ToArray();
        }


If anybody faces issues in getting this run, comment here. I can upload a sample MVC5 project.

http://theshravan.net/blog/configure-the-views-search-locations-in-asp-net-mvc/
http://stackoverflow.com/questions/632964/can-i-specify-a-custom-location-to-search-for-views-in-asp-net-mvc

No comments: