NET MVC区域路由404等解决方案

第一遍检查发现路由重命名

第二遍跟踪路由解析发现命名空间与controller文件不匹配

更改后成功解析

其他解决方案:转载至 

原文地址

http://blog.useasp.net/archive/2012/08/07/confused-with-the-MapRoute-constraint-and-IgnoreRoute-method-in-MVC3-route.aspx

近日在使用MVC3进行开发时,碰到要将一个不存在的路径剔除出来,不要在当前的Route中匹配。但是根据官方的方法怎么也没有办法。感觉MapRoute的处理方法相当的怪异。

  首先说明下需求:

一个Area: admin

我们有一个路径:admin/system-monitor/state.axd,该路径没有控制器来接管,也没有物理文件,而是有专门的Handler来处理,因此需要将此路径排除匹配。

我们在Global.asax中的配置大概如下:

code
1
2
3
4
5
6
7
8
routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" );
 
routes.MapRoute(
     "Default" ,
     "{manager}/{controller}/{action}/{id}/{p}" ,
     new { manager= "Sino" , controller =  "Home" , action =  "Index" , id = UrlParameter.Optional, p = UrlParameter.Optional },
     new string [] {  "Sino.Nico.Controllers" }
);

这个是配置前台的路由,问题不大,后台的路由配置:

code
1
2
3
4
5
6
context.MapRoute(
     "admin" ,
     "admin/{manager}/{controller}/{action}" ,
     new { manager=  "Sino" , controller =  "Home" , action =  "Index" },
     new string [] {  "Sino.Nico.Areas.Admin.Controllers" }
     );

这两个配置在没有加入排除路径的前提下,运行正常。为了排除路径,我们能想到的最简单的方法就是使用IgnoreRoute了,于是,我们在Global.asax中添加,变成如下:

code
1
2
3
4
5
6
7
8
9
10
11
12
public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" );
            routes.IgnoreRoute( "admin/system-monitor/state.axd/{*pathInfo}" );
 
            routes.MapRoute(
                "Default" ,
                "{manager}/{controller}/{action}/{id}/{p}" ,
                new { manager= "Sino" , controller =  "Home" , action =  "Index" , id = UrlParameter.Optional, p = UrlParameter.Optional },
                new string [] {  "Sino.Nico.Controllers" }
            );
        }

可是这样处理并没有正常的排除掉这个路径,这个路径的访问还是被admin这个Area的路由匹配,结果找不到资源。

MS的官方说,如果使用IgnoreRoute方式来处理后的路径,如果第一时间匹配之后,会直接排除而不会进行任何路由匹配,看来在MVC3中,这个说法好像并不是很确切。 —— 也许是个人理解的出入。为了解决这个问题,我们只能换一种方法来处理,在Area中的RegisterArea方法中创建MapRoute的时候,添加约束,Areas中的代码:

code
1
2
3
4
5
6
7
8
9
10
11
public override void RegisterArea(AreaRegistrationContext context)
         {
 
             context.MapRoute(
                 "admin" ,
                 "admin/{manager}/{controller}/{action}" ,
                 new { manager=  "Sino" , controller =  "Home" , action =  "Index" },
                 new { manager=  @"^(?!system-monitor$)" },  // 使用约束将system-monitor强行不进行匹配
                 new string [] {  "Sino.Nico.Areas.admin.Controllers" }
                 );
         }

注意,这时候我们并没有在Global.asax中添加IgnoreRoute了,遗憾的是,这时候,我们访问的时候,system-monitor匹配到了Global.asax中的路由,直接报没有找到资源。

code
1
2
3
4
5
6
7
8
9
Server Error in '/' Application.
 
The resource cannot be found.
 
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.
 
Requested URL: /admin/system-monitor/
 
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.272

最后,我们只好做两件事情:

1. 我们将路径在Area中直接过滤掉;

2. 在Global.asax中使用IgnoreRoute排除该路径。

这回好了,不再报找不到路径了,但是等我们回过神来,却发现,后台所有的路径都有问题了,都是找不到资源,毫不犹豫肯定是manager的约束出现问题了。正则我们看了又看,肯定是没有问题的,如果manager不为system-monitor的时候,IsMatch肯定是返回true的。

在纠结一段时间之后,我们决定看看MVC内部到底是如何设计的,怎么会出现这种问题,结果,打开代码的那一刹那,我惊了:

code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected virtual bool ProcessConstraint(HttpRequestMessage request,  object constraint,  string parameterName, HttpRouteValueDictionary values, HttpRouteDirection routeDirection)
         {
             IHttpRouteConstraint customConstraint = constraint  as IHttpRouteConstraint;
             if (customConstraint !=  null )
             {
                 return customConstraint.Match(request,  this , parameterName, values, routeDirection);
             }
 
             // If there was no custom constraint, then treat the constraint as a string which represents a Regex.
             string constraintsRule = constraint  as string ;
             if (constraintsRule ==  null )
             {
                 throw Error.InvalidOperation(SRResources.Route_ValidationMustBeStringOrCustomConstraint, parameterName, RouteTemplate,  typeof (IHttpRouteConstraint).Name);
             }
 
             object parameterValue;
             values.TryGetValue(parameterName,  out parameterValue);
             string parameterValueString = Convert.ToString(parameterValue, CultureInfo.InvariantCulture);
             string constraintsRegEx =  "^(" + constraintsRule +  ")$" ;
             return Regex.IsMatch(parameterValueString, constraintsRegEx, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
         }

原来他自带^(...)$进行头尾匹配!

那么我们的正则再到这里就变成了:^(^(?!system-monitor$))$这个和^(?!system-monitor$)相差也太远了。看到问题了,解决起来就非常简单了。将代码变成如下这样:

code
1
2
3
4
5
6
7
8
9
10
11
public override void RegisterArea(AreaRegistrationContext context)
         {
 
             context.MapRoute(
                 "admin" ,
                 "admin/{manager}/{controller}/{action}" ,
                 new { manager=  "Sino" , controller =  "Home" , action =  "Index" },
                 new { manager=  @"(?!system-monitor$)[\w\W]*" },  // 使用约束将system-monitor强行不进行匹配
                 new string [] {  "Sino.Nico.Areas.admin.Controllers" }
                 );
         }

编译,运行,通过。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值