I’ve been doing a good amount of programming lately, but I haven’t been good about writing down what I’ve been learning! Worse, is I should be writing down things that I keep forgetting – like this topic, today: how to use UIHints in Entity Framework objects to help display data appropriately!
Let me start from the beginning – there is a truly magical formula, in my mind, of using:
Entity Frameworks + the Repository Pattern + MVC + jQuery = Magic!
In my career, I’ve yet to see anything as elegant as this suite of technologies. Several aspects of these work very powerfully together! I am working on building a site that uses just these technologies, and it will be HTML5 too, in the end.
One particularly cool feature is the idea that MVC can show data and do validation based on how the “model” is decorated with attributes. In particular, there is an attribute you can use, that MVC understands, that gives MVC a hint on how to display the data. I wanted to explain how that works for Future Robert, and anyone else that might be interested!
STEP 1: The Model
So first, this is assuming that we are using an Entity Frameworks model. You can use a model-first or code-first (POCO) type of model, it doesn’t matter. Although, if you are using model-first, you really have to do some fancy things to work around the auto-generated code. I would highly recommend converting those model-first generated classes to POCO’s, that would give you a lot more freedom to take advantage of things like this! OK, so on an entity class I have some definitions of properties that are defined like this:
Note in particular the [UIHint] attribute. That is nothing more but a way for me, in the model, to give a hint to the UI (whatever that may be) of how best to display this field of data. By the way, I’m a big fan of also using attributes to specify the length, a regular expression, and even what the label for this data should be. Again, you can’t easily do that with generated-classes with EF – so c’mon, convert your classes to POCO’s!
STEP 2: The MVC View
Now, the MVC view doesn’t do much of anything interesting, it just looks the way you’d expect:
This is part of why this is so cool. You don’t have to do anything special inside the view. The MVC framework inspects the underlying property and based off the annotations, it will add the label we specified, and add field validators for us automatically.
But what about that UIHint? Well, in any view, including Shared, you can create a DisplayTemplates and EditorTemplates folder. In those folders, if you create a partial view that has the name of that UIHint, MVC will pass that property to the partial control and leave it to figure out how to display it.
Now wait a second, that is almost amazing. What I mean is, in my data model, I set a UIHint of “Email”. So now, in my DisplayTemplates, I can create a partial view called Email.cshtml (I’m using MVC3 with Razor) – and in that file, I can display that field as a mailto link, for example!
STEP3: The Templates
Ok, under ViewsShared, create 2 new directories: DisplayTemplates and EditorTemplates – those should both be children under the Shared folder. Within the DisplayTemplates folder, create a new partial view called e-mail:
Inside of that file, put something like this (and only this):
Now, anywhere on your site, if you use @Html.DisplayFor for that field, it will automatically show as a mailto link – EVERYWHERE!
I have another DisplayTemplate for Hyperlink (in Hyperlink.cshtml – which corresponds to UIHint(“Hyperlink”)) – that looks like this:
Now, editor templates can be a little more fickle. However, this is how I approached it – for 3 common needs: 1) a medium textbox, 2) a medium text area and 3) a date/time field. For each of these, I pushed out whatever I could to a corresponding CSS class. That way, things like height, width, font, etc would be consistent and easy to change in one place. So, here are those 3 common ones I use a lot:
MediumTextArea.cshtml (corresponds with UIHint(“MediumTextArea”)):
MediumTextBox.cshtml (corresponds with UIHint(“MediumTextBox”)):
DateTime.cshtml (corresponds with UIHint(“DateTime”)):
This DateTime one is a little goofy, so let me explain what is going on. I wanted to show a jQuery UI datetime picker whenever I am editing a date field, on any table. However, jQuery needs to be able to find this textbox. I can’t give is a hard-coded ID because there might be more than one datepicker on the page.
Also, I can’t use the “id”, because MVC uses that while it’s keeping track of the model, during editing. jQuery can select things by CSS class, so I created a bogus CSS class, solely for the purpose of jQuery to be able to select the textbox.
So, the Razor code generates a random CSS class that will look something like “DateTimeTextBox_20394”. Then, I do a .TextBoxFor to render it to the screen, specifying the css class. You might notice that I use upper-case “Class” instead of “class”, that is because “class” is a reserved word.
After that, is just the jQuery UI code to show the DateTime picker. This assumes that the masterpage (_Layout.cshtml) is loading jQuery and jQuery UI already.
So, that’s all there is to it. You decorate your Model properties with UIHint. Then, you create a matching EditorTemplate or DisplayTemplate with a matching name. So long as you use DisplayFor or EditorFor (or EditorForModel, for that matter) – this all just magically works!
Oh, and Future Robert? You’re welcome.