{"id":1431,"date":"2012-10-24T00:00:00","date_gmt":"2012-10-24T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/writing-custom-html-helpers-for-asp-net-mvc\/"},"modified":"2021-05-17T18:34:58","modified_gmt":"2021-05-17T18:34:58","slug":"writing-custom-html-helpers-for-asp-net-mvc","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/writing-custom-html-helpers-for-asp-net-mvc\/","title":{"rendered":"Writing Custom HTML Helpers for ASP.NET MVC"},"content":{"rendered":"<div id=\"pretty\">\n<p class=\"start\">As a web forms developer, I found the transition to MVC to be a bit of a shock at first. Without fully understanding the nature of MVC, I found the lack of a Toolbox filled with server controls to be confusing. However, once it became clear that the goal of MVC was to expose HTML markup and give developers full control over what is rendered to the browser, I quickly embraced the idea.<\/p>\n<h2>Transitioning from Web Forms<\/h2>\n<p>In MVC development, HTML helpers replace the server control, but the similarities aren&#8217;t exactly parallel. Whereas web forms and server controls were intended to bring the workflow of desktop forms to the web, MVC&#8217;s HTML helpers simply provide a shortcut to writing out raw HTML elements that are frequently used.<\/p>\n<p>The HTML helper, in most cases, is a method that returns a string. When we call a helper in a View using the razor syntax <strong>@Html<\/strong>, we are accessing the Html property of the View, which is an instance of the HtmlHelper class.<\/p>\n<p>Writing extensions for the <strong>HtmlHelper<\/strong> class will allow us to create our own custom helpers to encapsulate complex HTML markup. Custom helpers also promote the use of reusable code and are unit testable. Custom helpers can be configured by passing values to the constructor, via fluent configuration, strongly typed parameters, or a combination of both, and ultimately return a string. <\/p>\n<h2>How to Begin<\/h2>\n<p>The first step in writing an HTML helper is finding code within our project that you intend on reusing. For the extent of this article I will be using an alert message as an example. The Alert is a UI element that displays a message which has a default, success, warning, or information style. The Alert element&#8217;s markup is simple in construction but gives us an adequate sample for the scope of this article.<\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1588-alert-box.jpg\" alt=\"1588-Alert-box.jpg\" \/><\/p>\n<p>With our code targeted, we&#8217;ll examine the alert markup and see how we can break it down and construct reusable pieces of content. The alert is made up of a div container, a message, a close button and can have multiple styles applied to it. If we examine the markup, we can see that there are parts of the element that are static, and parts that can be broken down into options that can be set as parameters. <\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1588-markup-details.jpg\" alt=\"1588-markup-details.jpg\" \/><\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1588-parameter-breakdown.jpg\" alt=\"1588-parameter-breakdown.jpg\" \/><\/p>\n<p><em>In addition to the HTML, the alert will require CSS and JavaScript in order to function. The CSS and JavaScript are beyond the scope of this article but are included in the final example at the end of this article.<\/em><\/p>\n<h2>Writing a Specification<\/h2>\n<p>Personally, once I have my HTML defined, I prefer to start writing a specification before I do anything else. Writing a specification isn&#8217;t a necessary step for creating a custom HTML helper, but it gives me a guide to how the HTML helper will function and what the desired syntax will be. A spec will also promote the use of semantic code, which improves discoverability for others that may be using the helper.<\/p>\n<p>Using a text file, I spec out how the helper will function and, since I will be unit testing the code, I&#8217;ll save the spec to my test project. There are several parameters that will be required to configure the Alert element: the text to be displayed, the style of the alert, and a close button that can be toggled. I&#8217;ll also be giving the Alert a default configuration that will only require that the text parameter be set. In addition to the elements configuration, custom attributes will be configurable through the <strong>htmlAttributes<\/strong> parameter as an anonymous object. Each configuration of the <strong>Alert<\/strong> helper is written out in the spec so it can be followed during implementation.<\/p>\n<pre>\/\/Given the Alert HTML Helper method\r\n\r\n\/\/Then Render the HTML\r\n\r\n\/\/Default Alert\r\n@Html.Alert(text:\"message\") [.HideCloseButton()]\r\n\r\n&lt;div class=\"alert-box\"&gt;\r\n&#160;&#160;&#160;&#160;Message\r\n&#160;&#160;&#160;&#160;&lt;a href=\"\" class=\"close\"&gt;&#215;&lt;\/a&gt;\r\n&lt;\/div&gt;\r\n\r\n\/\/Success Alert\r\n\r\n@Html.Alert(text:\"message\", style:AlertStyle.Success [,hideCloseButton:false ,htmlAttributes:object])\r\n\r\n&lt;div class=\"alert-box success\"&gt;\r\n&#160;&#160;&#160;&#160;Message\r\n&#160;&#160;&#160;&#160;&lt;a href=\"\" class=\"close\"&gt;&#215;&lt;\/a&gt;\r\n&lt;\/div&gt;\r\n\r\n\/\/Warning Alert\r\n\r\n@Html.Alert(text:\"message\", style:AlertStyle.Warning [,hideCloseButton:false ,htmlAttributes:object])\r\n\r\n&lt;div class=\"alert-box warning\"&gt;\r\n&#160;&#160;&#160;&#160;Message\r\n&#160;&#160;&#160;&#160;&lt;a href=\"\" class=\"close\"&gt;&#215;&lt;\/a&gt;\r\n&lt;\/div&gt;\r\n\r\n\/\/Info Alert\r\n\r\n@Html.Alert(text:\"message\", style:AlertStyle.Info [,hideCloseButton:false ,htmlAttributes:object])\r\n\r\n&lt;div class=\"alert-box info\"&gt;\r\n&#160;&#160;&#160;&#160;Message\r\n&#160;&#160;&#160;&#160;&lt;a href=\"\" class=\"close\"&gt;&#215;&lt;\/a&gt;\r\n&lt;\/div&gt; <\/pre>\n<h2>Unit Testing<\/h2>\n<p>ASP.NET MVC is highly regarded for its ability to be unit tested, and custom HTML helpers can be thoroughly tested too. With the right setup, unit testing your custom helper isn&#8217;t difficult: <\/p>\n<p>First, we need to create an instance of the <strong>HtmlHelper<\/strong> class so our extension method can be tested. Next, the custom method is called, and finally we can check the results against our expectations.<\/p>\n<p>So, before we can write our test, we will need to create an instance of the <strong>HtmlHelper<\/strong> class. However, the <strong>HtmlHelper<\/strong> class has no default constructor, so a little work must be done up front to get an instance. To create an instance of <strong>HtmlHelper<\/strong>, we must specify a context and view data container &#8211; for the scope of this article, fakes will do just fine. Since each test will require an instance of <strong>HtmlHelper<\/strong>, I&#8217;ve created an <strong>HtmlHelperFactory<\/strong> class to create the instances.<\/p>\n<pre>\/\/Creates an HtmlHelper for unit testing\r\nclass HtmlHelperFactory\r\n{\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;summary&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ Create a new HtmlHelper with a fake context and container\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;\/summary&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;returns&gt;HtmlHelper&lt;\/returns&gt;\r\n&#160;&#160;&#160;&#160;public static HtmlHelper Create()\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;var vc = new ViewContext();\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;vc.HttpContext = new FakeHttpContext();\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;var html = new HtmlHelper(vc, new FakeViewDataContainer());\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return html;\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;private class FakeHttpContext : HttpContextBase\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;private readonly Dictionary&lt;object, object&gt; items = new Dictionary&lt;object, object&gt;();\r\n\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public override IDictionary Items\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;get\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return items;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;private class FakeViewDataContainer : IViewDataContainer\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;private ViewDataDictionary viewData = new ViewDataDictionary();\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public ViewDataDictionary ViewData\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;get\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return viewData;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;set\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;viewData = value;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}\r\n&#160;&#160;&#160;&#160;}\r\n} <\/pre>\n<p>Now that the <strong>HtmlHelperFactory<\/strong> is available, getting an instance of HtmlHelper is as simple as calling <strong>HtmlHelperFactory.Create()<\/strong>.<\/p>\n<p>Using the first spec, I&#8217;ll create a unit test for the default alert. In this test, the <strong>Alert<\/strong> method will be called, and should return the HTML markup we defined, the message specified, with no additional style, and a visible close button. <\/p>\n<p>First, we arrange our expected output and create an instance of HtmlHelper:<\/p>\n<pre>\/\/Spec\r\n\/\/Should render an default alert box\r\n\/\/@Html.Alert(text:\"message\")\r\n\/\/arrange\r\nstring htmlAlert = @\"&lt;div class=\"\"alert-box\"\"&gt;message&lt;a class=\"\"close\"\" href=\"\"\"\"&gt;&#215;&lt;\/a&gt;&lt;\/div&gt;\";\r\nvar html = HtmlHelperFactory.Create(); <\/pre>\n<p>At this point, the method has not been defined yet, so we&#8217;ll use what has been defined in the spec to guide us:<\/p>\n<pre>\/\/act\r\nvar result = html.Alert(\"message\").ToHtmlString(); <\/pre>\n<p>Finally, we check our results with the expected output using <strong>Assert.AreEqual<\/strong>:<\/p>\n<pre>\/\/assert\r\nAssert.AreEqual(htmlAlert, result, ignoreCase: true); <\/pre>\n<p>So now the first unit test is written, but before it can be put to use the <strong>Alert<\/strong> method must be created. This test-first approach ensures that the custom Helper we write gives us the result we defined as HTML in our spec and, as each spec is fulfilled, this process will be repeated until all the specs are completed and satisfied.<\/p>\n<h2>Basic Implementation<\/h2>\n<p>Before creating our implementation, there are a few things we should know about MVC and the <strong>HtmlHelper<\/strong> class. The <strong>HtmlHelper<\/strong> class provides methods that help you create HTML controls programmatically; all <strong>HtmlHelper<\/strong> methods generate HTML and return the result as a string.<\/p>\n<p>We&#8217;ll begin by creating a new class and implementing the <strong>IHtmlString<\/strong> interface &#8211; this provides the <strong>ToHtmlString<\/strong> method, which is used by MVC to render the control to the View. Next we override the <strong>ToString<\/strong> method of our class; the <strong>ToString<\/strong> and <strong>ToHtmlString<\/strong> methods will return the same result, which is a common practice for <strong>HtmlHelpers<\/strong>.<\/p>\n<pre>public class AlertBox : IHtmlString\r\n{\r\n&#160;&#160;&#160;&#160;private readonly string text;\r\n\r\n&#160;&#160;&#160;&#160;public AlertBox(string text)\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;this.html = html;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;this.text = text;\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;\/\/Render HTML\r\n&#160;&#160;&#160;&#160;public override string ToString()\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return \"\";\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;\/\/Return ToString\r\n&#160;&#160;&#160;&#160;public string ToHtmlString()\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return ToString();\r\n&#160;&#160;&#160;&#160;}\r\n} <\/pre>\n<p>Now that we have an <strong>HtmlHelper<\/strong> class, we need to be able to call it from MVC. We&#8217;ll do this by writing an extension method that returns our custom <strong>HtmlHelper<\/strong> class:<\/p>\n<pre>\/\/\/ &lt;summary&gt;\r\n\/\/\/ Generates an Alert message\r\n\/\/\/ &lt;\/summary&gt;\r\npublic static class AlertHtmlHelper\r\n{\r\n&#160;&#160;&#160;&#160;public static AlertBox Alert(this HtmlHelper html, string text)\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return new AlertBox(text);\r\n&#160;&#160;&#160;&#160;}\r\n} <\/pre>\n<p>At this point a complete scaffold of our code is complete, and our unit test should execute but fail to pass.<\/p>\n<p>To finish our basic implementation and pass the unit test, we&#8217;ll need to set up our parameters and render the HTML. MVC provides the <strong>TagBuilder<\/strong> class for building HTML, which we&#8217;ll use to build our render method:<\/p>\n<pre>&#160;&#160;&#160;&#160;private string RenderAlert()\r\n&#160;&#160;&#160;&#160;{\r\n\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;var wrapper = new TagBuilder(\"div\");\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;wrapper.AddCssClass(\"alert-box\");\r\n\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;var closeButton = new TagBuilder(\"a\");\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;closeButton.AddCssClass(\"close\");\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;closeButton.Attributes.Add(\"href\", \"\");\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;closeButton.InnerHtml = \"&#215;\";\r\n\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;wrapper.InnerHtml = text;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;wrapper.InnerHtml += closeButton.ToString();\r\n\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return wrapper.ToString();\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;\/\/Render HTML\r\n&#160;&#160;&#160;&#160;public override string ToString()\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return RenderAlert();\r\n&#160;&#160;&#160;&#160;} <\/pre>\n<p>The HTML helper should now pass the unit test.<\/p>\n<p>With the basic implementation complete, we can easily expand on the HTML helper by adding additional options. Following our spec, we&#8217;ll add the option to change the style of the alert; once again, we start with a unit test and then modify our code to complete the test:<\/p>\n<pre>[TestMethod]\r\npublic void ShouldCreateSuccessAlert()\r\n{\r\n&#160;&#160;&#160;&#160;\/\/Spec \r\n&#160;&#160;&#160;&#160;\/\/Should render a Success alert box\r\n&#160;&#160;&#160;&#160;\/\/@Html.Alert(text:\"message\", style:AlertStyle.Success)\r\n&#160;&#160;&#160;&#160;\/\/arrange\r\n&#160;&#160;&#160;&#160;string htmlAlert = @\"&lt;div class=\"\"alert-box success\"\"&gt;message&lt;a class=\"\"close\"\" href=\"\"\"\"&gt;&#215;&lt;\/a&gt;&lt;\/div&gt;\";\r\n&#160;&#160;&#160;&#160;var html = HtmlHelperFactory.Create();\r\n\r\n&#160;&#160;&#160;&#160;\/\/act\r\n&#160;&#160;&#160;&#160;var result = html.Alert(\"message\", AlertStyle.Success).ToHtmlString();\r\n\r\n&#160;&#160;&#160;&#160;\/\/assert\r\n&#160;&#160;&#160;&#160;Assert.AreEqual(htmlAlert, result, ignoreCase: true);\r\n}\r\n\r\n\r\n\r\npublic class AlertBox : IHtmlString\r\n{\r\n\r\nprivate readonly string text;\r\n\r\nprivate readonly AlertStyle alertStyle;\r\n\r\nprivate readonly bool hideCloseButton;\r\n\r\npublic AlertBox(HtmlHelper html, string text, AlertStyle style, bool hideCloseButton)\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;this.html = html;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;this.text = text;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;this.alertStyle = style;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;this.hideCloseButton = hideCloseButton;\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;private string RenderAlert()\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if (alertStyle != AlertStyle.Default)\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;wrapper.AddCssClass(alertStyle.ToString().ToLower());\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;wrapper.AddCssClass(\"alert-box\");\r\n\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;\/\/build html\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;wrapper.InnerHtml = text;\r\n\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;\/\/Add close button\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if (!hideCloseButton)\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;wrapper.InnerHtml += RenderCloseButton();\r\n\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return wrapper.ToString();\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;private static TagBuilder RenderCloseButton()\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;\/\/&lt;a href=\"\" class=\"close\"&gt;x&lt;\/a&gt;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;var closeButton = new TagBuilder(\"a\");\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;closeButton.AddCssClass(\"close\");\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;closeButton.Attributes.Add(\"href\", \"\");\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;closeButton.InnerHtml = \"&#215;\";\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return closeButton;\r\n&#160;&#160;&#160;&#160;}\r\n} <\/pre>\n<p>Finally, we&#8217;ll make our helper more flexible by giving the end user the ability to define additional HTML attributes. The <strong>TagBuilder<\/strong>&#8216;s <strong>MergeAttributes<\/strong> method adds a specified attribute to the tag being rendered. In addition to the <strong>MergeAttributes<\/strong> method, the <strong>HtmlHelper<\/strong> <strong>AnonymousObjectToHtmlAttributes<\/strong> is used to allow an anonymous object to be used to define additional parameters:<\/p>\n<pre>public class AlertBox : IHtmlString\r\n{...\r\n&#160;&#160;&#160;&#160;private object htmlAttributes;\r\n\r\n&#160;&#160;&#160;&#160;public AlertBox(string text, AlertStyle style, bool hideCloseButton = false, object htmlAttributes = null)\r\n\r\n&#160;&#160;&#160;&#160;private string RenderAlert()\r\n&#160;&#160;&#160;&#160;{ ...\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;wrapper.MergeAttributes(htmlAttributes != null ? HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes) : null);\r\n&#160;&#160;&#160;&#160;...}\r\n} <\/pre>\n<p>The basic implementation is now complete, and the custom helper can be referernced and called in any ASP.NET MVC project. Using the synax outlined in the spec, an Alert can easily be placed anywhere in our project:<\/p>\n<pre>@Html.Alert(\"Message\") <\/pre>\n<h2>Fluent Configuration<\/h2>\n<p>Next, we&#8217;ll build upon the basic HTML helper we have created thus far, with the goal of adding a Fluent API configuration to our existing <strong>Alert<\/strong> helper. The Fluent API won&#8217;t add functionality to the helper &#8211; instead we will be simplifying the syntax used for setting options on our helper; some refer to this as adding syntactic sugar.<\/p>\n<p>Taking a look at the basic implementation of the <strong>Alert<\/strong> helper, we can see that there are several options that can be set when calling the <strong>Alert<\/strong> helper:<\/p>\n<pre>@Html.Alert(text, alertStyle [Default | Success | Warning | Info], hideCloseButton, htmlAttributes) <\/pre>\n<p>Instead of using the constructor as the only manner of setting options on our helper, we will guide the user of our helper through the options. In addition to making options simpler to set, we will also be making our code easier to read. The end result <em>should<\/em> be a syntax which resembles the spoken intent of its use:<\/p>\n<pre>@Html.Alert(text).Success().HideCloseButton()\r\n\"Alert success, hide the close button\" <\/pre>\n<p>Designing a Fluent API requires some planning; again, I prefer to write a specification of how I intend the code to function. Using the specification from earlier I&#8217;ll plan out the code and show the expected results. <\/p>\n<pre>\/\/Success Alert\r\n@Html.Alert(text:\"message\").Success() [.HideCloseButton().Attributes(object)] \/\/Fluent\r\n\r\n&lt;div class=\"alert-box success\"&gt;\r\n&#160;&#160;&#160;&#160;Message\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&lt;a href=\"\" class=\"close\"&gt;&#215;&lt;\/a&gt;\r\n&lt;\/div&gt; <\/pre>\n<p>For the <strong>Alert<\/strong> helper, we&#8217;ll be eliminating the need to specify the alert style as an enumerator and instead just call a method that defines the style by name. In this example we&#8217;ll use interfaces to chain our methods together so the user is guided through the options. In addition to guiding the user, we can control what options are available as well &#8211; for example, when the style is set, only the <strong>HideCloseButton<\/strong> and <strong>Attributes<\/strong> methods will be available.<\/p>\n<p>To create the API we&#8217;ll need to define an interface for setting the style, and a second interface for setting the remaining options. Our <strong>Alert<\/strong> helper will implement both interfaces.<\/p>\n<p>The <strong>IAlertBox<\/strong> interface outlines three method signatures &#8211; <strong>Success<\/strong>, <strong>Warning<\/strong>, and <strong>Info<\/strong> &#8211; which will all return the <strong>IAlertBoxFluentOptions<\/strong> interface. We will use these methods to set our alert style:<\/p>\n<pre>public interface IAlertBox : IAlertBoxFluentOptions\r\n{\r\n&#160;&#160;&#160;&#160;IAlertBoxFluentOptions Success();\r\n&#160;&#160;&#160;&#160;IAlertBoxFluentOptions Warning();\r\n&#160;&#160;&#160;&#160;IAlertBoxFluentOptions Info();\r\n} <\/pre>\n<p>The <strong>IAlertBoxFluentOptions<\/strong> interface outlines the rest of the options for the <strong>Alert<\/strong>. The method signatures <strong>HideCloseButton<\/strong> and <strong>Attributes<\/strong> also return <strong>IAlertBoxFluentOptions<\/strong>, which will prevent the style option from being set again.<\/p>\n<pre>public interface IAlertBoxFluentOptions : IHtmlString\r\n{\r\n&#160;&#160;&#160;&#160;IAlertBoxFluentOptions HideCloseButton(bool hideCloseButton = true);\r\n&#160;&#160;&#160;&#160;IAlertBoxFluentOptions Attributes(object htmlAttributes);\r\n} <\/pre>\n<p>Now that we have defined our interfaces, we will need to create a class which implements <strong>IAlertBoxFluentOptions<\/strong>. Because the class will be returned at the end of the method call, it will also be responsible for rendering HTML and should function as an HTML Helper which implements the <strong>IHtmlString<\/strong> interface.<\/p>\n<pre>public class AlertBoxFluentOptions : IHtmlString, IAlertBoxFluentOptions\r\n{\r\n&#160;&#160;&#160;&#160;private readonly AlertBox parent;\r\n\r\n&#160;&#160;&#160;&#160;public AlertBoxFluentOptions(AlertBox parent)\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;this.parent = parent;\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;public IAlertBoxFluentOptions HideCloseButton(bool hideCloseButton = true)\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return parent.HideCloseButton(hideCloseButton);\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;public IAlertBoxFluentOptions Attributes(object htmlAttributes)\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return parent.Attributes(htmlAttributes);\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;public override string ToString()\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return parent.ToString();\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;public string ToHtmlString()\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return ToString();\r\n&#160;&#160;&#160;&#160;}\r\n} <\/pre>\n<p>The <strong>AlertBoxFluentHelper<\/strong> class is essentially extending the functionality of the <strong>AlertBox<\/strong> class. The helper needs to be able to call back to the <strong>AlertBox<\/strong> we began building to set properties and call the render method, and to accomplish these task we will pass an instance of <strong>AlertBox<\/strong> in the constructor of the <strong>AlertFluentHelper<\/strong>. Using the <strong>AlertBox<\/strong> referenced as &#8220;parent&#8221;, we can call the parent&#8217;s <strong>ToString<\/strong> and <strong>ToHtmlString<\/strong> methods and return the results.<\/p>\n<p>To complete the Fluent API we need to implement both <strong>IAlertBox<\/strong> and <strong>IAlertBoxFluentHelperOptions<\/strong> in the <strong>AlertBox<\/strong> class. Each method will be responsible for setting the desired value, and returns a new <strong>AlertBoxFluentOptions<\/strong> object passing itself to the constructor.<\/p>\n<pre>#region FluentAPI\r\n\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;summary&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ Sets the display style to Success\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;\/summary&gt;\r\n&#160;&#160;&#160;&#160;public IAlertBoxFluentOptions Success()\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;alertStyle = AlertStyle.Success;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return new AlertBoxFluentOptions(this);\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;summary&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ Sets the display style to Warning\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;\/summary&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\n&#160;&#160;&#160;&#160;public IAlertBoxFluentOptions Warning()\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;alertStyle = AlertStyle.Warning;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return new AlertBoxFluentOptions(this);\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;summary&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ Sets the display style to Info\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;\/summary&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\n&#160;&#160;&#160;&#160;public IAlertBoxFluentOptions Info()\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;alertStyle = AlertStyle.Info;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return new AlertBoxFluentOptions(this);\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;summary&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ Sets the close button visibility\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;\/summary&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\n&#160;&#160;&#160;&#160;public IAlertBoxFluentOptions HideCloseButton(bool hideCloseButton = true)\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;this.hideCloseButton = hideCloseButton;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return new AlertBoxFluentOptions(this);\r\n&#160;&#160;&#160;&#160;}\r\n\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;summary&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ An object that contains the HTML attributes to set for the element.\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;\/summary&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;param id=\"htmlAttributes\"\"&gt;&lt;\/param&gt;\r\n&#160;&#160;&#160;&#160;\/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\n&#160;&#160;&#160;&#160;public IAlertBoxFluentOptions Attributes(object htmlAttributes)\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;this.htmlAttributes = htmlAttributes;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return new AlertBoxFluentOptions(this);\r\n&#160;&#160;&#160;&#160;}\r\n&#160;&#160;&#160;&#160;#endregion \/\/FluentAPI <\/pre>\n<p>The Fluent API is now complete and ready to be used.<\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1588-fluent-api-set-style.jpg\" alt=\"1588-fluent-api-set-style.jpg\" \/><\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1588-fluent-api-set-attributes.jpg\" alt=\"1588-fluent-api-set-attributes.jpg\" \/><\/p>\n<p>While the code required for creating a Fluent API may seem unnecessary or overly complex for this example, more complex HTML Helpers could greatly benefit from this type of API. Complexity, frequency of use, and the type of end user your HTML Helper is being designed for are all considerations when for including a Fluent API for your project.<\/p>\n<h2>Stronly Typed Helpers<\/h2>\n<p>Finally we&#8217;ll complete our overview of custom HTML Helpers by learning about strongly typed HTML Helpers. If you are already familiar with MVC, then you have probably seen or used strongly typed HTML Helpers. These helpers use the ElementFor convention, meaning the helper has a <strong>For<\/strong> suffix to indicate that it is strongly typed.<\/p>\n<p>To create a strongly typed helper we need to understand what makes them different from regular HTML Helpers. Strongly typed helpers are used to pass data from the Model to the helper using expression syntax. The <strong>HtmlHelper<\/strong> class is a strongly typed subclass of the <strong>HtmlHelper<\/strong> class. <\/p>\n<p>In addition to <strong><code>HtmlHelper&lt;TModel&gt;<\/code><\/strong>, we will be using <strong><code>Expression&lt;Func&lt;T,T&gt;&gt;<\/code><\/strong> to collect information about the Model. <strong><code>Expression&lt;Func&lt;T,T&gt;&gt;<\/code><\/strong>, which is part of LINQ, represents an expression tree of a delegate which accepts a parameter and returns a result. When writing HTML Helpers, the expression will allow the Helper to accept lambda expressions as parameters. All of the hard work of extracting data from the Model via lambda expression has been done for us in MVC; the <strong><code>ModelMetadata.FromLambdaExpression<\/code><\/strong> method will return the Model data based on the expression.<\/p>\n<p>Since we already have the basic <strong>Alert<\/strong> Html Helper built, we only need to create additional extension methods and allow them to call the <strong>Alert<\/strong> helper:<\/p>\n<pre>&#160;&#160;&#160;&#160;public static AlertBox AlertFor&lt;TModel, TTextProperty, TStyleProperty&gt;(this HtmlHelper&lt;TModel&gt; html,\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Expression&lt;Func&lt;TModel, TTextProperty&gt;&gt; textExpression,\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Expression&lt;Func&lt;TModel, TStyleProperty&gt;&gt; styleExpression,\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;bool hideCloseButton = false,\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;object htmlAttributes = null\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)\r\n&#160;&#160;&#160;&#160;{\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;var text = (string)ModelMetadata.FromLambdaExpression(textExpression, html.ViewData).Model;\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;var alertStyle = (AlertStyle)ModelMetadata.FromLambdaExpression(styleExpression, html.ViewData).Model;\r\n\r\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return new AlertBox(text, alertStyle, hideCloseButton, htmlAttributes);\r\n&#160;&#160;&#160;&#160;} <\/pre>\n<p>In usage you get this:<\/p>\n<pre>@Html.AlertFor(m =&gt; m.AlertBoxText, m =&gt; m.AlertBoxStyle) <\/pre>\n<p>The strongly typed HTML helpers provide better compile time support and benefit from intellisense. Adding this option to your HTML helper extends its usefulness, and gives the end user more flexibility.<\/p>\n<h2>Usage<\/h2>\n<p>Once the custom helper is complete simply add a refernce to your project and call your helper from the view.<\/p>\n<pre>@using MyHelpers;\r\n@Html.Alert(\"Message\")\r\n@Html.Alert(\"Message\").Success()\r\n@Html.Alert(\"Message\").Warning()\r\n@Html.Alert(\"Message\").Info() <\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1588-alert-box-usage.jpg\" alt=\"1588-alert-box-usage.jpg\" \/><\/p>\n<h2>Considerations<\/h2>\n<p>HTML helpers are intended to save time by making our code more reusable. As a result, when creating HTML Helpers, you should consider how often the HTML is going to be used and how the code will be used in a project. Even though HTML helpers save time, they are also an investment. Choosing when to create one and what level of configuration is needed should be decided on a per project basis.<\/p>\n<p>If your goal is to simplify a project, then a basic HTML helper will due. If you plan to use the code across multiple projects, or to create a suite of tools, then Fluent APIs and strongly typed variations of your helpers will increase the value to the end user.<\/p>\n<h2>In Conclusion<\/h2>\n<p>Custom HTML helpers are a powerful tool in MVC, used to encapsulate reusable HTML fragments and, throughout this article, we&#8217;ve identified common practices for creating them. I&#8217;ve used the custom <strong>Alert<\/strong> helper to demonstrate how to create a basic implementation, a Fluent API configuration and the strongly typed convention and the complete project, containing all source code, unit tests and the MVC solution, <a href=\"http:\/\/bit.ly\/SkCGth\"><strong>can be downloaded from GitHub<\/strong><\/a>.<\/p>\n<div class=\"note\">\n<p class=\"note\"><a href=\"http:\/\/bit.ly\/SkCGth\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1588-Github_contribute.png\" class=\"float-left\" alt=\"1588-Github_contribute.png\" \/><\/a>This article is hosted on Github, and we&#8217;d love you to be involved if you have suggestions or ideas for enhancements.<\/p>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Switching from developing ASP.NET WebForms to MVC might seem awkward at first, but Ed demonstrates why the change needn&#8217;t be painful, and how best to build a set of tools for rapid MVC development. This article is hosted on Github, so feel free to contribute suggestions, improvements or translations.&hellip;<\/p>\n","protected":false},"author":58772,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[4143,4156,4157,5669,4963,5166,5746],"coauthors":[6808],"class_list":["post-1431","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","tag-net","tag-asp","tag-asp-net","tag-asp-net-mvc","tag-git","tag-mvc","tag-web-forms"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1431","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/58772"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=1431"}],"version-history":[{"count":7,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1431\/revisions"}],"predecessor-version":[{"id":71878,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1431\/revisions\/71878"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=1431"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=1431"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=1431"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=1431"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}