Fluent Html Helpers In Asp.Net MVC

I’ve been spending a fair amount of time recently developing client side controls for use with the Asp.Net MVC framework and have realised that they are great place to make use of the fluent interface pattern.

Now I realise that a lot of people shy away from using the fluent interface pattern as it can sometimes mean a little more work in terms of initial build and maintenance but I am personally finding they are absolutely worth the effort when creating html helper extensions.

Anyway, I’ve recently been working on a number of large controls such as grid views and text editors which would be way to much code to demonstrate here so I’ve put together a really contrived example just to demonstrate the fluent interface pattern in action – this is not a production control as it’s pretty useless but it will hopefully provide a nice insight into how I’m using the pattern.

The contrived example:

I’m going to create a really minimal helper that creates an input html control.

Firstly, the following example shows the general fluent syntax that is used to configure the control with the required html attributes – hopefully you will like the way it looks enough to read on and give it a go yourself.

  1. <%= this.Html.RenderInput
  2.     (
  3.         Attributes.Configure()
  4.             .AddType("submit")
  5.             .AddId("submit_button")
  6.             .AddName("submit.button")
  7.             .AddCssClass("submitButtonCssClass")
  8.     ) %>

As you can see I’ve created a submit button with an id, name and CSS class – hopefully the fluent style has made it both really clean and easy to understand the intention of the control configuration.

The html generated by this configuration is the following:

<input class="submitButtonCssClass" id="submit_button" name="submit.button" type="submit" />

The Attributes Class

The Attributes class does all the fluent work for this simple control.

Basically in this case the class is a custom collection inheriting from the RouteValueDictionary class.

  1.     /// <summary>
  2.     /// Class for creating a list of attributes.
  3.     /// </summary>
  4.     public class Attributes : RouteValueDictionary
  5.     {
  6.  
  7.         /// <summary>
  8.         /// Configures this instance.
  9.         /// </summary>
  10.         /// <returns></returns>
  11.         public static Attributes Configure()
  12.         {
  13.             return new Attributes();
  14.         }
  15.  
  16.         /// <summary>
  17.         /// Adds the type.
  18.         /// </summary>
  19.         /// <param name="value">The value.</param>
  20.         public Attributes AddType(string value)
  21.         {
  22.             this.Add("type", value);
  23.             return this;
  24.         }
  25.  
  26.         /// <summary>
  27.         /// Adds the name.
  28.         /// </summary>
  29.         /// <param name="value">The value.</param>
  30.         public Attributes AddName(string value)
  31.         {
  32.             this.Add("name", value);
  33.             return this;
  34.         }
  35.  
  36.         /// <summary>
  37.         /// Adds the id.
  38.         /// </summary>
  39.         /// <param name="value">The value.</param>
  40.         public Attributes AddId(string value)
  41.         {
  42.             this.Add("id", value);
  43.             return this;
  44.         }
  45.  
  46.         /// <summary>
  47.         /// Adds the value.
  48.         /// </summary>
  49.         /// <param name="value">The value.</param>
  50.         public Attributes AddValue(string value)
  51.         {
  52.             this.Add("value", value);
  53.             return this;
  54.         }
  55.  
  56.         /// <summary>
  57.         /// Adds the CSS class.
  58.         /// </summary>
  59.         /// <param name="value">The value.</param>
  60.         public Attributes AddCssClass(string value)
  61.         {
  62.             this.Add("class", value);
  63.             return this;
  64.         }
  65.     }

As a quick explanation of what is going on:

The static Configure method works a little bit like a factory method – it’s sole purpose is to create and return a new instance of the Attributes class, this starts off the fluent interface pattern.

All of the other methods simple add a name – value pair to the base RouteValueDictionary and return the current instance of the Attributes class, this completes the fluent interface.

The Helper Extension

Although writing the helper extension is probably fairly simple, I’ll put here for good measure to finish off the example, it literally just uses the TagBuilder class to build up the input control and then merges all the attributes added via the fluent methods.

  1.     /// <summary>
  2.     /// Class for creating html input tags.
  3.     /// </summary>
  4.     public static class InputExtensions
  5.     {
  6.         /// <summary>
  7.         /// Renders the input.
  8.         /// </summary>
  9.         /// <param name="html">The HTML.</param>
  10.         /// <param name="attributes">The attributes.</param>
  11.         public static string RenderInput(this HtmlHelper html, Attributes attributes)
  12.         {
  13.             TagBuilder input = new TagBuilder("input");
  14.             input.MergeAttributes(attributes);
  15.             return input.ToString(TagRenderMode.SelfClosing);
  16.         }
  17.     }

 

That’s pretty much it – I hope this is useful.

Kind Regards,

Sean McAlinden

www.asp-net-mvc.com

6 Comments

  • Too complicated frame is not friendly to your next mate.
    sometimes, easy means easy to understand, and easy to read.

  • Hi Charlie,

    Not 100% sure what you mean.. when I was talking about it being easy to understand, I was making reference to having clear intention with the names of the fluent methods such as AddName, AddCssClass etc. This becomes especially useful when working on more complicated controls where there is a great deal more configuration required to get it going.
    This example is really just a basic primer to using the fluent interface style.

  • Just use MvcContrib.FluentHtml and don't try to reinvent the wheel.

    But yeah - fluent api is great.

  • Hi Arnis,

    This blog has nothing to do with the contrib fluent project at all? this is a primer for people/juniors interested in building fluent helpers - especially when about to embark on complicated controls - the fluent contrib project is failry specific in what it's doing - the example might be something you can do with the contrib project but that wasn't the point of the blog...

  • I guess the only thing I'd change would be AddType to just Type. Why have an additional "Add" to everything?

  • Hi Willie T,
    I think that's good advice - much more succinct.
    Thanks
    Sean.

Comments have been disabled for this content.