[英]ASP.NET MVC 2 How are urls/routes, views related to controllers?
有人可以解釋一下MVC 2中路由器與控制器的關聯方式嗎? 目前,我在/Controllers/HomeController.cs中有一個控制器和一個視圖/Home/Index.aspx。
我的路線注冊方法如下:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
routes.MapRoute(
"Default",
// Route name
"{controller}/{action}/{id}",
// URL with parameters
new { controller = "Home", action = "Index", id = "" }
// Parameter defaults
);
}
如果我請求URL: http:// localhost / Home / Index ,則HomeController.Index()正確處理請求。
但是,對於我的生活,我無法弄清楚url / Home / Index如何指向HomeController。 據我所知,視圖aspx沒有引用HomeController,HomeController沒有引用視圖,路由表也沒有明確提到HomeController。 這神奇地發生了什么? 當然我錯過了一些明顯的東西。
然后
這是ASP.NET MVC中的約定。
使用DefaultControllerFactory時,此約定隱藏在內部密封類System.Web.Mvc.ControllerTypeCache
(Microsoft通常用於編寫內部密封類)。 在里面你會發現一個名為EnsureInitialized
的方法,如下所示:
public void EnsureInitialized(IBuildManager buildManager)
{
if (this._cache == null)
{
lock (this._lockObj)
{
if (this._cache == null)
{
this._cache = GetAllControllerTypes(buildManager).GroupBy<Type, string>(delegate (Type t) {
return t.Name.Substring(0, t.Name.Length - "Controller".Length);
}, StringComparer.OrdinalIgnoreCase).ToDictionary<IGrouping<string, Type>, string, ILookup<string, Type>>(delegate (IGrouping<string, Type> g) {
return g.Key;
}, delegate (IGrouping<string, Type> g) {
return g.ToLookup<Type, string>(t => t.Namespace ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}, StringComparer.OrdinalIgnoreCase);
}
}
}
}
注意如何進行分組。 因此,基本上,DefaultControllerFactory將查看實現Controller基類的類型的所有引用程序集,並從名稱中刪除“Controller”。
如果你真的想詳細剖析ASP.NET MVC的管道,我會推薦你這篇優秀的文章 。
ASP.NET MVC附帶的默認視圖引擎適用於以下約定:
你有這樣的文件夾結構:
- Controllers\
|- HomeController.cs
- Views\
|- Home\
|-- Index.aspx
|- Shared\
當請求進入並匹配RegisterRoutes方法中定義的路由時(請參閱URL路由等更多內容),然后調用匹配的控制器:
routes.MapRoute(
"Default", // Route name, allows you to call this route elsewhere
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
在默認路由中,您還指定了默認控制器(沒有“Controller”后綴) - 路由引擎將自動將Controller
添加到控制器名稱中 - 以及默認操作。
在您的控制器中,您可以調用簡單方法:
public ActionResult Index(){
return View();
}
然后,默認視圖引擎在“Views”文件夾(約定)中的名為“Home”的文件夾(與控制器相同)中查找名為Index的aspx文件(與操作相同)。
如果它沒有在那里找到,它還將在共享文件夾中查找索引頁面。
在解析視圖模板時,ASP.NET MVC應用程序默認使用基於約定的目錄命名結構。 這允許開發人員在從Controller類中引用視圖時避免必須完全限定位置路徑。 默認情況下,ASP.NET MVC將在應用程序下的
\\Views\\[ControllerName]\\
目錄中查找視圖模板文件。
\\Views\\Shared
子目錄提供了一種存儲視圖模板的方法,這些模板在應用程序中的多個控制器之間重復使用。 當ASP.NET MVC嘗試解析視圖模板時,它將首先在\\Views\\[Controller]
特定目錄中進行檢查,如果找不到視圖模板,它將在\\Views\\Shared
目錄中查找。在命名單個視圖模板時,建議的指導是使視圖模板與導致其呈現的操作方法共享相同的名稱。 例如,在我們的“索引”操作方法上方使用“索引”視圖來呈現視圖結果,“詳細信息”操作方法使用“詳細信息”視圖來呈現其結果。 這樣可以輕松快速查看與每個操作關聯的模板。
當視圖模板與控制器上調用的操作方法同名時,開發人員無需顯式指定視圖模板名稱。 我們可以只將模型對象傳遞給
View()
輔助方法(不指定視圖名稱),ASP.NET MVC會自動推斷我們要使用\\Views\\[ControllerName]\\[ActionName]
視圖模板磁盤來渲染它。
編輯添加:
我設置的一些示例路由,顯式設置控制器是:
routes.MapRoute(
"PhotoDetailsSlug",
"Albums/{albumId}/{photoId}/{slug}",
new {controller = "Albums", action = "PhotoDetails"},
new {albumId = @"\d{1,4}", photoId = @"\d{1,8}"}
);
在這里,我明確指出我正在使用Albums控制器和PhotoDetails操作,並將各種ID傳遞給該操作。
在操作索引內部有一個語句return View()
。 返回空白視圖時,DefaultViewEngine會在幾個默認文件夾中搜索Controller方法的名稱(特別是在FindView方法中)。 其中一個是Views / Home目錄,因為Home是控制器的名稱。 在那里它找到索引文件,並使用它來顯示結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.