为什么这条路线不匹配

时间:2012-01-03 11:47:21

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

我在使路线匹配时遇到一些麻烦。

我使用base-32编码的int作为Web应用程序中幻灯片的短链接。每个幻灯片有5个不同版本,我使用首字母来区分每个版本。

路由始终匹配,除非base-32编码int的第一个字符与指定幻灯片版本的字符相同。所有5个前缀字母都存在此异常:n,f,c,x和h。

前两个字符是一样的,这些路线不匹配?我无法理解这里发生了什么(当路线不匹配时,它们只会达到默认值)。

路线匹配(/na0): route for na0

路线不匹配(/nn0): route for nn0

路线匹配(/nfg): route for nfg

路线不匹配(/ffg): route for ffg

我很难过。这是路由代码,如果在屏幕截图中的RouteDebug表中不清楚:

        routes.MapRoute(
            "NonBrandedSlideshow",
            "n{id}",
            MVC.Slideshow.NonBranded(), null,
            new { id = Settings.Base32Regex }
        );

        routes.MapRoute(
            "FullSlideshow",
            "f{id}",
            MVC.Slideshow.Full(), null,
            new { id = Settings.Base32Regex }
        );

        routes.MapRoute(
            "CompactSlideshow",
            "c{id}",
            MVC.Slideshow.Compact(), null,
            new { id = Settings.Base32Regex }
        );

        routes.MapRoute(
            "FlexibleSlideshow",
            "x{id}",
            MVC.Slideshow.Flexible(), null,
            new { id = Settings.Base32Regex }
        );

        routes.MapRoute(
            "Html5Slideshow",
            "h{id}",
            MVC.Slideshow.NonBrandedHtml5(), null,
            new { id = Settings.Base32Regex }
        );

我应该在此注意我使用T4MVC(请参阅第2.2.5节),这些MapRoute方法是T4MVC添加的扩展。我使用的MapRoute方法等同于标准方法,我尝试使用非T4MVC MapRoute方法,结果相同:

        routes.MapRoute(
            "Html5Slideshow",
            "h{id}",
            new { controller = "Slideshow", action = "NonBrandedHtml5" },
            new { id = Settings.Base32Regex }
        );

这是Base32Regex,虽然我已经尝试了它有没有这个约束(我使用的Base32实现将假设I和O是1和0,例如)。

public static partial class Settings
{
    public static string Base32Regex
    {
        get { return @"[0-9ABCDEFGHJKMNPQRSTVWXYZ]+"; }
    }
}

5 个答案:

答案 0 :(得分:3)

这是ASP.NET路由中的已知错误,请参阅this answer以获取解释和解决方法。简而言之,使用文字子段不能很好地工作。

答案 1 :(得分:3)

好吧,我同样可怜。我执行了一些其他测试,据我所知,当路由参数之前的常量具有相同的重复字符时,这必须是检查路由的方式中的一些错误。其他一些令人难以置信的例子:

"nn{id}"
route matches (/nna0)
route doesn't match (/nnn0)

"nnn{id}"
route matches (/nnna0)
route doesn't match (/nnnn0)

一旦我使常量不重复相同的字符,一切都很好

"mn{id}"
route matches (/mna0)
route matches (/mnn0)
route matches (/mnmn)

这可能不是您正在寻找的。但考虑到情况的奇怪,这是我唯一能想到的。将常量添加到约束中并将其从URL中删除。然后在你的控制器中(这是我不喜欢的部分)你需要从id参数中删除该常量。希望这有效,或至少帮助引发另一种解决方案。

routes.MapRoute(
    "NonBrandedSlideshow",
    "{id}",
    MVC.Slideshow.NonBranded(), null,
    new { id = "n"+Settings.Base32Regex }
);

<强>更新

我想这是known issue,谢谢@ max-toro

答案 2 :(得分:2)

我没有太多成功获得匹配的路由,并为路由参数"const{param}"添加常量。您是否尝试将前缀用作完整的路径段,例如"const/{param}"?那会满足你的要求吗?

routes.MapRoute(

    "NonBrandedSlideshow",
    "n/{id}",
    MVC.Slideshow.NonBranded(), null,
    new { id = Settings.Base32Regex }
);

routes.MapRoute(
    "FullSlideshow",
    "f/{id}",
    MVC.Slideshow.Full(), null,
    new { id = Settings.Base32Regex }
);

...等?

在评论#1后更新

解读。我能想到的另一件事就是让id param变成一个catchall参数。看看是否有效:

routes.MapRoute(

    "NonBrandedSlideshow",
    "n{*id}",
    MVC.Slideshow.NonBranded(), null,
    new { id = Settings.Base32Regex }
);

routes.MapRoute(
    "FullSlideshow",
    "f{*id}",
    MVC.Slideshow.Full(), null,
    new { id = Settings.Base32Regex }
);

但是,这些路由应该延迟注册,以便控制器不会将任何带有n,f等前缀的URL路由到这些控制器操作。

答案 3 :(得分:1)

你是否试过在没有路线约束的情况下匹配它们?

编辑:抱歉半个答案被打断了

你需要尝试这个路线约束

     routes.MapRoute(
            "NSlideshow",
            "{id}",
            new { controller = "SlideShow", action = "N", id = UrlParameter.Optional },
            new
            {
                id = @"^[n]{1}[0-9ABCDEFGHJKMNPQRSTVWXYZ]+"
            }
        );

     routes.MapRoute(
            "GSlideshow",
            "{id}",
            new { controller = "SlideShow", action = "G", id = UrlParameter.Optional },
            new
            {
                id = @"^[g]{1}[0-9ABCDEFGHJKMNPQRSTVWXYZ]+"
            }
        );

为每个案例冲洗并重复,在你的动作方法中剥去id前面的第一个字符

答案 4 :(得分:1)

这是一种解决方法。一个奇怪的,我想......

由于路由规则非常简单,您可以创建自定义ControllerFactory并检查网址。如果url符合您的方式,您可以定义要使用的控制器和操作,并根据URL设置id参数。如果没有,只需保留常规行为。

我知道,它不会使用开箱即用的路由,但因为它不起作用...好消息是,一旦它修复你可以更新路由,删除自定义ControllerFactory并继续,没有解决方法。