MVC自定义路由,实现二级域名类导致的找到多个与名为xxx的控制器匹配的类型的错误

时间:2022-10-04 05:55:40
今日在网站错误日志中发现手机站页面访问: http://m.jinrimianshi.com/company/395961

时出现找到多个与名为“company”的控制器匹配的类型。如果为此请求(“{controller}/{action}/{id}”)提供服务的路由没有指定命名空间以搜索与此请求相匹配的控制器,则会发生这种情况。如果是这样,请通过调用带有 'namespaces' 参数的 "MapRoute" 方法的重载来注册此路由的错误。

“company”请求找到下列匹配的控制器:

LMCMS.Areas.Admin.Controllers.CompanyController

LMSoft.Zhaopin.Controllers.CompanyController

我的m.jinrimianshi.com是自定义的二级域名,指向的是www.jinrimianshi.com的area=M的区域。在这里面只有一个home控制器,而没有company控制器。我感到有点奇怪,没找到相应控制器不是应该返回404错误么。

由于我没有使用namespaces参数,而有如果出现多个匹配,可以使用namespaces参数的maproute方法重载来注册此路由的提示。我进行了重写。重写后是这样得:


//自定义路由 
routes.Add("DomainRouteForManage"new DomainRoute(
     "m.jinrimianshi.com",                      // 固定的二级域名
     "{controller}/{action}/{id}",                  // URL with parameters
     new                               //defaults
     {
        area = "M",
        controller = "Home",
        action = "Index",
        id = UrlParameter.Optional,
        Namespaces = new string[] { "LMSoft.Zhaopin.Areas.M.Controllers" }
      }  // Parameter defaults
));

但是编译刷新后问题依旧,没起什么作用。这时我想知道这个路由究竟是如何匹配的。由于以前处理路由匹配的时候知道有一个routedebugger工具可以查匹配情况。因此先装此工具。

首先在程序包控制台中执行命令

Install-Package routedebugger

执行后web.config中出现了一行代码:

<add key="RouteDebugger:Enabled" value="true" />

然后编译刷新项目,但是在页面底部并没有出现routedebugger的路由提示信息。经过分析,发现项目中缺少了对routedebugger的dll引用。在项目的packages包中找到routedebugger.dll,在项目中添加对其的引用。添加后编译,刷新项目,路由信息出现了。

MVC自定义路由,实现二级域名类导致的找到多个与名为xxx的控制器匹配的类型的错误

通过查看,有4个匹配项。绿色为true的。由于我们知道mvc的路由匹配机制是从上往下寻找。当找到第一个匹配的时候就跳转到这个匹配规则上执行。下面的其他匹配被放弃。通过下图可以看出,确实匹配的是名字为DomainRouteForManage的自定义路由。可是已经限制了这个controller的命名空间为:LMSoft.Zhaopin.Areas.M.Controllers,怎么没起作用?

MVC自定义路由,实现二级域名类导致的找到多个与名为xxx的控制器匹配的类型的错误

通过大量的查找资料,终于找到了想要的答案。原来在控制器的激活过程中,是由DefaultControllerFactory控制的。它首先在你限定的命名空间中进行查找,如果找不到相应的控制器,那么它会看DataTokens["UseNamespaceFallback"]是否有,如果没有设置,或者有但是值为true,那么在限定的命名空间中找不到相应的控制器的情况下,它会搜索项目中其他命名空间下的控制器,如果出现多个匹配,则就会报找到多个与名为“company”的控制器匹配的类型这样得错误信息。如果有设置,并且值为false,则在找不到匹配的情况下就会报404错误。那对应此次我碰到的错误。很显然,在LMSoft.Zhaopin.Areas.M.Controllers这个我限定的命名空间没找到名我company的控制器,而在DataTokens中,UseNamespaceFallback也没有。所以导致其搜索了项目其他命名空间的控制器,找到了两个匹配,因此出现了此错误。知道了错误的原因,那么解决此问题就有了思路。由于我自定义二级域名的路由使用的是一个自写的类:DomainRoute,此类是在网上找的,网上有相应代码,大同小异,我这里就不写了。我找到了此类中添加Namespaces的代码部分。

foreach (KeyValuePair<stringobject> item in Defaults)
{
     data.Values[item.Key] = item.Value;     
#region 此处将area及Namespaces写入DataTokens里
     if (item.Key.Equals("area") || item.Key.Equals("Namespaces"))
     {
          data.DataTokens[item.Key] = item.Value;
                            
     }      
#endregion
}

data.DataTokens[item.Key] = item.Value;代码下面增加了一行代码:

data.DataTokens["UseNamespaceFallback"] = false;

由于这个是循环添加,加上后我还担心会不会重复添加UseNamespaceFallback,编译刷新后才发现自己多虑了。并没有重复添加,仍然是一个UseNamespaceFallback。

结果出来了,出现了我想要的,404未发现的错误。问题解决

参考文章:

http://www.cnblogs.com/P_Chou/archive/2010/11/15/details-asp-net-mvc-04.html

http://www.cnblogs.com/yipu/archive/2012/11/21/2780119.html