ASP MVC4在不同区域中具有相同名称的控制器中查找适当的方法

时间:2012-03-07 23:46:03

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

我见过一些类似的问题,但我发现我有一个不同的问题。

我在基础项目中有一个带控制器的MVC4项目和3个区域。每个区域都包含一个名为AdminController的控制器和一个方法List。

我的问题是,当我使用链接转到方法列表时,总是通过相同的控制器(例如,用户区域中的AdminController),但返回的视图是正确的。

项目结构如下:

  • Mimbre.Administration(网络mvc4项目)
      • 目录
        • 控制器
          • AdminController
        • 模型
          • 管理
            • List.chtml -ContentsAreaRegistration.cs
      • 日志
        • 控制器
          • AdminController
        • 模型
          • 管理
            • List.chtml
        • LogsAreaRegistration.cs
      • 用户
        • 控制器
          • AdminController
        • 模型
          • 管理
            • List.chtml
        • UsersAreaRegistration.cs
    • 控制器(基础项目)
    • 观点(基础项目)

区域注册的类包含这样的RegisterArea方法(根据当前区域具有适当的名称和命名空间):

   public override void RegisterArea(AreaRegistrationContext context) {
        context.MapRoute(
            "Contents_default",
            "Contents/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional },
            new string[] { "Mimbre.Administration.Areas.Contents.Controllers" }
        );
    }

Global.asax包含基础项目的注册路由的方法

        public static void RegisterRoutes(RouteCollection routes) {

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        AreaRegistration.RegisterAllAreas();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            namespaces: new string[]{"Mimbre.Administration.Controllers"}
        );
    }

在index.chtml中(在基础项目中)我创建了每个区域的List方法的链接:

<a href="@Url.Action("List", "Admin", new { area = "Contents"})" >Contents list</a>
<a href="@Url.Action("List", "Admin", new { area = "Logs"})" >Logs list</a>
<a href="@Url.Action("List", "Admin", new { area = "Users"})" >Users list</a>

在生成的html中,这些链接如下所示:

<a href="/Contents/Admin/List/">Contents list</a>
<a href="/Logs/Admin/List/">Logs list</a>
<a href="/Users/Admin/List/">Users list</a>

我认为这些链接是正确的,问题是点击的任何链接总是带我通过AdminController of Users区域中的方法List,其他区域的AdminController中的方法List永远不会被选中。

这个问题可以通过重命名控制器的名称,每个区域的唯一名称来解决,但我真的需要在所有区域保持相同的控制器名称,任何想法???

提前结束!!!

2 个答案:

答案 0 :(得分:2)

最后我可以模拟你的问题。我可以获得与您相同的输出的唯一方法(无论您尝试访问哪个区域,但是到达相同的用户控制器并使用正确的视图进行响应)都是在您使用错误的控制器名称空间注册区域时。 / p>

/ Admin / Home / List route:

namespace SandboxMvcApplication.Areas.Admin.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult List()
        {
            ViewBag.Message = "You've acessed Admin/List";

            return View();
        }
    }
}

/ Admin / Home / List view:

@{
    ViewBag.Title = "List";
}

<h1>Admin</h1>

<h2>@ViewBag.Message</h2>

管理区域注册:

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        "Admin_default",
        "Admin/{controller}/{action}/{id}",
        new { action = "Index", id = UrlParameter.Optional },
        new string[] { "SandboxMvcApplication.Areas.Admin.Controllers" }
    );
}

/用户/主页/列表路线:

public class HomeController : Controller
{
    public ActionResult List()
    {
        ViewBag.Message = "You've accessed User/List";

        return View();
    }
}

/用户/主页/列表视图:

@{
    ViewBag.Title = "List";
}

<h1>User</h1>

<h2>@ViewBag.Message</h2>

用户区注册:

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        "User_default",
        "User/{controller}/{action}/{id}",
        new { action = "Index", id = UrlParameter.Optional },
        new string[] { "SandboxMvcApplication.Areas.Admin.Controllers" }
    );
}

使用此配置,我的输出是:

  1. / Admin / Home / List

    管理

    您已经访问了管理员/列表

  2. /用户/主页/列表

    用户

    您已经访问了管理员/列表

  3. 请注意,第一个单词可以正常工作(确保呈现了正确的视图,但是从列表操作中提交了错误的数据)。

    如果我更正UserAreaRegistration(“SandboxMvcApplication.Areas.User.Controllers”)中的用户控制器命名空间,一切正常!

    检查一下这是否可以帮助您或尝试将您的命名空间明确地放到正确的控制器上。您还可以检查Admins控制器是否也具有正确的命名空间。

答案 1 :(得分:0)

您需要在路线注册中再添加一个设置。这将阻止DefaultControllerFactory在非预期区域中搜索控制器。

        routes.MapRoute( 
        name: "Default", 
        url: "{controller}/{action}/{id}", 
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 
        namespaces: new string[]{"Mimbre.Administration.Controllers"} 
    ).DataTokens["UseNamespaceFallback"] = false;