The ‘Using’ statement and auto-closing HTML Helpers

Thursday February 4, 2010

I was recently speaking to someone who was asking how you create a HTML Helper that contains other elements and then closes itself like the MVC Form element. The MVC form element is made up of two HTML helpers 'BeginForm' and 'EndForm' which can be used in conjunction with each other as below:


<%=Html.BeginForm()%>
   Name:
   <%=Html.TextBox("Name", Model.Name)%>
<%=Html.EndForm()%>

Which rather unsurprisingly would produce HTML mark-up similar to this when a view is rendered:


<form action=”/controller/action/”>
  <p>
  <label for="Name">Name:</label>
  <input type="text" name="Name" />
  </p>
</form>

The other way of using the MVC form HTML Helper involves a 'using' statement. Like below:

<% using (Html.BeginForm()){ %>
   <p>
   <label for="Name">Name:</label>
   <%=Html.TextBox("Name", Model.Name)%>
   </p>
<%}%> 

This will create exactly the same HTML mark-up as the first element. So the question I was asked was how can you implement your own auto closing HTML helpers following this pattern? The answer is really very simple and it is something that I have taken for granted and have been using for some time. The key to understanding this pattern is with the 'using' statement and the fact that a string is not returned from the HTML helper it returns a type of 'MvcForm'. A using statement is normally used to ensure we are closing resources and as such calls dispose when the using statement is exited. The 'BeginForm' helper actually writes directly to the response stream and then returns a MVCForm object to the using statement. When the using statement is exited the Dispose function is called on the MVCForm object which writes out the end form tag. To be honest, I'd say this particular usage of the 'using' statement is a bit of a hack on the part of the .NET MVC team, but it certainly works well enough.

To show a working example of how this works in practice. I am going to consider a very simple scenario which I wouldn't want to suggest is a suitable candidate for this kind of method; however, it will give us a nice easy example to see this in action. Consider a component where we have buttons that need to be contained within a ButtonBar component to be styled up correctly. In this scenario the ButtonBar is a div that we wish to implement the auto-closure functionality.

public static MvcSelfClosingDiv BeginButtonBar(this HtmlHelper helper) 

   HttpResponseBase httpResponse = helper.ViewContext.HttpContext.Response;
   httpResponse.Write("<div class=\"buttonBar\">"); 
   return new MvcSelfClosingDiv(httpResponse); 
}

 

public static void EndButtonBar(this HtmlHelper helper) 

   HttpResponseBase httpResponse = helper.ViewContext.HttpContext.Response; 
   httpResponse.Write("</div>"); 

First of all here we implement the opening and closing tags for the ‘ButtonBar’. Notice how we are writing directly to the response stream using the response object and return a ‘MvcSelfClosingDiv’ from the ‘BeginButtonBar’ HTML helper.

Then the code for the ‘MvcSelfClosingDiv’ class looks like this:


public class MvcSelfClosingDiv : IDisposable
{
   private bool _disposed;
   private readonly HttpResponseBase _httpResponse;
  

   public MvcSelfClosingDiv(HttpResponseBase httpResponse)
   {
      if (httpResponse == null)
      {
         throw new ArgumentException("httpResponse");
      }

      _httpResponse = httpResponse;
   }

   public void Dispose()
   {
      Dispose(true);
      GC.SuppressFinalize(this);
   }

   protected virtual void Dispose(bool Disposing)
   {
      if (!_disposed)
      {
         _disposed = true;
         _httpResponse.Write("");
      }
   }

   public void EndDiv()
   {
      this.Dispose(true);
   }

}

As you can see we are using the dispose function to write the end tag directly to the response stream.

I’m fairly certain many people out there will have probably taken this pattern a step further and implemented a more generic solution. It would be simple enough to build a generic ‘SelfClosingTag’ class where you could set the closing tag string when the object is created in the ‘BeginX’ HTML Helper.

I’m sure many out there will have been already aware of this pattern used within the .NET framework as it is very easily accessible in the MVC source code or via reflector, however, I hope maybe this might be of use to someone who is just starting down the route of writing HTML Helpers and might save them from having to fire up reflector to see what is going off under the covers with the MVC Form HTML Helper.

Post Info

Written by Ross

Comments
*
*
*
*