I’m not a huge fan of the fluent-API. I think it’s a pattern that’s been overused and is now applied like mayonnaise: people are putting it on things where it just doesn’t belong. That said, there are times when it’s useful. Case in point is building up an HTML snippet programmatically for use in ASP.NET MVC. Unfortunately, the handy TagBuilder class actually isn’t fluent (at all). Most of its methods return void. Fortunately it is quite easy to adapt the TagBuilder into a fluent version. Behold, FluentTagBuilder:
/// <summary> /// Wrapper for <see cref="TagBuilder"/> that makes /// it a fluent API. /// </summary> public class FluentTagBuilder { private TagBuilder mBuilder; public FluentTagBuilder(string tagName) { mBuilder = new TagBuilder(tagName); } public FluentTagBuilder MergeAttribute(string key, string value) { mBuilder.MergeAttribute(key, value); return this; } public FluentTagBuilder AddCssClass(string cssClass) { mBuilder.AddCssClass(cssClass); return this; } public string InnerHtml { get { return mBuilder.InnerHtml; } set { mBuilder.InnerHtml = value; } } public override string ToString() { return mBuilder.ToString(); } }
Note that I haven’t exposed all the underlying TagBuilder functionality, just the bits I needed today. Implementing the rest yourself should be trivial though. Here’s an example use in an HtmlHelper extension:
public FluentTagBuilder SuperSecretButton(string url, string altText) { FluentTagBuilder link = new FluentTagBuilder("a") .MergeAttribute("href", url) .MergeAttribute("target", "_blank"); FluentTagBuilder image = new FluentTagBuilder("img") .MergeAttribute("src", mHelper.ResolveUrl(SEEKRET_URL)) .MergeAttribute("alt", altText); link.InnerHtml = image.ToString(); return link; }
And the use of the helper in the view:
Html.MyHelper().SuperSecretButton("http://wherever", "I am a button").AddCssClass("analyzeCostResearch")
Note how the view can add a class (or potentially any other attribute) without clutering up the method signatures for the helper.