2009-04-10 102 views
2

我想在asp.net mvc中拥有多个控制器和相同对象/模型的视图,但事实证明这比我预期的有点复杂。控制器和视图中的子文件夹

基本上就是我想要做的是这样的:

 
site.com/product 
    -> will show product details to visitors. 

site.com/admin/product 
    -> will show some extra information together with product details. 
     and some commands like delete, edit etc. 

的目标是单独为游客和管理员的URL。

我的第一种方法是,我想创建控制器和视图文件夹的子文件夹,这样的事情会这样看:

 
> Controllers 
    > Admin 
     ProductController.cs 
    ProductController.cs 
> Views 
    > Admin 
     > Product 
      Index.aspx 
    > Product 
     Index.aspx 

我的URL到正确的控制器映射没有问题(只要我指定他们的名字空间,因为类名是相同的)。 但是,当我从管理文件夹下的控制器返回视图时,它不会在视图/管理员/产品文件夹下显示索引视图,而是在视图/产品下显示该视图。

我知道我可以说return View("Full path here")返回我想要的视图。但这显然不是一个好的解决方案,我不想那样做。

我的问题是,处理这种情况的最佳方法是什么,并且网址的条件必须是这样吗?

  • 创建一个覆盖视图方法(或需要被重写此目的的任何其他的),并确保返回正确的视图定制的控制器类?

    • 这是一个丑陋的黑客,但会工作。
  • 创建一个自定义视图引擎,同时考虑文件夹?

    • 我并不确切地知道我能做到这一点,但据我了解,这也应该解决的问题
  • 使用Phil HaackAreas Prototype

    • 这一个实际上使用不同的文件夹布局,但理论上这也应该工作。但我仍然不确定这是否是最好的方法,因为在网站的不同部分下有不同的控制器视图文件夹并不完全是我想要的。

我倾向于自定义视图引擎的想法,当返回的意见,即需要的文件夹考虑,但就像我说的,我不知道该怎么做。

有什么建议吗?

回答

1

ASP.Net MVC默认使用的扁平浏览文件夹结构。尽管他们只给你一个更高的水平,地区可以在一定程度上有所帮助!

这可以使控制器深层嵌套层次结构的视图难以管理。你真正想要的是你的Views文件夹层次结构与控制器的命名空间层次结构相匹配。

好消息是,你可以写一个自定义视图引擎具有令人惊讶的一点努力做到这一点 - 看到我ControllerPathViewEngine project on GitHub了解详情。

我已经包含ControllerPathRazorViewEngine类的一个片段来概述它是如何工作的。通过拦截FindView/FindPartialView方法并用文件夹路径(基于控制器名称空间和名称)替换控制器名称,我们可以从主要Views文件夹中的嵌套文件夹中加载视图。

public class ControllerPathRazorViewEngine : RazorViewEngine 
    { 
     //... constructors etc. 

     public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) 
     { 
      return FindUsingControllerPath(controllerContext,() => base.FindView(controllerContext, viewName, masterName, useCache)); 
     } 

     public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) 
     { 
      return FindUsingControllerPath(controllerContext,() => base.FindPartialView(controllerContext, partialViewName, useCache)); 
     } 

     private ViewEngineResult FindUsingControllerPath(ControllerContext controllerContext, Func<ViewEngineResult> func) 
     { 
      string controllerName = controllerContext.RouteData.GetRequiredString("controller"); 
      string controllerPath = controllerPathResolver.GetPath(controllerContext.Controller.GetType()); 
      controllerContext.RouteData.Values["controller"] = controllerPath; 
      var result = func(); 
      controllerContext.RouteData.Values["controller"] = controllerName; 
      return result; 
     } 
    } 
相关问题