Search code examples
c#asp.net-mvcasp.net-mvc-5asp.net-mvc-routingasp.net-mvc-areas

Adding a sub-folder under Area and configuring View Engine to search the views in the sub-folder


I am working on an e-commerce website. The website connects to several 3rd party applications, such as Shopify. I have created an Area for this purpose and called B2b (business to business)...

I want to create a sub-folder for each of these 3rd parties under B2b Area, so this is how the folder structure looks like:

enter image description here

Note that OrganisationController is common to all 3rd parties, so I have not put it in any sub-folder.

This is my Area Registration Code:

public class B2bAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get { return "B2b"; }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "Shopify_default",
            "B2b/Shopify/{controller}/{action}/{id}",
            new { controller = "Dashboard", action = "DisplayProducts", id = UrlParameter.Optional },
            new[] { "e-commerce.Web.Areas.B2b.Controllers.Shopify" }
        );

        context.MapRoute(
            "B2b_default",
            "B2b/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional }
        );
    }
}

Now if I try the following URL:

https://localhost:44339/b2b/shopify/setup/install?shop=some-name

It would hit the correct controller:

[HttpGet]
public ActionResult Install(string shop)
{
    var myViewModel = new MyViewModel(shop);
    return View(myViewModel);
}

But the view engine is not able to find the correct view, this is the error that I get:

enter image description here

As you can notice, the View Engine is not searching the Shopify sub-folder. I assume I can fix this issue by returning the path for the view, but I was wondering if there is a more elegant solution for this?


Solution

  • I solved the issue with the help of this tutorial

    I created a customized Razor View Engine:

    public class ExpandedViewEngine : RazorViewEngine
    {
        public ExpandedViewEngine()
        {
            var thirdPartySubfolders = new[] 
            {
                "~/Areas/B2b/Views/Shopify/{1}/{0}.cshtml"
            };
    
            ViewLocationFormats = ViewLocationFormats.Union(thirdPartySubfolders).ToArray();
    
            // use the following if you want to extend the partial locations
            // PartialViewLocationFormats = PartialViewLocationFormats.Union(new[] { "new partial location" }).ToArray();
    
            // use the following if you want to extend the master locations
            // MasterLocationFormats = MasterLocationFormats.Union(new[] { "new master location" }).ToArray();   
        }
    }
    

    And configured the website to use the above view engine in Global.asax:

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            ViewEngines.Engines.Add(new ExpandedViewEngine());
            AreaRegistration.RegisterAllAreas();
    
            // more configuratins...     
        }
    }