3Da*_*ave 4 asp.net asp.net-mvc-routing asp.net-mvc-2
有人可以解释一下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
);
}
Run Code Online (Sandbox Code Playgroud)
如果我请求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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
注意如何进行分组.因此,基本上,DefaultControllerFactory将查看实现Controller基类的类型的所有引用程序集,并从名称中删除"Controller".
如果你真的想详细剖析ASP.NET MVC的管道,我会推荐你这篇优秀的文章.
ASP.NET MVC附带的默认视图引擎适用于以下约定:
你有这样的文件夹结构:
- Controllers\
|- HomeController.cs
- Views\
|- Home\
|-- Index.aspx
|- Shared\
Run Code Online (Sandbox Code Playgroud)
当请求进入并匹配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
);
Run Code Online (Sandbox Code Playgroud)
在默认路由中,您还指定了一个默认控制器(没有"Controller"后缀) - 路由引擎将自动添加Controller到您的控制器名称 - 以及默认操作.
在您的控制器中,您可以调用简单方法:
public ActionResult Index(){
return View();
}
Run Code Online (Sandbox Code Playgroud)
然后,默认视图引擎在"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}"}
);
Run Code Online (Sandbox Code Playgroud)
在这里,我明确指出我正在使用Albums控制器和PhotoDetails操作,并将各种ID传递给该操作.