【问题标题】:Is it possible, in MVC3, to have the same controller name in different areas?在 MVC3 中,是否有可能在不同的区域拥有相同的控制器名称?
【发布时间】:2011-07-01 05:27:40
【问题描述】:

在 MVC3 中,我有以下几个方面:

  • 手机
  • 沙盒

然后我像这样路由地图:

    context.MapRoute(
        "Sandbox_default",
        "Sandbox/{controller}/{action}/{id}",
        new { controller = "SandboxHome", action = "Index", id = UrlParameter.Optional }

    context.MapRoute(
        "Mobile_default",
        "Mobile/{controller}/{action}/{id}",
        new { controller = "MobileHome", action = "Index", id = UrlParameter.Optional }
    );

问题是这会给出如下网址:

http://localhost:58784/Mobile/MobileHome

http://localhost:58784/Sandbox/SandboxHome

但我想要这样:

http://localhost:58784/Mobile/Home
http://localhost:58784/Sandbox/Home

问题是当我将 SandboxHome-Controller 重命名为 Home,将 MobileHome-Controller 重命名为 Home,这将提供所需的 URL,它不会编译,说它有两个 HomeController 类。

如何在不同的区域拥有相同的控制器名称?

【问题讨论】:

    标签: c# asp.net-mvc vb.net asp.net-mvc-3


    【解决方案1】:

    是的。

    正如这篇博文所述:http://haacked.com/archive/2010/01/12/ambiguous-controller-names.aspx

    假设您调用了 RegisterAllAreas 和 Visual Studio 生成的 AreaRegistration 文件。您需要做的只是全局 ASAX 中默认路由上的命名空间,以防止冲突。

    //Map routes for the main site. This specifies a namespace so that areas can have controllers with the same name
    routes.MapRoute(
            "Default",
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new[]{"MyProject.Web.Controllers"}
     );
    

    只要您将区域控制器保留在它们自己的命名空间中。这会起作用。

    【讨论】:

    • 但是...你将如何使用你的路由定义来翻译这个http://localhost:58784/Mobile/Home URL?我不认为你的答案是正确的。会是哪个区域?哪个控制器和哪个动作?
    • 这是 Global.asax 路由。一旦你指定了这个命名空间,你就可以不理会你的区域路线。我在我的应用程序中就是这样做的。
    • @Rob 是的,你是对的。当您通过 Visual Studio 创建区域时,它会为您创建区域注册类,以便您可以使用您提供的代码。你说得对。但。您可能还应该将呼叫添加到 RegisterAllAreas() 呼叫。
    • @Robert 是的,我同意您仍然需要 RegisterAllAreas 和 AreaRegistration 文件。我假设 OP 已经拥有这些,因为它们是由 VS 生成的。
    【解决方案2】:

    是的,但您必须更改路由:

    context.MapRoute(
        "Default",
        "{area}/{controller}/{action}/{id}",
        new { area = "Mobile", controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
    

    您也可以保留这两条路线,但不要忘记在默认值中定义 area

    重要

    当然,您必须将控制器保存在它们自己的区域命名空间中:

    namespace MyApp.Areas.Mobile.Controllers
    {
        public class HomeController : Controller
        {
            ...
        }
    }
    
    namespace MyApp.Areas.Sandbox.Controllers
    {
        public class HomeController : Controller
        {
            ...
        }
    }
    

    检查this link on MSDN 并查看走槽。另外不要忘记查看this MSDN article 讨论区域注册的内容,因为您必须调用RegisterAllAreas() 方法。

    而且由于您仍想保留原始的非区域控制器,您还应该阅读此 Phil Haack's article 如何做到这一点(信用应该转到 @Rob 在他的回答中首先指向此博客文章)。

    【讨论】:

    • @Quanday:我在答案中又添加了一个链接。但是对于您在评论中的问题,您可以通过提供第二个路由定义来路由这些类型的 URL,而不需要您提供特定区域默认值的区域,例如 area = "Global"。但是您还必须在该区域的第一条路线上添加一个约束,以仅在 area 具有特定字符串值时匹配该路线。你知道我在说什么吗?
    • 经过大约 2 小时的尝试,我可以说 "{area}/{ 是一个非常糟糕的主意,因为如果您这样做,您网站上的每个 url 都会重定向到按字母顺序排列的最低区域...
    • @Quandary:我严重怀疑这一点。默认值由路由顺序而不是字母表定义。但没关系,我希望您按照我最后添加的链接解决了您的问题。
    • 无论它是什么顺序,它总是路由到同一个地方,这似乎是字母顺序最低的区域 - 不一定是那样。但是,以下解决方案可以正常工作。我犯了另一个错误:我将 HomeController 操作文件命名为 Home 而不是 Index,然后它总是路由到全局 home 索引操作 - 而不是发出 HTTP 404 ...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 2015-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    相关资源
    最近更新 更多