UrlHelper.Action 等同于 UrlHelper.RouteUrl 吗?

Is UrlHelper.Action Equivalent to UrlHelper.RouteUrl?

我想替换 UrlHelper.Action with UrlHelper.RouteUrl in my code because of the performance benefits 的所有实例。根据文档,这两种方法都会生成完全合格的 URL,我想确认它们 return 与 完全 相同 URL。


示例:

假设 RouteConfig 中的路线具有唯一的 controlleraction 组合:

给定 RouteConfig 中的以下路线:

routes.MapRoute(
    "RouteName",
    "Url",
    new { controller = "Controller", action = "Action" }
);

假设

安全吗
urlHelper.Action("Action", "Controller", routeValueDictionary);

完全等同于

urlHelper.RouteUrl("RouteName", routeValueDictionary);

一旦您显示的地图上方没有映射的路线可以匹配从

生成的路线
urlHelper.Action("Action", "Controller", routeValueDictionary);

那么您在使用路由名称时的假设是安全的。

例如,如果您有两条这样定义的路由...

routes.MapRoute(
    "AnotherRouteName",
    "{controller}/blah/{action}",
    new { controller = "Controller", action = "Action" }
);

routes.MapRoute(
    "RouteName",
    "Url",
    new { controller = "Controller", action = "Action" }
);

...那么第一条路线将匹配..

urlHelper.Action("Action", "Controller", routeValueDictionary);

更新:

如果您查看 UrlHelper

的来源

您会注意到,在内部它们使用相关参数调用相同方法的相同重载。

public virtual string Action(string actionName, string controllerName, object routeValues)
{
    return GenerateUrl(null /* routeName */, actionName, controllerName, TypeHelper.ObjectToDictionary(routeValues));
}

public virtual string Action(string actionName, string controllerName, RouteValueDictionary routeValues)
{
    return GenerateUrl(null /* routeName */, actionName, controllerName, routeValues);
}

//...other code removed for brevity

public virtual string RouteUrl(string routeName, object routeValues, string protocol)
{
    return GenerateUrl(routeName, null /* actionName */, null /* controllerName */, protocol, null /* hostName */, null /* fragment */, TypeHelper.ObjectToDictionary(routeValues), RouteCollection, RequestContext, false /* includeImplicitMvcValues */);
}

这里 post 的代码太多了。查看 class 源代码以更好地了解引擎盖下发生的事情。

无法提供比这更多的细节。我一直回到源代码。

不,不完全是。

urlHelper.RouteUrl 仅向路由添加一个额外的过滤器。您仍然必须提供匹配参数(包括 controlleraction),否则它将 return null 而不是您期望的 URL。

urlHelper.RouteUrl("RouteName", 
    new { controller = "Controller", action = "Action"[, other route values... ]);

主要区别在于此过滤器只会让路由框架检查 一个 路由,而不是按顺序检查所有路由。这使得在生成 URLs 时不可能匹配错误的路由,但是传入的请求仍然有可能通过以错误的顺序将它们放在路由 table 中来匹配错误的路由 - 这意味着你可以可能会从路由 table 中生成 URLs,但实际上无法在应用程序中访问。

Unless you have thousands of routes in your route table, it is unlikely you will see any noticeable performance difference.

这是否有任何实际好处值得怀疑。事实上,ActionRouteUrl 最终都在 UrlHelper 中调用了完全相同的方法来生成 URL。无论您使用 Action 还是 RouteUrl 来生成 URLs,您仍然应该 make unit tests 以确保传入路由与您想要的路由匹配并且 return 正确的一组路由值。

RouteUrl 确实有一个 Action 没有的好处——你可以传递 null 作为路由名称(或者调用没有路由名称的重载),这允许你向它传递一组现成的路由值,而不必为 controlleraction 显式设置单独的参数。这使得 RouteUrl 的行为与 Action 完全相同,但更容易与动态操纵路由值的代码集成。

urlHelper.RouteUrl(routeValueDictionary);