ASP.NET MVC站点附带以下默认root,在访问站点的根目录时执行Home控制器的Index操作(例如http://localhost:12345
)
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
那么当没有找到路线时,这是一种后备吗?
没那么快。如果我们尝试导航到http://localhost/a/b
(没有'a'控制器存在),它将不会执行Home控制器的Index操作 - 将返回错误。
为什么在那种情况下无法执行Home / Index - 但在路径中输入绝对没有执行Home / Index?
这里的逻辑是什么 - 为什么这条路线被称为'默认'?
我看过很多文章都涉及到路由 - 但不是解释这个问题的文章。
相关问题
在其他情况下,'默认'中的内容似乎更像是路线的映射。例如
url: "abc/def", defaults: new { controller = "bongo", action = "bingo" }
这只是在bongo控制器上执行宾果动作 - 只要输入了确切的URL“abc / def”。为什么称它为“默认值” - 这个术语似乎并不适合。 (删除'默认值'有没有效果,我已经看到它被省略了。)
在默认路线中,它似乎更像是后备,在后一个例子中更像是一个映射?
我觉得我在这里缺少概念层面的东西。
THX。
答案 0 :(得分:2)
逻辑虽然起初不是很直观,但实际上非常简单。
通常,当传入请求发生时,会发生两种不同的事情。
当传入请求发生时,MVC在路由表中执行第一条路由的GetRouteData
方法。如果它不匹配,它将尝试第二个,第三个,依此类推,直到找到匹配为止。
如果路由表中最终没有匹配项,则RouteCollection.GetRouteData
(调用每条路由的GetRouteData
的方法)将返回null
。如果找到匹配,则匹配路由的路由值将返回到MVC,在MVC中,它使用它们来查找控制器和要执行的操作。请注意,在这种情况下,不会检查路由表中的其他路由以进行匹配。换句话说,第一场比赛总是胜利。
匹配过程依赖于三件事:
您要问的部分是占位符以及没有值时它们匹配的原因。占位符(即{controller}
)就像变量一样。他们会接受任何价值。它们可以初始化为默认值。如果它们未初始化为默认值,则必须位于URL 中才能匹配。
考虑路线定义中的defaults
:
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
如果URL 中未提供占位符,则这些值将用作(作为RouteValues中的匹配和输出)。
按照同样的逻辑,默认情况下,所有这些网址都会到达HomeController.Index
操作方法。
/
/Home
/Home/Index
/Home/Index/Foo
/Home/Index/123
网址:
/
如果您将网址/
传递给框架,它会匹配Default
路由并将其发送到HomeController.Index
方法,因为默认值为如果没有提供,则Home
和Index
。在这种情况下,路线值为:
| Key | Value |
|-------------|-------------|
| controller | Home |
| action | Index |
| id | {} |
网址
/Home
请注意,您也可以只传递控制器名称/Home
。路线表看起来完全一样。
| Key | Value |
|-------------|-------------|
| controller | Home |
| action | Index |
| id | {} |
但是,在这种情况下,controller
值将通过URL中的占位符传递。它不再考虑路由的默认controller
值,因为URL中已提供了值。
网址:
/Test
遵循相同的逻辑,URL /Test
将产生以下路由表。
| Key | Value |
|-------------|-------------|
| controller | Test |
| action | Index |
| id | {} |
路由不会自动检查控制器是否确实存在。它只是提供价值。如果您的应用程序中没有名为TestController
并且Index
操作的控制器,则会导致错误。
这就是您在上面提供的网址/a/b
无法正常工作的原因 - 您的项目中没有名为AController
的控制器,其操作名为B
。
如果占位符未初始化为默认值,则必须位于URL 中才能使路径匹配。
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional }
);
因此,根据上述路线,它将匹配网址/Home
:
| Key | Value |
|-------------|-------------|
| controller | Home |
| action | Index |
| id | {} |
但它不会匹配网址/
,因为控制器没有默认值。
routes.MapRoute(
name: "Foo",
url: "abc/def",
defaults: new { controller = "bongo", action = "bingo" }
);
以上路线在网址中使用文字段。文字段需要精确匹配(不区分大小写)才能将路径视为匹配。因此,唯一匹配的网址是abc/def
或这两个网段的任何大写/小写组合。
但是,这种情况在一方面有所不同。 无法通过网址传递值。因此,必须设置默认值(至少为controller
和action
),以便将任何路由值传递给MVC。
| Key | Value |
|-------------|-------------|
| controller | bongo |
| action | bingo |
MVC框架要求BongoController
有一个名为Bingo
的动作,否则这条路线将失败。
约束是额外条件,这是路线匹配所必需的。每个约束都返回一个布尔(匹配/不匹配)响应。每条路线可以有0到多个约束。
routes.MapRoute(
name: "CustomRoute",
url: "{placeholder1}/{action}/{id}",
defaults: new { controller = "MyController" },
constraints: new { placeholder1 = @"^house$|^car$|^bus$" }
);
匹配
/house/details/123
/car/foo/bar
/car/bar/foo
不匹配
/house/details
/bank/details/123
/bus/foo
/car
/
public class CorrectDateConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var year = values["year"] as string;
var month = values["month"] as string;
var day = values["day"] as string;
DateTime theDate;
return DateTime.TryParse(year + "-" + month + "-" + day, System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.None, out theDate);
}
}
routes.MapRoute(
name: "CustomRoute",
url: "{year}/{month}/{day}/{article}",
defaults: new { controller = "News", action = "ArticleDetails" },
constraints: new { year = new CorrectDateConstraint() }
);
注意:约束分配给的值(在上面的例子year =
中)与传递给自定义约束的值相同。但是,自定义约束没有义务使用此值。有时使用任何值都没有意义,在这种情况下,您可以在controller
上设置约束。
匹配
/2012/06/20/some-great-article
/2016/12/25/all-about-christmas
不匹配
/2012/06/33/some-great-article
/2012/06/20
/99999/09/09/the-foo-article
在大多数情况下,只要网址中有占位符(例如{controller}
或{something}
),就应该使用约束,以防止它们与不应匹配的值匹配39;吨
文字段(或带有占位符的部分文字段),约束和所需值通常都是非常好在路由设置中使用的东西。它们有助于确保您的路线在如此宽的范围内不匹配,以阻止在路线表中执行在其后面注册的路线。
占位符匹配任何值,因此除非与约束一起使用,否则通常不建议在任何路径中仅使用占位符,而是使用
Default
路径。 StackOverflow上的许多人建议完全删除Default
路径,以确保无意识的路由不起作用,我不一定不同意这种情绪。