У меня есть вопрос, который в значительной степени задали здесь:
asp.net mvc HTML. ActionLink () сохраняющий маршрут оценивают, я не хочу
Однако конечным решением является клудж, чистый и простой, и я действительно хотел бы понять, почему это происходит, если кто-то может объяснить это мне?
Для полноты возможно воссоздать сценарий очень легко:
Заметьте, что главное меню связывается с приблизительно, теперь на самом деле связывается с/Home/About/Flib - это неправильно насколько я вижу, поскольку у меня теперь нет абсолютно никакого способа использовать ссылки сайта для возвращения к/Home/About
Я действительно не понимаю, почему я должен быть вынужден изменить весь свой HTML. ActionLinks для включения new { id = string.Empty }
для routevalues и пустого указателя для htmlAttribs. Это кажется особенно в неисправном состоянии, потому что я уже указываю id = 0
как часть самого маршрута.
Надо надеяться, я пропускаю прием здесь.
Когда вы просматриваете исходный код ссылки действия, вы обнаруживаете, что
<%= Html.ActionLink("LinkText", "Action", "Controller"); %>
будет соответствовать
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName) {
return ActionLink(htmlHelper, linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary());
}
. Пока что это выглядит хорошо, поскольку создается новый словарь значений маршрута, поэтому он не передает значения в вашем текущий контекст будет добавлен к новой ссылке, что и произойдет.
Однако ниже в коде, где создается 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;
}
вы можете увидеть, на что ссылается requestContext, который имеет доступ к routeData и routeCollections, которые будут содержать данные идентификатора. При создании VirtualPathForArea в следующей строке указывается значение идентификатора в вашем URL-адресе:
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;
}
Строка:
VirtualPathData vpd = filteredRoutes.GetVirtualPath(requestContext, correctedValues);
берет виртуальный путь (который является просто маршрутом) и возвращает его. Таким образом, виртуальный путь будет / Home / About / Flib
Затем, когда этот виртуальный путь будет возвращен, следующая строка использует его для установки URL-адреса клиента для ссылки действия:
string modifiedUrl = PathHelpers.GenerateClientUrl(requestContext.HttpContext, vpd.VirtualPath);
В общем, это похоже на actionlink задается с использованием виртуального пути для области, который является просто совпавшим маршрутом, который в данном случае является маршрутом по умолчанию.
Если я правильно понимаю, похоже, вам нужно зарегистрировать второй маршрут «Только действие» и использовать Html.RouteLink. Сначала зарегистрируйте такой маршрут при запуске приложения:
routes.MapRoute("ActionOnly", "{controller}/{action}", new { controller = "Home", action = "Index" } );
Затем вместо ActionLink для создания этих ссылок используйте:
Html.RouteLink("About","ActionOnly")