My first thought:
MVC3 already??? ScottGu, slow down pal, give us some time to breath!
Alrighty, so I installed the bits for MVC3. I fired-up VS2010 and I see some new guys in the neighborhood.
When you select the ASP.NET MVC 3 Empty Web Application option, no controllers and no views (not even the master page) are created. I’m guessing that’s why they put the word ‘Empty’ in there, but how would I know… English is my second language!!
As I’m still not very comfortable with Razor, I created the solution with the non-Razor flavor. The first thing I did was to add a Razor view and check it’s compatibility. Just wanted to see how two different view engines lived under the same project in harmony! While doing this I also tested the ‘dynamic’ ViewModel property on the controller.
I’m used to creating views by right-clicking in the action method and choosing ‘Add View…’ and here’s what I see:
Look at that – the two view engines. So I select Razor and add it to my project. All I had to do was to make a call to @View.Message and this is what the Razor view looked like:
I run the application and when I change to url to /home/test, I get the following output:
I loved the simplicity. But just before we move on to the other features, had a couple of concerns. The “@” is similar to <%: %> (the encoded version). So to display something like “ASP.NET <br /> MVC 3” in two different lines you can do:
The second concern is that when I selected Razor in the Add View window for my (ASPX)-style solution and click on ‘Add’, I get the following error message:
I would’ve preferred if it had asked me ‘Want the master page to be created?’ But I’m guessing this is already in the works. So for my above test, I had to uncheck the master page checkbox and continue.
In his blog, ScottGu mentions about permanent redirects. Let’s take this to a spin. I modified my Test action method:
Now when I go to ‘/home/test’, I get back to the Index page and Fiddler tells me what happened in the backend:
A 301 indeed. ASP.NET 4.0 also has this feature – details here.
Now let’s do something more ‘real-world’ish. I created my model:
My Index action ends up like this:
I create my view for Product as:
And to display the Components, I created the ‘Component.cshtml’ Razor partial view.
With this mix, I ran the application and got a beautifully rendered page (another proof of (ASPX) and Razor’s harmonious co-existence).
The curious side of me said ‘What if both Razor and (ASPX) partial views exist in the same folder? Which one will be picked up?’ I added an (ASPX) partial view with the same name – Component.ascx to the EditorTemplate folder. I made this view slightly different – the components were editable. Running the application gave me this:
Turns out ascx has a higher priority than cshtml. Seems like the View Engine looks for .ascx files first and then searches for the .cshtml files. MVC team, please let me know if my understanding is wrong.
At this point, I’d like to raise a feature-request. In the Add View window, it’ll be really helpful if there are two more options next to the ‘Create a partial view’ checkbox – Create partial view as Display Template and Create partial view as Editor Template. These would be grayed out initially and enabled only when user checks the partial view checkbox. Based on what template has been selected, VS2010 should create the appropriate folder (EditorTemplates / DisplayTemplates) and add the partial view file in the appropriate folder. This is a good thing to have even for MVC2 projects.
It’s time to do some validation on our Product class. With MVC2, you could add validation attributes on the properties directly. MVC3 gives another way of doing this (it’s too early for me to say which one’s better). Here’s what my Product class became after adding the validation checks.
During model binding, if any of these conditions is true, the associated validation message gets displayed on the screen.
I was unable to add HandleLogging attribute to my controller. VS2010 complained of missing some references for this attribute. And when I looked at the Object Browser for System.Web.Mvc, there’s no HandleLoggingAttribute member listed:
May be ‘The Gu’ has special bits for this!
Now here’s my main concern – Model Binding for complex view models. I had this issue with MVC2 as well, but then I thought they’ll fix this issue in the next release.
I’ll use the above Model and the following View to go detail on this issue:
The partial view ‘Component’ looks like this:
This gets me the output as:
Now when I click on the submit button, only the product name and category get bound to my product instance, but not the Components list.
The reason this happens is due to the way the html is rendered. When I do a View Source on the page, I see the components as:
If only the name attribute of the input tag gets rendered as ‘Components.Name’, ‘Components.ManufacturerCompany’ and MS tweaks their Model binding logic a little bit, this will get a lot easier for users. Currently for one of our projects, we’re having to use Html.CustomTextBoxFor() extensions that emits the name attribute correctly and our own Model binding algorithm to get the object mapped correctly.
I’ll stop at this; will update more later. Please download the code here.
Verdict: There’s a lot more to learn and play with, but this sure is a good start for MVC3.