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,而不是添加辅助路由,它似乎也能正常工作,但我猜它可能会产生不需要的副作用。我也不确定这种行为是故意的,还是只是一个错误。)