Search code examples
asp.net-mvcparentviewcontroller

Cannot resolve view of the parent controller


Create a controller:

public abstract class MyBaseController : Controller
{
   public ActionResult MyAction(string id)
   {
      return View();
   }
}

Than create another specific controller that inherit from MyBaseController:

public class MyController : MyBaseController 
{

}

There is a view called MyAction.aspx in the Views/MyBaseController folder Then, call MyController/MyAction method. Following exception will be generated:

The view 'MyAction' or its master could not be found. The following locations were searched: ~/Views/MyController/MyAction.aspx ~/Views/MyController/MyAction.ascx ~/Views/Shared/MyAction.aspx ~/Views/Shared/MyAction.ascx

Can I make MVC.NET to use the view from Views/MyBaseController folder?


Solution

  • you should wait for a more finesse answer but this work:

    Create a new view engine based on the default one and override the FindViewMethod this way:

    
     public class MyNewViewEngine : WebFormViewEngine
     {
         public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
         {
            var type = controllerContext.Controller.GetType();
    
                //Retrieve all the applicable views.
                var applicableViews = from m in type.GetMethods()
                                      where typeof(ActionResult).IsAssignableFrom(m.ReturnType) & m.Name == viewName
                                      select m;
    
                //Save the original location formats.
                var cacheLocations = ViewLocationFormats;
                var tempLocations = cacheLocations.ToList();
    
                //Iterate over applicable views and check if they have been declared in the given controller.
                foreach(var view in applicableViews)
                {
                    //If not, add a new format location to the ones at the default engine.
                    if (view.DeclaringType != type)
                    {
                        var newLocation = "~/Views/" + view.DeclaringType.Name.Substring(0, view.DeclaringType.Name.LastIndexOf("Controller")) + "/{0}.aspx";
                        if (!tempLocations.Contains(newLocation))
                            tempLocations.Add(newLocation);
                    }
                }
    
                //Change the location formats.
                ViewLocationFormats = tempLocations.ToArray();
    
                //Redirected to the default implementation
                var result = base.FindView(controllerContext, viewName, masterName, useCache);
    
                //Restore the location formats
                ViewLocationFormats = cacheLocations;
    
                return result;
       }
    }
    

    Add the new view engine:

    
     public class MvcApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
                ViewEngines.Engines.Clear();
                ViewEngines.Engines.Add(new MyNewViewEngine());
                RegisterRoutes(RouteTable.Routes);
            }
        }
    

    hope this helps