Car*_*arl 11 c# model-view-controller asp.net-mvc asp.net-mvc-2
我有一个问题,在这里几乎被问到:
asp.net mvc Html.ActionLink()保留我不想要的路由值
然而,最终的解决方案是一个纯粹而简单的kludge,我真的很想知道为什么会发生这种情况,如果有人可以向我解释一下呢?
为了完整起见,可以非常轻松地重新创建场景:
请注意,现在关于About的顶级菜单链接实际上链接到/ Home/About/Flib - 据我所知这是错误的,因为我现在绝对没有办法使用站点链接回到/ Home/About
我真的不明白为什么我应该被迫修改我的所有Html.ActionLinks以包含new { id = string.Empty }routevalues和null为htmlAttribs.这似乎特别糟糕,因为我已经指定id = 0了路线本身的一部分.
希望我在这里错过了一个技巧.
amu*_*rra 13
当您查看操作链接的源代码时,您会发现它
<%= Html.ActionLink("LinkText", "Action", "Controller"); %>
Run Code Online (Sandbox Code Playgroud)
会匹配
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName) {
return ActionLink(htmlHelper, linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary());
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,这看起来很好,因为它正在创建一个新的路由值字典,因此它不会传递当前上下文中的值以添加到新链接,这将会发生.
但是,在生成url的代码中进一步向下:
public static string GenerateUrl(string routeName, string actionName, string controllerName, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, bool includeImplicitMvcValues) {
if (routeCollection == null) {
throw new ArgumentNullException("routeCollection");
}
if (requestContext == null) {
throw new ArgumentNullException("requestContext");
}
RouteValueDictionary mergedRouteValues = RouteValuesHelpers.MergeRouteValues(actionName, controllerName, requestContext.RouteData.Values, routeValues, includeImplicitMvcValues);
VirtualPathData vpd = routeCollection.GetVirtualPathForArea(requestContext, routeName, mergedRouteValues);
if (vpd == null) {
return null;
}
string modifiedUrl = PathHelpers.GenerateClientUrl(requestContext.HttpContext, vpd.VirtualPath);
return modifiedUrl;
}
Run Code Online (Sandbox Code Playgroud)
你可以看到被引用的requestContext有权访问routeData和routeCollections,它们将包含id数据.创建VirtualPathForArea时,以下行是您的网址中显示的ID值:
internal static VirtualPathData GetVirtualPathForArea(this RouteCollection routes, RequestContext requestContext, string name, RouteValueDictionary values, out bool usingAreas) {
if (routes == null) {
throw new ArgumentNullException("routes");
}
if (!String.IsNullOrEmpty(name)) {
// the route name is a stronger qualifier than the area name, so just pipe it through
usingAreas = false;
return routes.GetVirtualPath(requestContext, name, values);
}
string targetArea = null;
if (values != null) {
object targetAreaRawValue;
if (values.TryGetValue("area", out targetAreaRawValue)) {
targetArea = targetAreaRawValue as string;
}
else {
// set target area to current area
if (requestContext != null) {
targetArea = AreaHelpers.GetAreaName(requestContext.RouteData);
}
}
}
// need to apply a correction to the RVD if areas are in use
RouteValueDictionary correctedValues = values;
RouteCollection filteredRoutes = FilterRouteCollectionByArea(routes, targetArea, out usingAreas);
if (usingAreas) {
correctedValues = new RouteValueDictionary(values);
correctedValues.Remove("area");
}
VirtualPathData vpd = filteredRoutes.GetVirtualPath(requestContext, correctedValues);
return vpd;
}
Run Code Online (Sandbox Code Playgroud)
这条线:
VirtualPathData vpd = filteredRoutes.GetVirtualPath(requestContext, correctedValues);
Run Code Online (Sandbox Code Playgroud)
获取虚拟路径(只是路径)并返回它.所以虚拟路径就是/Home/About/Flib
然后,当返回该虚拟路径时,以下行使用它来设置操作链接的客户端URL:
string modifiedUrl = PathHelpers.GenerateClientUrl(requestContext.HttpContext, vpd.VirtualPath);
Run Code Online (Sandbox Code Playgroud)
所以看起来动作链接是使用区域的虚拟路径设置的,这只是匹配的路径,在这种情况下恰好是默认路由.