Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Append to routeValues in HtmlHelper extension method

I want to create a simple extension of HtmlHelper.ActionLink that adds a value to the route value dictionary. The parameters would be identical to HtmlHelper.ActionLink, i.e.:

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);
}

The logic for what I am adding to routeValues is somewhat verbose, hence my desire to put it in an extension method helper instead of repeating it in each view.

I have a solution that seems to be working (posted as an answer below), but:

  • It seems to be unnecessarily complicated for such a simple task.
  • All the casting strikes me as fragile, like there are some edge cases where I'm going to be causing a NullReferenceException or something.

Please post any suggestions for improvement or better solutions.

like image 340
Dave Mateer Avatar asked Feb 03 '12 14:02

Dave Mateer


1 Answers

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);
}
like image 64
Dave Mateer Avatar answered Nov 11 '22 03:11

Dave Mateer