Let’s Get Geeky!! This week I have been updating a project I’m working on from ASP.NET MVC3 to ASP.NET MVC4 (Beta). MVC4 ships with an improved version of the Razor view engine. But “updated” apparently also means “broken”… That is, if you’re using jQuery UI Widgets. Which I am. So it is.
Let’s build a simple MVC app and show you what I mean. The steps are the same for MVC 3 and MVC 4, but the MVC 3 one works while MVC 4 doesn’t. (If you’re lazy, I applaud you. I provide both code samples at the bottom of the page).
Run Recipe…
Create a new ASP.NET MVC Web Project. Set it to be an Intranet application (Windows Authentication) so we don’t have to mess about with logging in, make sure the View Engine is set to “Razor”. We won’t need a Test Project.
Our website is going to show the details of a customer using data from C# (perhaps from EF, or a SQL query) injected into a jQuery UI widget in an MVC View. (Microsoft’s Project Silk has good documentation about creating jQuery UI widgets). First thing, let’s create a Customer Model:
…which has three properties: an ID, a name and a Credit Limit:
Next, create a Customers controller:
And write an Index() Action which outputs a hand-cranked CustomerModel to a view (in the real world, of course, this would come from a database):
(Note: Just to be sure. The “M” means “decimal”, not million, or Mega, or Moomins or Maggie Gyllenhaal)
Compile the web app at this point by pressing F6. Now lets add a view for our “Index” action:
Select the Model class to be the CustomerModel. This will allow us to use the properties of that Type in the View.
Add the following code to the View (note the difference in code highlighting between the MVC3 view on the left, and the MVC4 code on the right):
Hint: Razor V2 seems less greedy about its curly-brace matching. In fact, it seems to lose track of its opening and closing braces entirely.
The section called “Script” should be added to the Views\Shared\_Layout.cshtml file, inside script tags and just before the closing </body> tag:
This creates a nice, neat, hook point for Views to execute JavaScript in a consistent, progressive-enhancement kind of way.
Licking the Spoon
Create a new JavaScript file in the Scripts folder called “customers.jquery.js”, and write the following:
This widget is called “customer” and lives in the “test” namespace. It has three properties (or options) which match those on the CustomerModel. When it is attached to a DOM element (such as the DIV with the ID of “customer” in our view) it outputs either “No customer selected” (if the options haven’t been overridden) or the information about the customer.
Add a reference to the jQuery UI JavaScript file, and our new customers.jquery.js file in the _Layout.cshtml file:
Let Her Rip!
Now fire up your MVC application. Here’s what you will see:
Spot the difference?
Download the code for MVC3 (works) or MVC4 (borked). OK, OK, it’s Beta, but I’m astonished this common use case wasn’t picked up in testing…
Update
The awesome Scott Hanselman (sorry, bit of a geek-crush there!) referred me to Andrew Nurse, main developer of the Razor view engine (also seems like a thoroughly bloody good bloke). Andrew said it should be fixed in the Release Candidate for MVC 4 (although this is to be confirmed next week).
Feeling a little guilty now. Hadn’t realised the Razor view engine was effectively the work of one fella. It’s easy to be flippant in the direction of an anonymous, faceless corporate team, but less-so when it’s one person toiling away creating something truly useful and creative. Let that be a lesson to you, blogosphere!