Archive for the 'MVC' Category

Writing Custom MVC Html Helpers

Monday, June 10th, 2013

While the advantages of ASP.Net MVC over plain ASP.Net are numerous, one of the things that makes up for not having a graphical designer built-in to Visual Studio is the ease with which you can add controls using Html Helpers.  While the built-in helpers are very useful, the real power comes from the fact that you can extend this model simply by adding your own helpers.

One of the things missing from the built-in helpers is the ability to easily display a hyperlinked image.  So here is a helper that will do this for you:

public static MvcHtmlString ActionImageLink(this HtmlHelper helper, string imageUrl, string altText, string actionName, string controller, RouteValueDictionary routeValues, string _imageClass = "", object htmlAttributes = null)
{
var image = new TagBuilder("img");
image.MergeAttribute("src", imageUrl);
image.MergeAttribute("alt", altText);
if (string.IsNullOrEmpty(_imageClass) == false) image.MergeAttribute("class", _imageClass);
var link = helper.ActionLink("[replaceme]", actionName, controller, routeValues, htmlAttributes);
return new MvcHtmlString(link.ToHtmlString().Replace("[replaceme]", image.ToString(TagRenderMode.SelfClosing)));
}

You can simply copy this code into your project in a new static class and start using it right away.  For the rest of this article, I’m going to discuss what each line does and give some helpful hints on writing your own Html Helpers for MVC.

We’ll start by declaring our function, obviously public and static are necessary modifiers for the type of function we’re creating.  Setting the return type to MvcHtmlString is necessary for an HtmlHelper.  The name of our function is ActionImageLink to indicate that the link we’ll return will contain an image.  Notice that the first parameter is an HtmlHelper, this lets MVC know that this an extension to the HtmlHelper class and will get it to show this helper function as well when you type helper. in your view (as long as you have a using statement for the class this is a part of).   The rest of the parameters are pretty straightforward, they include the items needed for the image and for the ActionLink.

public static MvcHtmlString ActionImageLink(this HtmlHelper helper, string imageUrl, string altText, string actionName, string controller, RouteValueDictionary routeValues, string _imageClass = "", object htmlAttributes = null)
{

 

MVC includes a great object that greatly assists with creating html tags called TagBuilder, it takes care of the html syntax necessary for creating a tag.  Not that it’s complicated but it keeps us developing in an object oriented manner encapsulating this functionality in one place and making it so that we don’t have to do unnecessary string manipulation in every Html Helper we write.

var image = new TagBuilder("img");

 

Now that we have our image tag, which at this point would only write out “<img />”, we need to add attributes for the important items:

image.MergeAttribute("src", imageUrl);

image.MergeAttribute("alt", altText);

 

Now we come to our first optional parameter, we’ll check to see whether a real class name was passed in before merging this attribute.  If it’s blank then theirs not much point to adding it:

if (string.IsNullOrEmpty(_imageClass) == false)
image.MergeAttribute("class", _imageClass);

 

One of the great things about MVC Html Helpers is that we can use existing ones in our new extension.  This helps us to avoid rewriting existing functionality.  In this case, their is no reason to rewrite the functionality to create Action Links, so we’ll use the existing helper.  Notice that we’re passing in the first parameter as “[replaceme]“, this is the link text which we’ll want to replace with the image tag html in the next step:

var link = helper.ActionLink("[replaceme]", actionName, controller, routeValues, htmlAttributes);

 

And of course, now that we have the link, we’ll replace it with the image tag and then convert the entire html string into an MvcHtmlString to be returned  to the caller:

return new MvcHtmlString(link.ToHtmlString().Replace("[replaceme]", image.ToString(TagRenderMode.SelfClosing)));

 

ASP.Net MVC has set up a great environment that is easy to extend to add functionality.  While their are ongoing arguments as to when it is appropriate to simply code the html by hand; I lean towards an all or nothing approach for active elements.  It just doesn’t make sense to be hand-coding active elements on the page when the HtmlHelper pattern exists to encapsulate this functionality and makes it so easy to extend as you see in this example.