Monday, July 7, 2014

ASP.net MVC ActionLink with Image: Part 1 (using Glyph)

If you are using ASP.net MVC you surely know that there is an helpful helper to create a link that points to an Action of a controller: it's the Html.ActionLink.

You can use this helper only with text, but what about if you want to add to the link a glyph image, like in this example?



Well, the "fast&dirty" answer is to write some html directly in the cshtml page. Something like:

<a href="@Url.Action("Edit", new { id = Model.id })">
  <i class="glyphicon glyphicon-pencil"></i>
  <span>Edit</span>
</a>


This approach is faster that any other, if you need to have it only in few places. But what about if you have to use it spread all around you application (as in my case?). You will have to copy&paste the code all around and then change it. Not so good...

The better way to do it, in this case, is to write a custom helper that will do it for you.

/// <summary>
/// Create an ActionLink with an associated glyphicon
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="linkText"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <param name="glyphicon"></param>
/// <param name="routeValues"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static MvcHtmlString ImageActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string glyphicon, object routeValues = null, object htmlAttributes = null)
{
 //Exemple of result:
 //<a href="@Url.Action("Edit", new { id = Model.id_rod })">
 //  <i class="glyphicon glyphicon-pencil"></i>
 //  <span>Edit</span>
 //</a>

 var builderI = new TagBuilder("i");
 builderI.MergeAttribute("class", "glyphicon " + glyphicon);
 string iTag = builderI.ToString(TagRenderMode.Normal);

 string spanTag = "";
 if (!string.IsNullOrEmpty(linkText))
 {
  var builderSPAN = new TagBuilder("span");
  builderSPAN.InnerHtml = " " + linkText;
  spanTag = builderSPAN.ToString(TagRenderMode.Normal);
 }            

 //Create the "a" tag that wraps
 var builderA = new TagBuilder("a");

 var requestContext = HttpContext.Current.Request.RequestContext;
 var uh = new UrlHelper(requestContext);
 
 builderA.MergeAttribute("href", uh.Action(actionName, controllerName, routeValues));

 if (htmlAttributes != null)
 {
  IDictionary<string, object> attributes = new RouteValueDictionary(htmlAttributes);
  builderA.MergeAttributes(attributes);
 }
  
 builderA.InnerHtml = iTag + spanTag;
 
 return new MvcHtmlString(builderA.ToString(TagRenderMode.Normal));
}

At this point it will be possible to invoke the Html.ImageActionLink helper in the same way and with the same parameters that we will use with the "normal" Html.ActionLink plus the glyphicon class of the glyph image we wanna add to the link.

3 comments:

Shaine MaGuire said...

I have been looking for something like this for a while. It works wonders. Thanks for the post.

Shaine MaGuire said...

By the way, the ActionLink I used in my MVC app after implementing this awesome code is:

@Html.ImageActionLink((string)ViewBag.Title, "Create", "Address", "glyphicon-plus", HTMLAttributes: new { @class = "btn btn-primary" })

Anonymous said...

Amazing! Works perfectly. I couldn't find any answers that were able to account for htmlAttributes before this - thank you!