ASP.NET MVC 3's Razor View Engine: Tips, Tricks, and Potential Gotchas
Why Mike Campbell loves ASP.NET MVC 3's Razor view engine--and useful tips he's learned while working with it
January 19, 2011
Unless you've been living in a cave, you probably know that MVC 3 and the Razor view engine have been unleashed upon the world. Sadly, I was living in a cave while much of MVC 3 and Razor were in beta, but I've recently emerged and had a bit of time to play around with both MVC 3 and Razor, and I'm loving what I'm seeing.
Coming to Love Razor
I'm very hard to please. To the point where I actually didn't like Razor for a long time just because I thought that the .cshtml (or .vbhtml) extensions it used were lame. For me, these extensions were too descriptive and not cool enough. (Yes, I actually care about superficial, pointless, stuff like how "cool" extensions sound/feel. And something like .rzrc or .rzrv files would have been much cooler, in my mind.)
At any rate, partially due to snobbery, but mostly due to a lack of time, I've ignored Razor for a long time. Only, I've had some time free up lately and was therefore finally able to look at Razor in a non-superficial way.
But now that I've spent some actual time with Razor and used it in real projects, I'm absolutely in love with it. And not just because it's new and shiny (I'm petty in that regard as well), but because it is so much more terse, flows so much better, and does an even better job of reducing visual clutter than I was even anticipating that it would.
What I think I enjoy most about Razor, though, is that it very cleanly and succinctly gets rid of the last vestige of ASP.NET Web Forms from MVC by removing excessively verbose declarative aspx tags from the mix—while simultaneously making everything that I've always loved about master pages that much better.
Case in point: Compare the following first few lines of an older aspx View to those of a Razor view that performs the exact same function:
ASPX View:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
Sample Content
Razor View:
@model ZipTracker.Site.LogOnModel
@\{ ViewBag.Title = "LogIn"; \}
Sample Content
Much cleaner, right? Not to mention much less visually cluttered. That, and there's no need to specify the language—because it's included in the extension. (Which means I really was a dummy to be so snobby about the extension/name.) Likewise, as I'll cover down below, there's no need to explicitly specify a master page—though you still retain full, granular control over the same functionality (called a layout) when using Razor.
Moreover, it doesn't take much time spent with Razor to really come to appreciate just how much more fluid and terse Razor syntax can be. And while I can't wait for some additional improvements with IntelliSense support for Razor in a few minor areas, one of my hands-down favorite things about Razor is that I can finally get IntelliSense within HTML attributes when using Razor—something that I wasn't able to get at all with previous versions of Visual Studio.
Tips, Tricks, and Potential Gotchas
In the few hours that I've been working with Razor I've found it insanely easy to adapt to—but I have bumped my head on a few things. So, if you haven't yet had a chance to work with Razor or are planning on working with it shortly, then these few tips, tricks, links, and potential gotchas might help you save some time and pain when coming up to speed with Razor.
Extension Methods
One of the things that I leverage extensively within MVC projects is the ability to "decorate" my models with extension methods. In this way I can use domain models where it makes sense, yet add additional, presentation-focused, logic into my MVC site by means of extension methods. I find that this ends up being a very powerful way to handle formatting routines and address potential if/then/else scenarios without cluttering up my views with lots of logic. And it makes for a powerful way to create links or tackle other issues where I'm intertwining logic and presentation (because I can tackle these needs using an extension method that, effectively, wraps interaction with a TagBuilder.
Only, one of the first things that I noticed with my Razor view was that even though I had specified the "custom" namespaces needed for my extensions methods to work with ASPX views, they weren't compiling when the same views were converted to using Razor syntax.
Happily, it only took a bit of poking around, but I determined that with Razor views, you need to add your "custom" namespaces to the web.config in the Views folder—because that's where most of the config information for Razor is stored. Otherwise, you can also use an @using directive (don't forget the semicolon) in the top of your Razor view—but I prefer avoiding using/imports statements in my views by means of modifying the web.config. So putting those imported namespaces into the web.config in the Views folder was the fix I needed.
Navigating the Syntax
Razor syntax is really quite simple, logical, and fluid. If you're familiar with ASP.NET in general, then Razor will come naturally. That said, most people (including me) learn by examples, and to that end I really found Scott Guthrie's blog posts on Razor syntax and Layouts to be great quick-starts. That said, those posts were done pre-launch, so there are some minor differences in how certain features were documented pre-launch and how there are now with the RTM version of Razor.
To that end, I found Phil Haack's Razor syntax quick reference to be very valuable. In fact, after scanning Scott's posts, I was able to do just about everything I needed by using Phil's quick reference as a guide along the way until I had everything basically under wraps within just a few minutes.
Consequently, I think about the only thing I found lacking was a quick reference for Layouts, so I've included one that I created below, which defines how calls within Layout pages correspond to markup within individual .cshtml files.
@RenderBody()
This corresponds to the main body/markup in an entire .cshtml (or .vbhtml) file. Nothing special at all about this one.
@RenderSection(sectionName)
The best way to think of sections is to treat them like ContentPlaceHolders in ASPX views. In the Layout Page a call to @RenderSection(sectionName) corresponds to the following markup in a view:
@section sectionName \{
This is the Partial Content for sectionName
\}
@RenderPage("~/path/partialname.cshtml")
As you would expect, this is more like RenderPartial—where the contents of an entire view are processed and then stuffed into the output stream.
Otherwise, using Razor is about as easy as falling off of a log.
Master Pages Optional
One of the first things I wanted to know when getting started with Razor was whether I could remove the _ViewStart.cshtml file in the root of my Views folder. My thought was that it was probably the Razor equivalent of the view that MVC1 and MVC2 sites put in place to handle IIS 6 sites. But was I wrong. It turns out that not only is this something you'll want to keep, but it's an insanely powerful tool that shows off just how much thought and effort was put into making Razor a success.
By default, if you create a new MVC3 site with Razor, you'll see that _ViewStart.cshtml contains a single directive, which points to a layout file. And the beauty of this is that every view that is rendered by Razor will process this file first—getting any defaults or whatnot needed here. Consequently, this is how Razor files can avoid the need to explicitly define which Layout file (i.e., "master page") to use. Of course, you can still specify a specific Layout within individual views, but the existence of the _ViewStart.cshtml file represents a best-practices approach to avoiding DRY (don't repeat yourself) and makes it easier to establish sitewide defaults and behaviors.
Stuff You Don't Want to Remove
By way of confession, one of the first things I did after upgrading my site to MVC3 and Razor was to remove the reference that the upgrade process added to Microsoft.CSharp. I hadn't been using that previously and made the mistake of assuming that it was similar in scope to how .NET 1.0 sites and projects added a gratuitous reference to Microsoft.VisualBasic to keep VB6 developers more at ease.
Only it didn't take me long to realize that this reference is required if you want to take advantage of any logic or branching when using MVC3's new ViewBag (still hate that name, but I'm getting over it). So, unless you'd like to get some really ugly compiler errors (the kind that don't include line filenames and class numbers), then you'll want to leave this reference intact.
And while that's not exactly a Razor concern, another thing that I realized you won't want to mess with is the appSettings entry in the Viewsweb.config. Specifically, the entry that looks like this:
is one you'll probably want to leave alone—as the default definition (which sets Enabled to false) is what keeps visitors to your site from getting Razor to serve up your .cshtml (or .vbhtml) files as plain text (which could, obviously, represent a potential security problem).
Lots to Love in Razor and MVC 3
I've only spent about 20 hours with MVC3 and Razor to this point—but I'm loving everything that I'm seeing. MVC 3 itself provides a number of very powerful productivity enhancements. Validation, for example, is so much cleaner and easier to leverage, and I love how the drop-down for creating strongly typed views now lists classes as "ClassName (NameSpace)" instead of just "NameSpace.ClassName", as that minor UX change makes for less friction that will make for a big productivity boost over the next few hundred or thousand times that I use it.
And, frankly, MVC3 is just chock full of little things like that—along with Razor, which is a much bigger productivity boost than I could have imagined or anticipated.
In short, there's lots to love. And this is easily the best release of MVC yet—which says a lot given how much I loved MVC1 and MVC2.
Michael K. Campbell ([email protected]) is a contributing editor for SQL Server Magazine and a consultant with years of SQL Server DBA and developer experience. He enjoys consulting, development, and creating free videos for www.sqlservervideos.com.
About the Author
You May Also Like