MVC Area 技術的使用 - 同名 Controller 處理方法
打鐵趁熱,繼續利用上一個 Project 來了解同名 Controller 的處理方法。
一、處理頂層 Controller 同名問題
先在 MyArea 底下改成與頂層同名的 HomeController
View 的部份也要修改一下成 MyArea/Views/Home
先來看頂層的index.cshtml,按F5執行如下圖,出現同名Controller問題
因為網站初始會先顯示該首頁之前,就會拿頂層的 HomeController 去跟其他 Controller 比對發現有同名 Controller。
此時於頂層的 RouteConfig.cs 限制一下命名空間「namespaces: new string[] { "WebApplication1.Controllers" }」,
表示此 routing 規則限用於 WebApplication1.Controllers 命名空間
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace WebApplication1
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "WebApplication1.Controllers" }
);
}
}
}
頂層的 HomeController 同名問題即可解決。
二、處理 Area 層 Controller 同名問題
接下來繼續發覺問題,
於頂層的 _Layout.cshtml 裡新增一個連到 MyArea/Home/Index 的超連結,
_Layout.cshtml 的內容為
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - My ASP.NET Application</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> <li>@Html.ActionLink("Contact", "Contact", "Home")</li> <li>@Html.ActionLink("MyAreaHome", "Index", new { controller = "Home", area = "MyArea" })</li> </ul> </div> </div> </div> <div class="container body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - My ASP.NET Application</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
我們故意要把問題顯現出來,將 Area 層的 MyAreaAreaRegistration.cs 的內容
using System.Web.Mvc;
namespace WebApplication1.Areas.MyArea
{
public class MyAreaAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "MyArea";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyArea/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
}
改成
using System.Web.Mvc;
namespace WebApplication1
{
public class MyAreaAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "MyArea";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyArea/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
}
繼續 F5 執行並點選「MyAreaHome」超連結
假設路由的命名空間都在 WebApplication1 之下,此時會出現 MyArea 的 HomeController 同名問題
也是一樣修改方法,於 MyAreaAreaRegistration.cs 檔,限制一下命名空間,修改程式碼如下
using System.Web.Mvc;
namespace WebApplication1
{
public class MyAreaAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "MyArea";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyArea/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "WebApplication1.Areas.MyArea.Controllers" }
);
}
}
}
問題即可解決。
三、路由的命名空間限制
接下來再做一點變化,
1、在 MyArea/Controllers 底下再新增一個資料夾「NewFolder1」。
2、NewFolder1 資料夾裡再新增一個名為 DefaultController.cs 檔。
3、再新增對應的View。
經由上圖看 DefaultController.cs 裡面的內容,發現命名空間又多了一層NewFolder1,
執行後觀察卻發現找不到該網頁,原因是路由的命名空間限制問題。
請於 MyAreaAreaRegistration.cs 裡也允許使用 WebApplication1.Areas.MyArea.Controllers.NewFolder1 命名空間
using System.Web.Mvc;
namespace WebApplication1
{
public class MyAreaAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "MyArea";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyArea/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "WebApplication1.Areas.MyArea.Controllers", "WebApplication1.Areas.MyArea.Controllers.NewFolder1" }
);
}
}
}
即可成功找到該網頁。