2010-10-21 59 views
1

创建一个控制器:无法解析视图的父控制器

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

不是创造,从MyBaseController继承另一个特定的控制器:

public class MyController : MyBaseController 
{ 

} 

有一个名为MyAction.aspx在浏览视图/ MyBaseController文件夹 然后,调用MyController/MyAction方法。以下异常会产生:

视图“MyAction”或它的主人 找不到。下面 位置进行检索: 〜/查看/ myController的/ MyAction.aspx 〜/查看/ myController的/ MyAction.ascx 〜/查看/共享/ MyAction.aspx 〜/查看/共享/ MyAction.ascx

我可以让MVC.NET使用Views/MyBaseController文件夹中的视图吗?

回答

3

你应该等待更多的技巧答案,但这项工作:

创建基于默认的一个新视图引擎,并覆盖FindViewMethod这样:


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; 
    } 
} 

添加新的视图引擎:


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

希望这有助于

+0

无需子类化 - 您可以通过设置“ViewLocationFormats”来为现有View Engine上的Views设置搜索路径。 – bzlm 2010-10-21 17:26:03

+0

为什么downvote?该代码旨在用于每个抽象继承链,而不仅仅是一个硬编码的链。 – 2010-10-21 18:06:22

0

您需要将它添加到共享中,因为您处于子控制器的上下文中。如果你需要不同控制器的不同行为,那么你需要在每个子控制器视图文件夹中放置一个MyAction视图。

要回答你的问题,你可能会让它看起来在基本控制器文件夹,但它会要求你编写你自己的请求处理程序,它看起来在基本控制器文件夹。默认实现仅在当前控制器上下文的视图文件夹中查找,然后在共享文件夹中查找。这听起来像你的看法是共享的,所以共享文件夹似乎是一个好地方。

+0

感谢您的答复。我如何覆盖我的控制器的行为,以便在基本控制器文件夹中查找视图? – Egor4eg 2010-10-21 13:06:16

+1

@ Egor4eg:只需在现有的ViewEngine上设置ViewLocationFormats。 – bzlm 2010-10-21 17:28:02

0

这是可能的,但不是很干净。

public class MyController : MyBaseController 
{ 
    public ActionResult MyAction(string id) 
    { 
     return View("~/Views/MyBaseController/MyAction.aspx"); 
    } 
} 

但是,如果您的视图(MyAction.aspx)包含的局部视图参考,ASP.NET MVC将寻找它在浏览/文件夹myController的(而不是找到它!)。

如果您的视图是跨控制器共享的,最好按照NickLarsen的建议将其放置在Views/Shared文件夹中。