Back in January, Jeremy Miller posted a nice article on HtmlTags: Shrink your Views with FubuMVC Html Conventions. We were immediately in love with the idea and have spent several months adapting the conventions to work with our ASP.Net MVC applications. I was having a conversation with Ryan recently, reflecting on how far we’ve come and how we had no vision of that when we first read that article. I want to share some of that, so I will be working on a series of blog posts to show “What we are doing with HtmlTags.” But first: why?
A lot of buzz has been generated around reusability and views, particularly html. Html being a highly compositional language, but lacking any ability for reuse, has led to copy paste hell. Several different philosophies are employed in View Engines (VE) to try to address this issue and recently MVC2 was released with it’s templated helpers. The problem with reusing html directly is that lacks the benefits of separating the concern of what we need from the html (building it) and generating it, classically, the difference between “What” I want versus “How” I get it. The power of the Linq abstraction shows the benefits of separating “What” versus “How.” HtmlTags is another model based approach that separates the “What” and “How.” It goes even further by allowing the “How” to be configured via conventions. Here is a list of the benefits this separation has brought to our team:
- View engine agnostic. HtmlTags is not coupled to any particular VE. It can even be returned from a controller action and rendered directly to the response!
- Testability with out spinning up a costly integration environment, I can write assertions directly against the model!
- Html is a language that lacks the ability to query it in any reasonable fashion.
- We integrate security as an aspect to our conventions that build our Html. Now, we can write a simple test to ensure that the security shows/hides elements in the model by simply asserting the lack of their presence! Try parsing html to do this after you spin up an integration test to access the view output!
- Translation: HtmlTags is a model that is easily traversed. We leverage this to transform the html model into an export model that can then be translated to csv, pdf and other formats. Now we get exports for free on any view result simply by writing the guts of the view in HtmlTags!
- The ability to translate from our data model to the html model directly, in c#, instead of using a view engine with a mish mash of concerns (html & code).
- This avoids reshaping of our data to get it to easily work with our view engine. Instead we can translate directly, on our view models, and have the full power of c# at our finger tips.
- This also helps with refactoring, where the story is still very poor with VE content.
- Simply put: avoids the html / code disparity
- Composable conventions, we build upon the HtmlTags DisplayFor, LabelFor and InputFor to build up higher level concepts in our application, like a form field (composed of fields for a label, input, validation etc). This gives us a on stop spot to restructure the html for every form in our application, no more shotgun surgery on views!
- We also leverage concepts around menus, buttons, forms etc.
- Reusable across projects: we don’t have to try to copy/paste a bunch of templates, we simply drop in a dll with default conventions and configure from there.
- Avoid fat fingering html tag names, attributes etc. We don’t have to think as much about html anymore, amazing concept! Templated html still has issues with fat fingering as <div> is all over whereas we have a nice Tags.Div static entry point to generate a div tag. We do this for all tags we use. This is the concept of reuse between templates that is rather lacking from MVC2 templates without bee sting hell. This is a great example of leveraging a statically typed language to fail fast, we don’t have to render a few to find out if we fat fingered some html. All html tags, attributes etc are kept as constants collections.
- Avoid hard coded css classes: we make our class names configurable and put them right with the builder so any project can override them. Try doing that without a bunch of bee stings in a templated helper and a nightmare of classes coupled to the template to provide the constants in code. This reminds me of code behind hell from web forms days. Then try reusing that across projects.
- I’ve seen some really scary stuff in samples with templated helpers where people try to access attributes. property types, etc and conditionally render sections. The only alternative is to put that code into helpers that are separated from the view and lead to a coupling mess when trying to reuse the templates across projects.
The next set of posts will cover examples of how we are using HtmlTags and how it’s paying dividends.