Need Quality Code? Get Silver Backed

Conditional Attributes Gotchas



by Gary H

The release of MVC4 brought a number of new features however one that was sneaked in without fanfare was conditional attributes - buried treasure that can cause real breaking changes to your view rendering.

Conditional attributes extend the Razor 2 view engine to allow entire attributes to be added or removed based on their value. Take the following example, given the view:

	var items = new List<Tuple<bool, string>>(new[]
				  new Tuple<bool, string>(false, "Item 1"),
				  new Tuple<bool, string>(true, "Item 2"),
				  new Tuple<bool, string>(false, "Item 3"),

Fun with attributes

We get a nice select list with option two selected. In addition if we take a look at the created HTML:

Fun with attributes

Note that the entire selected attribute is removed from the generated HTML. This is what conditional attributes do, when you are assigning a value to an attribute using Razor, if that value is null or false, the entire attribute will be omitted. If the value is true the value of the attribute will be set to the name of the attribute.

That last part is important so i'll say it again: If the value is true the value of the attribute will be set to the name of the attribute.

This is a nifty feature - it reduces the size of HTML generated however it also caused issues on our upgrade. Take the following View:

	Should have val true

	Should have val false

The first pair of anchors closely resemble some code that our client had deployed. A true/false value was written to the attribute directly and prior to MVC4 this rendered as expected by calling an implicit ToString giving us True or False. After MVC4 we now get the val attribute either completely omitted or created with a non-boolean value. As this was pulled into JSON which was deserialized on the server into a .Net object this caused some fairly major breakage.

The fix is thankfully simple, force a ToString on the boolean values:

	Should have val true

	should have val false

It is also worth noting that another fix is to mark the attribute with the data prefix (i.e. rename val to data-val) but in our case it was much less work to add the ToString and be done.

C# , MVC

Comments are Locked for this Post