asp.net MVC | 寻找.匹配Controller

最初以为是根据默认命名规范,从文件夹Controllers中查询  ^_^. 然后做了个测试,将controller放到新的工程.测试成功,程序可以运行.说明是从载入的程序集中搜寻controller的.难道是从所有加载程序集中搜寻匹配?同名的怎么办?

又做了一个测试.在新的命名空间OOne.Mvc.Controllers1创建HomeController(与默认生成的相同) ,

很不幸,结果程序显示以下错误:System.InvalidOperationException: The controller name 'Home' is ambiguous between the following types:

 

OOne.Mvc.Controllers.HomeController
OOne.Mvc.Controllers1.HomeController

行 16:             HttpContext.Current.RewritePath(Request.ApplicationPath, false);
行 17: IHttpHandler httpHandler = new MvcHttpHandler();
行 18: httpHandler.ProcessRequest(HttpContext.Current);
行 19: HttpContext.Current.RewritePath(originalPath, false);

 源文件: D:"sl_projects"OOne"OOne.Mvc.View"Default.aspx.cs    行: 18

 表面看来是在所有载入的程序集中查询.

 然后查看mvc源代码,发现以下程序:

 //该方法抛出异常:InvalidOperationException

  private Type GetControllerTypeWithinNamespaces(string controllerName, HashSet<string> namespaces) {
            // Once the master list of controllers has been created we can quickly index into it
            ControllerTypeCache.EnsureInitialized(BuildManager);

            IList<Type> matchingTypes = ControllerTypeCache.GetControllerTypes(controllerName, namespaces);
            switch (matchingTypes.Count) {
                case 0:
                    // no matching types
                    return null;

                case 1:
                    // single matching type
                    return matchingTypes[0];

                default:
                    // multiple matching types
                    string typeNames = String.Join(", ", matchingTypes.Select(t => t.FullName).ToArray());
                    throw new InvalidOperationException(
                        String.Format(
                            CultureInfo.CurrentUICulture,
                            MvcResources.DefaultControllerFactory_ControllerNameAmbiguous,
                            controllerName, typeNames));
            }
        }

 其中参数HashSet<string> namespaces 由以下语句生成:

RequestContext.RouteData.DataTokens.TryGetValue("Namespaces", out routeNamespacesObj);

HashSet<string> nsHash = new HashSet<string>(routeNamespaces, StringComparer.OrdinalIgnoreCase);

或者

 HashSet<string> nsDefaults = new HashSet<string>(ControllerBuilder.DefaultNamespaces, StringComparer.OrdinalIgnoreCase)
或者

GetControllerTypeWithinNamespaces(controllerName, null /* namespaces */);

结论:

搜寻.匹配 是有优先级的. 首先会用 Route 注册时提供的 Namespace 进行匹配,在没有结果时再使用 ControllerBuilder.DefaultNamespaces 进行匹配.如果两者都没有, 就是匹配所有载入程序集内的controller了.

 同级中找出来多个就错了!

附:

1. ControllerTypeCache ._cache 保存了所有载入程序集中的 Controller 类型

 2.  Route 注册   routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
                , new String[] { "OOne.Mvc.Controllers1" }          // namespace
            );

3. DefaultNamespaces

protected void Application_Start()
        {
            //ControllerBuilder.Current.DefaultNamespaces.Add("OgilvyOne.Mvc.Controllers1");
            RegisterRoutes(RouteTable.Routes);
        }

posted on 2009-07-01 16:27  走向前  阅读(775)  评论(0编辑  收藏  举报