【问题标题】:Subfolders in controllers and views控制器和视图中的子文件夹
【发布时间】:2009-04-10 00:22:00
【问题描述】:

我想在 asp.net mvc 中为同一个对象/模型拥有多个控制器和视图,但结果比我预期的要复杂一些。

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

site.com/product -> 将向访问者显示产品详细信息。 site.com/admin/product -> 将显示一些额外的信息以及产品详细信息。 以及一些命令,如删除、编辑等。

目标是将访问者和管理员的网址分开。

我的第一个方法是在控制器和视图文件夹中创建一个子文件夹,所以事情看起来是这样的:

> 控制器 > 管理员 产品控制器.cs 产品控制器.cs > 意见 > 管理员 > 产品 索引.aspx > 产品 索引.aspx

我可以毫无问题地将 url 映射到正确的控制器(前提是我指定了它们的命名空间,因为类名相同)。 但是,当我从 admin 文件夹下的 Controller 返回视图时,它不会显示 Views/Admin/Product 文件夹下的 Index 视图,而是 Views/Product 下的一个。

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

我的问题是,处理这种情况的最佳方法是什么,网址必须是这种情况?

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

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

    • 我不完全知道该怎么做,但据我了解,这也应该可以解决问题
  • 使用Areas Prototype 中的Phil Haack

    • 这个实际上使用了不同的文件夹布局,但理论上这也应该有效。但我仍然不确定这是否是最好的方法,因为在网站的不同部分下拥有不同的 Controller & View 文件夹并不是我想要的。

我倾向于自定义视图引擎的想法,在返回视图时会考虑文件夹,但就像我说的,我不知道该怎么做。

有什么建议吗?

【问题讨论】:

    标签: asp.net-mvc model-view-controller


    【解决方案1】:

    为您的 MVC 项目试用 Phil Haack 的 /Areas/:http://haacked.com/archive/2008/11/04/areas-in-aspnetmvc.aspx

    您将拥有正常内容的正常根目录,以及所有管理内容的特殊 /Areas/Admin/ 部分(并且 URL 将是 /admin/)。


    (来源:haacked.com

    【讨论】:

      【解决方案2】:

      ASP.Net MVC 默认使用平面视图文件夹结构。区域可以在一定程度上有所帮助,尽管它们只会让您多一层!

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

      好消息是,您可以轻松编写自定义 ViewEngine 来执行此操作 - 有关详细信息,请参阅我的 ControllerPathViewEngine project on GitHub

      我已经包含了 ControllerPathRazorViewEngine 类的 sn-p 来概述它的工作原理。通过拦截 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;
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-14
        • 2022-07-09
        • 2013-07-23
        • 1970-01-01
        • 2016-01-20
        • 1970-01-01
        • 2012-10-18
        • 1970-01-01
        相关资源
        最近更新 更多