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.
- <%= this.Html.RenderInput
- (
- Attributes.Configure()
- .AddType("submit")
- .AddId("submit_button")
- .AddName("submit.button")
- .AddCssClass("submitButtonCssClass")
- ) %>
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:
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.
- /// <summary>
- /// Class for creating a list of attributes.
- /// </summary>
- public class Attributes : RouteValueDictionary
- {
- /// <summary>
- /// Configures this instance.
- /// </summary>
- /// <returns></returns>
- public static Attributes Configure()
- {
- return new Attributes();
- }
- /// <summary>
- /// Adds the type.
- /// </summary>
- /// <param name="value">The value.</param>
- public Attributes AddType(string value)
- {
- this.Add("type", value);
- return this;
- }
- /// <summary>
- /// Adds the name.
- /// </summary>
- /// <param name="value">The value.</param>
- public Attributes AddName(string value)
- {
- this.Add("name", value);
- return this;
- }
- /// <summary>
- /// Adds the id.
- /// </summary>
- /// <param name="value">The value.</param>
- public Attributes AddId(string value)
- {
- this.Add("id", value);
- return this;
- }
- /// <summary>
- /// Adds the value.
- /// </summary>
- /// <param name="value">The value.</param>
- public Attributes AddValue(string value)
- {
- this.Add("value", value);
- return this;
- }
- /// <summary>
- /// Adds the CSS class.
- /// </summary>
- /// <param name="value">The value.</param>
- public Attributes AddCssClass(string value)
- {
- this.Add("class", value);
- return this;
- }
- }
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.
- /// <summary>
- /// Class for creating html input tags.
- /// </summary>
- public static class InputExtensions
- {
- /// <summary>
- /// Renders the input.
- /// </summary>
- /// <param name="html">The HTML.</param>
- /// <param name="attributes">The attributes.</param>
- public static string RenderInput(this HtmlHelper html, Attributes attributes)
- {
- TagBuilder input = new TagBuilder("input");
- input.MergeAttributes(attributes);
- return input.ToString(TagRenderMode.SelfClosing);
- }
- }
That’s pretty much it – I hope this is useful.
Kind Regards,
Sean McAlinden