HTML5 inputs in ASP.NET

Recently I've been revisiting some HTML I wrote a while ago and seeing what would benefit from some HTML5 magic. HTML5's design philosophy makes this quite easy at the client side, due to a policy of backwards-compatibility from the spec's authors. For example, using a new input type such as search or email is fine because a browser that doesn't understand it will just render it as if it's type were text, which is what you would have used anyway.

It gets a bit more tricky when you're working on the server side. The site I work on at the moment has an ASP.NET back end (specifically, Web Forms — I don't know whether this applies to MVC or not), which has the downside (among others) that you don't have absolute control over some of the markup that it generates for forms. Here's how you write a regular text field in .NET:

<asp:TextBox id="query" runat="server" />

Like many things, it uses a server control to output an input type="text" to the page. Because you've declared the control like this, you can use your C# or VB code to manipulate it when the page is generated and when the postback occurs. So, how to change this so we are using input type="search"? First I tried this:

<input type="search" id="query" runat="server" />

The rendered page showed an error message about search not being a valid input type, so that was out. Next I tried this:

<asp:TextBox type="search" id="query" runat="server" />

The type="search" attribute I added was totally ignored, and the element was rendered as a regular text box. Next I tried leaving the control itself as a standard asp:TextBox, but adding some code to be executed on Page_PreRender to delete the type attribute from the element and replace it with type="search". Same result as above — it was ignored. Oh, and you can't use JavaScript to change the type attribute once the page has loaded — that doesn't work either You can use JavaScript to change the type attribute (although it doesn't work if you do it through jQuery), but that rather misses the point.

By this time I was getting seriously frustrated, and the only thing left was just to write a plain HTML tag like this:

<input type="search" id="query" name="query" />

Note the absence of the runat="server" attribute, so the element is rendered on the page as-is without being processed by the server, and we have to get the value the old-fashioned way from the request's POST data (bypassing .NET's postback architecture entirely):

string query = Request.Form["query"];

It works...but there are disadvantages:

  • Because it's not a server control, you won't be able to manipulate the element in the code behind before the page renders, so you'll have to hard code things like the value and placeholder instead of retrieving them from a database or resource file.
  • Because it's not a server control, you won't be able to use an asp:Label control to label it, so you'll have to hard code that element and it's values as well.
  • Because it's not a server control, it bypasses the Viewstate, which means it is less secure (although I don't know enough about .NET to understand why).

Update: Since writing this, I've ended up writing my own control that extends TextBox and provides the HTML5 features we want. Also, future versions of .NET will provide this as standard.