Question

I have only tried this in single project areas. So if anyone tries this in a multi-project areas solution please let us know.

Area support was added to MVC2. However the views for your controllers have to be in your main Views folder. The solution I present here will allow you to keep your area specific views in each area. If your project is structured like below, with Blog being an area.

+ Areas          <-- folder
  + Blog         <-- folder
    + Views      <-- folder
      + Shared   <-- folder
      Index.aspx
      Create.aspx
      Edit.aspx
+ Content
+ Controllers
...
ViewEngine.cs

Add this code to the Application_Start method in Global.asax.cs. It will clear your current view engines and use our new ViewEngine instead.

// Area Aware View Engine
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new AreaViewEngine());

Then create a file named ViewEngine.cs and add the code below.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;

namespace MyNamespace
{

    public class AreaViewEngine : WebFormViewEngine
    {
        public AreaViewEngine()
        {
            // {0} = View name
            // {1} = Controller name

            // Master Page locations
            MasterLocationFormats = new[] { "~/Views/{1}/{0}.master"
                                          , "~/Views/Shared/{0}.master"
                                          };

            // View locations
            ViewLocationFormats = new[] { "~/Views/{1}/{0}.aspx"
                                        , "~/Views/{1}/{0}.ascx"
                                        , "~/Views/Shared/{0}.aspx"
                                        , "~/Views/Shared/{0}.ascx"
                                        , "~/Areas/{1}/Views/{0}.aspx"
                                        , "~/Areas/{1}/Views/{0}.ascx"
                                        , "~/Areas/{1}/Views/Shared/{0}.aspx"
                                        , "~/Areas/{1}/Views/Shared/{0}.ascx"
                                        };

            // Partial view locations
            PartialViewLocationFormats = ViewLocationFormats;

        }

        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            return new WebFormView(partialPath, null);
        }

        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {
            return new WebFormView(viewPath, masterPath);
        }

    }   // End Class AreaViewEngine

}       // End Namespace    

This will find and use the views you have created in your areas.

This is one possible solution that allows me to keep views in the specified area. Does anyone else have a different, better, enhanced solution?

Thanks

Was it helpful?

Solution 2

This solution works well in Mvc2. It is not necessary in Mvc3.

OTHER TIPS

I'm sorry to be the one to tell you this, but you must be missing something. I currently have your scenario working out of the box with ASP.NET MVC 2 RC.

I assume you have all the register routes and have the correct web.config files inside your area's view folder?

Maybe have a look at this walk through, especially the part about creating the areas.

HTHs,
Charles

EDIT: Ok, so you're not happy about putting in the extra new { area = "blog' }, null - fair enough, I'll admit its niggly... but what else are you going to do?

What happens when you have two controllers with the same name? One in your root project and one in an area or two controllers with the same name in two different areas? How is it going to find the correct view?

Also, I do see a problem with your ViewLocationFormats. All of the area view locations have no reference to their area... e.g. ~/Areas/{1}/Views/{0}.ascx - how does it know what area?

If you are suggesting that all the different area's views and all thrown into the Areas folder under their controller name and then found under Views and Views/Shared - I would highly recommend against that... It'll become a mess very quickly.

So where does that leave you? It really leaves you needing to specify the area when creating the route. It really boils down to the fact that although it's niggly having to specify the area, there really is no other way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top