【问题标题】:Multiple controllers, same same controller name多个控制器,相同的控制器名称
【发布时间】:2016-01-28 22:49:55
【问题描述】:

我想知道这是否可能。假设我有一个单片控制器 ReportController.cs。

我想制作一个完全独立的控制器文件,但仍将 /Report/ 保留在我们需要了解和期望的 url 中。

我尝试的是在我的全局 asax 中这样做:

routes.MapRoute(
    "Testing", // Route name
    "{test}/{action}/{id}" // URL with parameters
);

我添加了一个名为 ReportTest.cs 的新控制器

原来的路线是这样的:

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "LandingPage", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

每次我尝试调用 ReportTest.cs 中的简单操作时都会收到此错误:“值不能为空或为空。参数名称:控制器名称”

我是否误解了它的工作原理。当您拥有“{controller}/..”时,这不是说“查找任何名为 + 控制器的控制器并使用它”。所以如果我去 .../Report/DoStuff 它会在 ReportController 上寻找方法 DoStuff 对吗?

那么我的其他路线不会只是附加一个搜索序列吗?所以如果我把 .../Report/DoStuff 它会在 ReportController 和 ReportTest 上寻找方法 DoStuff 对吗?

【问题讨论】:

  • 部分课程会起作用吗?
  • 不,部分类有帮助,但智能感知和重构方法在所有这些代码的重压下仍然会挣扎。离开是为了获得非常非常糟糕的开发体验。
  • @CodeCaster 如果他使用部分控制器类,他可以分解他的代码,这样它就不会全部放在一个巨大的文件中。那不行吗?
  • 有许多不同的潜在方法,具体取决于此处需要进行的重构。部分类是其中之一(尽管“在所有代码的重压下挣扎”真的让我想知道这个代码库是什么样的......)。也许属性路由是一种选择?然后全局路由和控制器名称就不再是什么问题了,您可以随意命名您的控制器类并在各个属性中定义路由。
  • @Josh 这更有意义。您的第一条评论缺乏背景。

标签: c# asp.net asp.net-mvc asp.net-mvc-4


【解决方案1】:

路由格式字符串:

{controller}/{action}/{id}

意思是:请求URI的第一部分(“part”为“在/上拆分后的元素”)是控制器名称,下一部分是操作方法,最后一部分是ID。

占位符{controller}{action} 是特殊的。因此,您的路线 {test}/{action}/{id} 将找不到任何控制器,因为没有指定任何控制器,并且 {test} 没有任何意义。 (确实如此,它将被添加为名为“test”的路由属性,并分配一个代表请求 URI 部分的值,因此与此场景无关)。

如果要将 URI 路由到 URI 中未提及的控制器,则必须逐字指定前缀,以及它应该路由到的控制器。

所以您的路由将如下所示:

routes.MapRoute(
    "SecondReportController", 
    "Report/NotOnReportController/{id}",
    new { controller = "NotAReportController" }
);

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "LandingPage", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

那么你就可以使用下面的控制器了:

public class NotAReportController : Controller
{
    public ActionResult NotOnReportController(int id)
    {
        // ...
    }
}

你当然也可以使用属性路由:

public class NotAReportController : Controller
{
    [Route("Report/NotOnReportController/{id}")]
    public ActionResult NotOnReportController(int id)
    {
        // ...
    }
}

【讨论】:

  • 这可行,但每个控制器方法的新路由条目似乎不是一个好主意:(
  • 同一路由上的多个控制器似乎也不是一个好主意。请记住,控制器只是将 URI 与逻辑联系起来,并将执行此逻辑的结果呈现给视图的一种方式。这根本不意味着该逻辑应该在控制器中in。也许您可以通过将逻辑移动到业务对象中来清理胖控制器(无论如何这似乎是您的实际问题)。
  • 这是真的,但我只是想知道在我开始删除和移动之前,是否对控制器名称解析的工作方式进行了更好的控制。
  • 您拥有的唯一标识符是/Report/{action}。如果您有两个与此路由匹配的控制器,那么系统应该实例化哪个控制器来执行{action}?您当然可以创建自己的控制器工厂,使用反射或其他方式查找实现{action} 的控制器,但您真的,真的不想这样做。顺序是1)找到一个控制器类,2)找到动作方法。如果未找到 2,MVC 将不会返回到第 1 步。
  • “使用反射或其他什么,但你真的,真的不想那样做” 怎么会?反射是不是超级低效?
猜你喜欢
  • 2014-08-26
  • 2015-06-20
  • 1970-01-01
  • 1970-01-01
  • 2017-03-08
  • 2013-06-14
  • 2016-07-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多