Как добавить хеш-фрагмент в словарь маршрутов T4MVC ActionResult?

У меня есть метод расширения, который возвращает ActionResult (упрощенный для демонстрационных целей):

public static ActionResult GetTestActionResult(this HtmlHelper htmlHelper, int productId)
{
    return MVC.Products.Details(productId);
}

Я использую это в Html.ActionLink:

@Html.ActionLink("Product Details", Html.GetTestActionResult(Model.ProductId), new { @class = "button blue" });

Я использую пользовательский плагин jQuery для вкладок, который использует эти хеш-фрагменты для навигации. Я хочу добавить вкладку, которую хочу открыть, пометив фрагмент хеша в конце URL.

Html.ActionLink имеет перегрузку для фрагмента, а именно:

public static MvcHtmlString ActionLink(
    this HtmlHelper htmlHelper,
    string linkText,
    string actionName,
    string controllerName,
    string protocol,
    string hostName,
    string fragment,
    Object routeValues,
    Object htmlAttributes
)

Тем не менее, он полон неприятных магических строк, которые T4MVC предназначен для удаления. Есть ли способ добавить фрагмент в словарь маршрутов в моем методе статического расширения (GetTestActionResult)?

Что-то вроде:

return MVC.Products.Details(productId).AddRouteValue(String.Empty, "#tab-similar-products");

Я знаю, что есть два похожих вопроса и ответа на SO, но они не совсем дают мне то, что я ищу. Мне нужно обернуть фрагмент в ActionResult ПЕРЕД передачей его обратно в представление:

  1. Включение хеш-значений в URL-маршруты ASP.NET MVC
  2. Создать T4MVC ActionLink с фрагментом URL

ОБНОВИТЬ:

Используя приведенное ниже исправление Дэвида Эббо, я внес следующие изменения. Немного бестолково, но это работает:

Сначала я изменил свою внутреннюю функцию, которая возвращает ActionResult, чтобы он также добавил фрагмент в качестве значения маршрута (не идеально, но работает):

return MVC.Products.Details(productId).AddRouteValue("tab", "#tab-similar-products");

Затем в представлении он копирует это значение фрагмента из словаря маршрутов, а затем удаляет это значение маршрута для полноты.

// get my ActionResult with the tab fragment tagged on as a route value
var actionResult = Html.GetTestActionResult(item.Key, Model.ClaimId);

// get the tab fragment value
var tabRoute = actionResult.GetRouteValueDictionary().FirstOrDefault(r => r.Key == "tab").Value ?? "none";

// remove the route value, otherwise it will get tagged to the querystring
actionResult.GetRouteValueDictionary().Remove("tab");

// display
@Html.ActionLink("Product Details", Html.GetTestActionResult(Model.ProductId), new { @class = "button blue" }, fragment: tabRoute.ToString());

Я уверен, что есть более красивый способ вернуть фрагмент с помощью ActionResult, но на данный момент это работает. Спасибо Дэвид.

1 ответ

Решение

T4MVC нужны новые перегрузки, чтобы справиться с этим. В T4MVC.tt попробуйте изменить:

public static <#=HtmlStringType #> ActionLink(this HtmlHelper htmlHelper, string linkText, ActionResult result, object htmlAttributes) {
  return ActionLink(htmlHelper, linkText, result, new RouteValueDictionary(htmlAttributes));
}

public static <#=HtmlStringType #> ActionLink(this HtmlHelper htmlHelper, string linkText, ActionResult result, IDictionary<string, object> htmlAttributes) {
  return htmlHelper.RouteLink(linkText, result.GetRouteValueDictionary(), htmlAttributes);
}

в

public static <#=HtmlStringType #> ActionLink(this HtmlHelper htmlHelper, string linkText, ActionResult result, object htmlAttributes, string protocol = null, string hostName = null, string fragment = null) {
  return ActionLink(htmlHelper, linkText, result, new RouteValueDictionary(htmlAttributes), protocol, hostName, fragment);
}

public static <#=HtmlStringType #> ActionLink(this HtmlHelper htmlHelper, string linkText, ActionResult result, IDictionary<string, object> htmlAttributes, string protocol = null, string hostName = null, string fragment = null) {
  return htmlHelper.RouteLink(linkText, null, protocol, hostName, fragment, result.GetRouteValueDictionary(), htmlAttributes);
}

тогда вы сможете написать что-то вроде:

@Html.ActionLink("Product Details", Html.GetTestActionResult(Model.ProductId), new { @class = "button blue" }, fragment: "#tab-similar-products")

Дайте мне знать, если это работает, и я постараюсь добавить его в основной шаблон.

Другие вопросы по тегам