Добавить к routeValues ​​в методе расширения HtmlHelper - PullRequest
7 голосов
/ 03 февраля 2012

Я хочу создать простое расширение HtmlHelper.ActionLink, которое добавляет значение в словарь значений маршрута. Параметры будут идентичны HtmlHelper.ActionLink, то есть:

public static MvcHtmlString FooableActionLink(
    this HtmlHelper html,
    string linkText,
    string actionName,
    string controllerName,
    object routeValues,
    object htmlAttributes)
{
  // Add a value to routeValues (based on Session, current Request Url, etc.)
  // object newRouteValues = AddStuffTo(routeValues);

  // Call the default implementation.
  return html.ActionLink(
      linkText, 
      actionName, 
      controllerName, 
      newRouteValues, 
      htmlAttributes);
}

Логика того, что я добавляю к routeValues, довольно многословна, поэтому я хочу поместить его в помощник метода расширения вместо того, чтобы повторять его в каждом представлении.

У меня есть решение, которое работает (опубликовано как ответ ниже), но:

  • Это кажется излишне сложным для такой простой задачи.
  • Все кастинги кажутся мне хрупкими, как в некоторых крайних случаях, когда я собираюсь вызвать исключение NullReferenceException или что-то в этом роде.

Пожалуйста, оставляйте любые предложения по улучшению или улучшению решения.

1 Ответ

12 голосов
/ 03 февраля 2012
public static MvcHtmlString FooableActionLink(
    this HtmlHelper html,
    string linkText,
    string actionName,
    string controllerName,
    object routeValues,
    object htmlAttributes)
{
    // Convert the routeValues to something we can modify.
    var routeValuesLocal =
        routeValues as IDictionary<string, object>
        ?? new RouteValueDictionary(routeValues);

    // Convert the htmlAttributes to IDictionary<string, object>
    // so we can get the correct ActionLink overload.
    IDictionary<string, object> htmlAttributesLocal =
        htmlAttributes as IDictionary<string, object>
        ?? new RouteValueDictionary(htmlAttributes);

    // Add our values.
    routeValuesLocal.Add("foo", "bar");

    // Call the correct ActionLink overload so it converts the
    // routeValues and htmlAttributes correctly and doesn't 
    // simply treat them as System.Object.
    return html.ActionLink(
        linkText,
        actionName,
        controllerName,
        new RouteValueDictionary(routeValuesLocal),
        htmlAttributesLocal);
}
...