I’ve spoken of the dangers of becoming reliant on a framework, but in this post I am specifically targeting the ASP.NET MVC Frameworks Html Helpers. At a high level, most of these pros and cons are true for ASP.NET WebForms, and probably true for other frameworks as well.
One term that comes up a lot is layer of abstraction. I spoke of this a lot of this concept in my post on certs, but never bothered to define it. Abstraction means a concept or idea not associated with any specific instance. Programming frameworks provide an interface to interact with with underlying mechanics. The benefit is that the user can work with a simple interface rather than needing to become an expert on the technology. This is a primary benefit and a crutch of all computer interfaces. The drawback of abstraction reliance is proportional to the importance of the knowledge of the underlying system. Case in point: calculators and word processors. Both very beneficial, but damaging if they prevent you from learning math, spelling or proper grammar (as I wrote this I misspelled grammar and spell check caught my mistake).
So, now that that’s out of the way, lets take a look at the general pros and cons of MVC html helpers. Overall, the pros outweigh the cons, despite the way this post may read (as a jab at a framework that I’m a huge fan of).
- Dummy Checking
Runtime errors (there are no compile time errors in views since the don’t compile) and syntax warnings are great time savers when writing code. The MVC helpers will throw errors when forgetting to close form tags, when urls don’t point to an existing page, and in general prevent a lot of malformed html markup that might go unnoticed and could even cause browser specific errors, which are very tough to find. Certain helpers bind directly to model properties, allowing strongly typed intellisense to speed up code writing and prevent naming incongruencies between post keys and model properties. These qualities really come in handy when refactoring models or rearranging file structure.
Select and multiselect controls are easier and more elegant to write than creating option tags in a loop with lots of ceremony to check for selected state and so forth. If you’re really making bare bones, admin level CRUD apps, the EditorForModel and DisplayForModel provide a quick interface to directly deal with model data. The AJAX form is more useful example. It wraps a wildly complex system in a simple interface (abstraction from proprietary code is good!) and ties nicely to the MVC framework in a cross-browser compatable system.
You can write your own helpers to centralize reusable bits of html. This feature can be easily abused and it can be misleading for devs who join your team that may think your extension functions are part of the MVC framework. One dev was excited to learn the “MVC way to add an image” but was disappointed when I told him it was just our own extension method.
- Abstraction from understanding html
The html mvc framework is a proprietary language, and the helper functions are non-transferable knowledge. This means you will have to learn a new system when changing frameworks and always have to keep up with updates to the existing framework. For new devs, or devs coming from the WebForms world which is the ultimate html abstraction, this is even more detrimental. They might not have a clear concept of the client/server relationship to begin with, and it’s very easy to believe that these html helpers are required to bind model properties, or that they somehow aid the server in interpreting post data. Also understanding the fundamentals of form controls, the difference between name and id, how user agents format key/value pairs and determine successful controls; these are quintessential skills of any web programmer. No shortcuts should be taken until they are mastered!
- Often more complex than basic html
Most html elements are very simple to write as html: Links, Labels, Buttons, Form tags, simple text inputs, etc. The helper alternatives are often longer and more complex to write (up to 12 overloads), harder to read, and introduce new problems which then require additional bandaid fixes. Example: there’s a property called IdAttributeDotReplacement. What does this do? It solves a problem that they caused, but it might change or go a way in future versions, and is generally a waste of time to learn.
- Inconsistent syntax
The signatures all have multiple overloads (2-12), and have a mixture of named and unnamed parameters. The first parameter is often a string or a lambda expression, the second may be a string, but its usage varies widely. Route values are often split between properties of an anonymous object and string parameters. The specific controller is often found in both. Html attributes are also divided between an anonymous object and string parameters.
- They aren’t written for html 5 (not even MVC 3 which just came out!)
There are no helpers for the host of new input types which branch off of text (email, phone, url, number, range, date, datetime, etc.) There also isn’t a discoverable way of adding the required attribute other than shoving it inside the HtmlAttributes object. There are plenty of html5 helper toolkits out there, and perhaps the mvc team was wise to leave these out of the framework because they are not widely supported and it might cause confusion and cross browser inconsistencies. I hope they address these new inputs by making a generic textbox helper with a class parameter rather than an explosion of helper classes for each new input.
- They didn’t think of everything
Simplicity often comes at the cost of flexibility. The MVC framework helpers handle the most common usages, but are often incompatible with edge cases. This was my original point to address in this post, so I have compiled a list below of cases where they missed the mark.
The Biggest Offenders
- CheckBox / CheckBoxFor
I’ve stopped using this helper altogether. See my post on the html checkbox (adding a hidden field, only allowing a boolean value, etc). There is no CheckBoxGroup helper, as there is for radio button group, but given how bad they fumbled the checkbox, I don’t think I’d come near it. You can specify an id, otherwise the id defaults to the name, but it will replace periods with underscores.
- Label / LabelFor
There’s no way to add css classes. You can only specify the display text and the “for” value (which binds to a model property in the case of LabelFor. Labels don’t work well with radio button groups, and they don’t work at all with checkbox groups, which are the smallest controls and thus the most useful to have a click-able label to set focus.
Inconsistent syntax. All other html helpers return a string which you must write. BeginForm simply writes the string. Inconsistent requirement of a controller with an action. All other helpers which allow specification of an action will default to the current controller if one is not specified. forms will not. This is not only annoying but in some cases limits functionality.
I’m using a profile edit form embedded in a shared view on two pages (external when creating an account, and internal for updating). If I use the default constructor, the action will resolve to the current page, which is what I want. But to specify an id, or any other elements, you must first specify an action AND a controller. If there is a workaround, I’d rather simply write <form id=”myform”>.
I may be wrong about some of the limitations I’ve noticed in the MVC framework. Rather than saying they aren’t there, I should say I have not yet found them in over 8 months. So if any of these features do exist, they are very hard to find, which is just as bad. I will continue to update this list as I discover new pros, cons or specific offenders.