I'm having some trouble getting routes to match.
我在寻找匹配路线方面遇到了一些麻烦。
I am using base-32 encoded int's as short links to slideshows in a web app. There are 5 different versions of each slideshow, and I am using an initial letter to distinguish between each version.
我使用base-32编码的int作为Web应用程序中幻灯片的短链接。每个幻灯片有5个不同版本,我使用首字母来区分每个版本。
The routes always match, except when the first character of the base-32 encoded int is the same as the character designating the slideshow version. This anomaly exists for all 5 prefix letters: n, f, c, x, and h.
路由始终匹配,除非base-32编码的int的第一个字符与指定幻灯片版本的字符相同。所有5个前缀字母都存在此异常:n,f,c,x和h。
What about the first two characters being the same makes these routes not match? I'm at a loss to understand what's going on here (when the routes don't match, they simply fall through to the default).
前两个字符相同会使这些路线不匹配?我无法理解这里发生了什么(当路线不匹配时,它们只会达到默认值)。
Route Matches (/na0
):
路线匹配(/ na0):
Route Doesn't Match (/nn0
):
路线不匹配(/ nn0):
Route Matches (/nfg
):
路线匹配(/ nfg):
Route Doesn't Match (/ffg
):
路线不匹配(/ ffg):
I'm boggled. Here's the routing code, in case it isn't clear in the RouteDebug tables in the screenshots:
我很难过。这是路由代码,如果在屏幕截图中的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 }
);
I should note here that I am using T4MVC (see section 2.2.5), and these MapRoute
methods are extensions added by T4MVC. The MapRoute
methods I am using are equivalent to the standard methods, and I have tried using the non-T4MVC MapRoute
method with the same result:
我在这里要注意的是,我使用的是T4MVC(参见第2.2.5节),这些MapRoute方法是T4MVC添加的扩展。我使用的MapRoute方法等同于标准方法,我尝试使用非T4MVC MapRoute方法,结果相同:
routes.MapRoute(
"Html5Slideshow",
"h{id}",
new { controller = "Slideshow", action = "NonBrandedHtml5" },
new { id = Settings.Base32Regex }
);
Here is the Base32Regex, though I have tried it with and without this constraint (the Base32 implementation I am using will assume I and O are 1 and 0, for example).
这是Base32Regex,虽然我已经尝试了它有没有这个约束(我使用的Base32实现将假设I和O是1和0,例如)。
public static partial class Settings
{
public static string Base32Regex
{
get { return @"[0-9ABCDEFGHJKMNPQRSTVWXYZ]+"; }
}
}
5 个解决方案
#1
3
Well, I am just as boggled. I performed some other tests and as far as I can see, this has to be some bug in the way the routes are checked when the constant before the route parameter has the same repeated character. Some other boggling examples:
好吧,我同样可怜。我执行了一些其他测试,据我所知,当路由参数之前的常量具有相同的重复字符时,这必须是检查路由的方式中的一些错误。其他一些令人难以置信的例子:
"nn{id}"
route matches (/nna0)
route doesn't match (/nnn0)
"nnn{id}"
route matches (/nnna0)
route doesn't match (/nnnn0)
as soon as i make the constant not repeat the same character, all is well
一旦我使常数不重复相同的字符,一切都很好
"mn{id}"
route matches (/mna0)
route matches (/mnn0)
route matches (/mnmn)
This may not be exactly what you are looking for. But given the oddity of the situation, it was the only thing I could come up with. Add the constant to the constraint and remove it from the url. Then in your controller (this is the part I didn't like) you will need to remove that constant from the id parameter. Hope this works, or at the least help spark another solution.
这可能不是您正在寻找的。但考虑到情况的怪异,这是我唯一能想到的。将常量添加到约束中并将其从URL中删除。然后在你的控制器中(这是我不喜欢的部分)你需要从id参数中删除该常量。希望这有效,或至少帮助激发另一种解决方案。
routes.MapRoute(
"NonBrandedSlideshow",
"{id}",
MVC.Slideshow.NonBranded(), null,
new { id = "n"+Settings.Base32Regex }
);
UPDATE:
I guess this is a known issue, thanks @max-toro
我想这是一个众所周知的问题,谢谢@ max-toro
#2
3
This is a known bug in ASP.NET Routing, see this answer for an explication and a workaround. In short, using literal sub-segments does not work very well.
这是ASP.NET路由中的已知错误,请参阅此答案以获取解释和解决方法。简而言之,使用文字子段不能很好地工作。
#3
2
I haven't had much success getting routes to match with prefixing a constant to a route parameter like "const{param}"
. Have you tried using your prefix as a complete route segment, like "const/{param}"
? Would that meet your requirements?
我没有太多成功获得匹配的路由,为路由参数添加前缀,例如“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 }
);
...etc?
Update after comment #1
评论#1后更新
Understood. The only other thing I can think of to try would involve making the id param a catchall parameter. See if that works:
了解。我能想到的另一件事就是让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 }
);
However, these routes should be registered late, so that the controller doesn't end up routing any URL prefixed with n, f, etc. to these controller actions.
但是,这些路由应该延迟注册,以便控制器不会将任何带有n,f等前缀的URL路由到这些控制器操作。
#4
1
have you tried matching them without the route contraint on the end?
你有没有试过匹配它们而没有路线约束?
EDIT: sorry for half an answer got interrupted
编辑:抱歉半个答案被打断了
you need to try this for a route constraint
你需要尝试这个路由约束
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]+"
}
);
rinse and repeat for each case, in your action method strip the first character off the front of the id
冲洗并重复每个案例,在你的动作方法中剥去id前面的第一个字符
#5
1
This is a workaround. A weird one, I think...
这是一种解决方法。一个奇怪的,我想......
As you routing rules are pretty simple, you can create a custom ControllerFactory
and check the url. if the url matches your way, you can define which controller and action to use, and set the id paramenter based on the url. If not, just leave the regular behavior.
由于路由规则非常简单,您可以创建自定义ControllerFactory并检查URL。如果url符合您的方式,您可以定义要使用的控制器和操作,并根据URL设置id参数。如果没有,只需保留常规行为即可。
I know, it won't make use of the out-of-the-box routing, but as it doesn't work... The good news is as soon as it's fixed you can update the routes, remove the custom ControllerFactory and continue without the workaround.
我知道,它不会使用开箱即用的路由,但因为它不起作用...好消息是,一旦它修复你可以更新路由,删除自定义ControllerFactory和继续没有解决方法。
#1
3
Well, I am just as boggled. I performed some other tests and as far as I can see, this has to be some bug in the way the routes are checked when the constant before the route parameter has the same repeated character. Some other boggling examples:
好吧,我同样可怜。我执行了一些其他测试,据我所知,当路由参数之前的常量具有相同的重复字符时,这必须是检查路由的方式中的一些错误。其他一些令人难以置信的例子:
"nn{id}"
route matches (/nna0)
route doesn't match (/nnn0)
"nnn{id}"
route matches (/nnna0)
route doesn't match (/nnnn0)
as soon as i make the constant not repeat the same character, all is well
一旦我使常数不重复相同的字符,一切都很好
"mn{id}"
route matches (/mna0)
route matches (/mnn0)
route matches (/mnmn)
This may not be exactly what you are looking for. But given the oddity of the situation, it was the only thing I could come up with. Add the constant to the constraint and remove it from the url. Then in your controller (this is the part I didn't like) you will need to remove that constant from the id parameter. Hope this works, or at the least help spark another solution.
这可能不是您正在寻找的。但考虑到情况的怪异,这是我唯一能想到的。将常量添加到约束中并将其从URL中删除。然后在你的控制器中(这是我不喜欢的部分)你需要从id参数中删除该常量。希望这有效,或至少帮助激发另一种解决方案。
routes.MapRoute(
"NonBrandedSlideshow",
"{id}",
MVC.Slideshow.NonBranded(), null,
new { id = "n"+Settings.Base32Regex }
);
UPDATE:
I guess this is a known issue, thanks @max-toro
我想这是一个众所周知的问题,谢谢@ max-toro
#2
3
This is a known bug in ASP.NET Routing, see this answer for an explication and a workaround. In short, using literal sub-segments does not work very well.
这是ASP.NET路由中的已知错误,请参阅此答案以获取解释和解决方法。简而言之,使用文字子段不能很好地工作。
#3
2
I haven't had much success getting routes to match with prefixing a constant to a route parameter like "const{param}"
. Have you tried using your prefix as a complete route segment, like "const/{param}"
? Would that meet your requirements?
我没有太多成功获得匹配的路由,为路由参数添加前缀,例如“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 }
);
...etc?
Update after comment #1
评论#1后更新
Understood. The only other thing I can think of to try would involve making the id param a catchall parameter. See if that works:
了解。我能想到的另一件事就是让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 }
);
However, these routes should be registered late, so that the controller doesn't end up routing any URL prefixed with n, f, etc. to these controller actions.
但是,这些路由应该延迟注册,以便控制器不会将任何带有n,f等前缀的URL路由到这些控制器操作。
#4
1
have you tried matching them without the route contraint on the end?
你有没有试过匹配它们而没有路线约束?
EDIT: sorry for half an answer got interrupted
编辑:抱歉半个答案被打断了
you need to try this for a route constraint
你需要尝试这个路由约束
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]+"
}
);
rinse and repeat for each case, in your action method strip the first character off the front of the id
冲洗并重复每个案例,在你的动作方法中剥去id前面的第一个字符
#5
1
This is a workaround. A weird one, I think...
这是一种解决方法。一个奇怪的,我想......
As you routing rules are pretty simple, you can create a custom ControllerFactory
and check the url. if the url matches your way, you can define which controller and action to use, and set the id paramenter based on the url. If not, just leave the regular behavior.
由于路由规则非常简单,您可以创建自定义ControllerFactory并检查URL。如果url符合您的方式,您可以定义要使用的控制器和操作,并根据URL设置id参数。如果没有,只需保留常规行为即可。
I know, it won't make use of the out-of-the-box routing, but as it doesn't work... The good news is as soon as it's fixed you can update the routes, remove the custom ControllerFactory and continue without the workaround.
我知道,它不会使用开箱即用的路由,但因为它不起作用...好消息是,一旦它修复你可以更新路由,删除自定义ControllerFactory和继续没有解决方法。