asp.net MVC | 寻找.匹配Controller

本文探讨了ASP.NET MVC中控制器的查找及匹配机制,详细解释了如何通过不同层级的命名空间来定位控制器,并分析了当存在同名控制器时程序如何处理这一情况。

最初以为是根据默认命名规范,从文件夹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);
        }

转载于:https://www.cnblogs.com/go-ahead/archive/2009/07/01/1514799.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值