邮件操作中的URL路由无法正常工作

时间:2012-07-30 12:07:04

标签: asp.net-mvc-3 url-routing

在我的应用程序中,我有一个区域(XYZ),在区域内有一个控制器(XYZController)和一堆其他控制器。 XYZController具有索引,视图,创建,编辑等一般操作。与某些特定功能相关的更具体的操作相应地安排在相应的控制器中。

为了避免URL具有以下结构:app / XYZ(区域)/ XYZ(控制器)/创建,我在区域路径寄存器文件中添加了如下路由。

context.MapRoute(
                  "XYZ_AreaDefaultControllerActions",
                  "XYZ/{action}/{id}",
                  new { controller = "XYZ", id = UrlParameter.Optional },
                  new { controller = "XYZ" },
                  new string[] { "App.Web.Areas.XYZ.Controllers.*" } 
              );

context.MapRoute(
                "XYZ_default",
                "XYZ/{controller}/{action}/{id}",
                new { controller = "XYZ", action = "Index", id = UrlParameter.Optional}
        );

此映射将url:app / XYZ / Create路由到area = XYZ,Controller = XYZ和Action = Create这是正确的,这是我想要做的,但是会混淆其他一些Post动作的路由。

考虑到这一点,我有另一个名为Notes控制器的控制器,它有一些Post动作。

当请求是HTTP Get并且路由调试器的输出显示第二个路由定义匹配而第一个路径定义不匹配时,将url作为/ app / XYZ / Notes / List / id的操作正确路由。 / p>

当我使用带有url / App / XYZ / Notes / AddNote的动作AddNote向同一个控制器发帖时,第一个路由定义根据路由调试器匹配,因此找不到操作,因为它需要Controller = XYZ,Action = Notes,Id = AddNote。 以下是路由调试器的输出:

匹配|网址|默认值|约束

  1. True | XYZ / {action} / {id} | controller = XYZ,id = | controller = XYZ

  2. True | XYZ / {controller} / {action} / {id} | controller = XYZ,action = Index,id = |(null)

  3. 问题是看起来第一条路线的约束条件并没有足够限制Post,而在Get中应用约束条件。

    有什么建议吗?

1 个答案:

答案 0 :(得分:0)

如果您的XYZController没有任何POST操作,您可以添加这样的约束以防止POST请求与您的第一条路线匹配:

context.MapRoute("XYZ_AreaDefaultControllerActions",
    "XYZ/{action}/{id}",
    new { controller = "XYZ", id = UrlParameter.Optional },
    new { controller = "XYZ", httpMethod = new HttpMethodConstraint("GET") },
    new string[] { "App.Web.Areas.XYZ.Controllers.*" }
);

<强>更新

由于您在XYZController中有后期操作,如上所述,上述路径约束对您不起作用。

这里的问题是你有一个与你的区域同名的控制器。这就是MVC将第一条路线与笔记控制器POST操作匹配的原因,因为它只是尝试根据传入 URL来匹配令牌:

  • / XYZ - 这与第一个路线的第一段字面匹配
  • /注意 - 这会填入您的{action}段
  • / AddNote - 这会填入您的{id}段

鉴于您的第一个路由,{ controller = "XYZ" }约束没有任何区别,因为MVC正在尝试将入站URL路由到控制器+ action + args。 MVC不知道它来自哪个控制器,它试图匹配控制器和操作将处理URL请求。

一种解决方案是在第一条路线上添加动作约束,但这只有在XYZController中的动作名称与记事控制器中的任何POST动作名称都不匹配时才有效:

new { controller = "XYZ", action = "XYZAction1|XYZAction2|XYZActionN" },

对于传入路由,当操作是约束中的一个以管道分隔的名称时,这将仅匹配第一个路径。

另一种选择是constrain your {id} route segment using a regex。如果你的id是字符串,这可能不是一个选项。但是,如果您的ID始终为数字,则可以将第一个路径限制为仅将路径段与{id}令牌匹配为数字。这样,“AddNote”与第一条路线的{id}段不匹配,因为它不是数字:

new { controller = "XYZ", id = @"\d+" },

要回答您的第二条评论,这与GET一起使用的原因是因为您的第二条路线有一个额外的路线段。 ID为的GETS与第一条路线不匹配,因为它们有4个令牌,而不是3个。