MVC 忽略路由默认值并呈现完整的“/Home/Index”URL 而不是根
MVC ignores route defaults and renders full “/Home/Index” URLs instead of root
我的 ASP.NET MVC 项目似乎在 编写 URL 时忽略路由默认值。例如,Url.Action("Index", "Home")
returns /Home/Index/
,而它应该 return 只是 /
(我在所有其他 MVC 网站上都看到过)。 using URL 没有任何问题,例如通过访问 http://myserver/
,正确找到了默认控制器和操作。
我该如何解决这个问题? (请注意,我发现 questions 询问如何 实现 这种行为,但似乎没有人遇到这个相反的问题。)
项目没什么了不起,没有自定义路由处理器等,路由配置也很简单:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("LoginHandler");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{*id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
(存在 *
是因为某些操作使用任意字符串作为标识符,其中可能包含嵌入的斜杠,如果没有星号,则路由与此类 URL 不匹配。)
问题确实出在小星号上。这些 catch-all parameters 显然与 UrlParameter.Optional
默认值不匹配,导致 URL 始终包含整个路径。
如果您想保留默认行为,同时还允许使用 catch-all 参数语法的任意参数,则需要在辅助路由中使用 catch-all 参数 :
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("LoginHandler");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "CatchAll",
url: "{controller}/{action}/{*id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
使用此定义,不包含斜线的简单参数将使用第一条路线进行处理(与未指定要使用的确切路线时的 URL 代一样),而带有斜线的复杂参数将退回到第二条路线,并在那里得到正确处理。
(请注意,这可能只是 MVC 实现中的一个错误:对于 catch-all 参数,MVC 的 ParsedRoute.IsParameterRequired
returns null
作为默认参数值,然后根据路由默认值提供的 UrlParameter.Optional
进行测试,发现不同。因此,您可以更改路由定义以使用 id = null
默认值而不是 id = UrlParameter.Optional
,而不是添加辅助路由,它似乎也能正常工作,但我猜它可能会产生不需要的副作用。我也不确定这种行为是故意的,还是只是一个错误。)
我的 ASP.NET MVC 项目似乎在 编写 URL 时忽略路由默认值。例如,Url.Action("Index", "Home")
returns /Home/Index/
,而它应该 return 只是 /
(我在所有其他 MVC 网站上都看到过)。 using URL 没有任何问题,例如通过访问 http://myserver/
,正确找到了默认控制器和操作。
我该如何解决这个问题? (请注意,我发现 questions 询问如何 实现 这种行为,但似乎没有人遇到这个相反的问题。)
项目没什么了不起,没有自定义路由处理器等,路由配置也很简单:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("LoginHandler");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{*id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
(存在 *
是因为某些操作使用任意字符串作为标识符,其中可能包含嵌入的斜杠,如果没有星号,则路由与此类 URL 不匹配。)
问题确实出在小星号上。这些 catch-all parameters 显然与 UrlParameter.Optional
默认值不匹配,导致 URL 始终包含整个路径。
如果您想保留默认行为,同时还允许使用 catch-all 参数语法的任意参数,则需要在辅助路由中使用 catch-all 参数 :
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("LoginHandler");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "CatchAll",
url: "{controller}/{action}/{*id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
使用此定义,不包含斜线的简单参数将使用第一条路线进行处理(与未指定要使用的确切路线时的 URL 代一样),而带有斜线的复杂参数将退回到第二条路线,并在那里得到正确处理。
(请注意,这可能只是 MVC 实现中的一个错误:对于 catch-all 参数,MVC 的 ParsedRoute.IsParameterRequired
returns null
作为默认参数值,然后根据路由默认值提供的 UrlParameter.Optional
进行测试,发现不同。因此,您可以更改路由定义以使用 id = null
默认值而不是 id = UrlParameter.Optional
,而不是添加辅助路由,它似乎也能正常工作,但我猜它可能会产生不需要的副作用。我也不确定这种行为是故意的,还是只是一个错误。)