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

本文关键字:控制器 方法 MVC4 区域 ASP | 更新日期: 2023-09-27 18:27:01

我看到了一些类似的问题,但我发现我有一个不同的问题。

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

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

项目结构如下:

  • Mimbre.Administration(web mvc4项目)
    • 区域
      • 目录
        • 控制器
          • AdminController
        • 型号
        • 视图
          • 管理员
            • List.chtml-内容重新注册.cs
      • 日志
        • 控制器
          • AdminController
        • 型号
        • 视图
          • 管理员
            • List.chtml
        • 日志重新注册.cs
      • 用户
        • 控制器
          • AdminController
        • 型号
        • 视图
          • 管理员
            • List.chtml
        • 用户重新注册.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区域中的方法List,而其他区域的AdminController中的方法列表从未被选中。

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

提前感谢!!!

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

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

/管理员/主页/列出路线:

namespace SandboxMvcApplication.Areas.Admin.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult List()
        {
            ViewBag.Message = "You've acessed Admin/List";
            return 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. /管理员/主页/列出

    管理员

    您已访问管理员/列表

  2. /用户/主页/列出

    用户

    您已访问管理员/列表

请注意,第一个单词很好用(确保呈现了正确的视图,但从列表操作中混合了错误的数据)。

如果我在UserAreaRegistration("SandboxMvcApplication.Areas.user.Controllers")中更正了用户控制器命名空间,一切都很好!

看看这是否能对你有所帮助,或者尝试将你的名称空间显式地放在正确的控制器上。您还可以检查Admins控制器是否也具有正确的命名空间。

您需要在路线注册中再添加一个设置。这将防止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;