ASP.NET MVC is a framework for building web applications that applies the general Model View Controller pattern to the ASP.NET framework. Let's break that down by first looking at how ASP.NET MVC and the ASP.NET framework are related.
When ASP.NET 1.0 was first released in 2002, it was easy to think of ASP.NET and Web Forms as one and the same thing. ASP.NET has always supported two layers of abstraction, though:
The mainstream method of developing with ASP.NET included the whole Web Forms stack — taking advantage of drag-and-drop server controls and semi-magical statefulness, while dealing with the complications behind the scenes (an often confusing page life cycle, less than optimal HTML that was difficult to customize, and so on).
However, there was always the possibility of getting below all that — responding directly to HTTP requests, building out web frameworks just the way you wanted them to work, crafting beautiful HTML — using handlers, modules, and other handwritten code. You could do it, but it was painful; there just wasn't a built-in pattern that supported any of those things. It wasn't for lack of patterns in the broader computer science world, though. By the time ASP.NET MVC was announced in 2007, the MVC pattern was becoming one of the most popular ways of building web frameworks.
Model-View-Controller (MVC) has been an important architectural pattern in computer science for many years. Originally named Thing-Model-View-Editor in 1979, it was later simplified to Model-View-Controller. It is a powerful and elegant means of separating concerns within an application (for example, separating data access logic from display logic) and applies itself extremely well to web applications. Its explicit separation of concerns does add a small amount of extra complexity to an application's design, but the extraordinary benefits outweigh the extra effort. It has been used in dozens of frameworks since its introduction. You'll find MVC in Java and C++, on Mac and on Windows, and inside literally dozens of frameworks.
The MVC separates the user interface (UI) of an application into three main aspects:
The MVC pattern is used frequently in web programming. With ASP.NET MVC, it's translated roughly as:
In the three short years since ASP.NET MVC 1 was released in March 2009, we've seen four major releases of ASP.NET MVC and several more interim releases. In order to understand ASP.NET MVC 4, it's important to understand how we got here. This section describes the contents and background of each of the three major ASP.NET MVC releases.
In February 2007, Scott Guthrie (“ScottGu”) of Microsoft sketched out the core of ASP.NET MVC while flying on a plane to a conference on the East Coast of the United States. It was a simple application, containing a few hundred lines of code, but the promise and potential it offered for parts of the Microsoft web developer audience was huge.
As the legend goes, at the Austin ALT.NET conference in October 2007 in Redmond, Washington, ScottGu showed a group of developers “this cool thing I wrote on a plane” and asked if they saw the need and what they thought of it. It was a hit. In fact, many people were involved with the original prototype, codenamed Scalene. Eilon Lipton e-mailed the first prototype to the team in September 2007, and he and ScottGu bounced prototypes, code, and ideas back and forth.
Even before the official release, it was clear that ASP.NET MVC wasn't your standard Microsoft product. The development cycle was highly interactive: There were nine preview releases before the official release, unit tests were made available, and the code shipped under an open source license. All these highlighted a philosophy that placed a high value on community interaction throughout the development process. The end result was that the official MVC 1.0 release — including code and unit tests — had already been used and reviewed by the developers who would be using it. ASP.NET MVC 1.0 was released on 13 March 2009.
ASP.NET MVC 2 was released just one year later, in March 2010. Some of the main features in MVC 2 included:
There were also lots of API enhancements and “pro” features, based on feedback from developers building a variety of applications on ASP.NET MVC 1, such as:
One important precedent set by the MVC 2 release was that there were very few breaking changes. I think this is a testament to the architectural design of ASP.NET MVC, which allows for a lot of extensibility without requiring core changes.
ASP.NET MVC 3 shipped just 10 months after MVC 2, driven by the release date for Web Matrix. Some of the top features in MVC 3 included:
Since these MVC 3 features are relatively recent and are pretty important, we'll go through them in a little more detail.
Razor is the first major update to rendering HTML since ASP.NET 1 shipped almost a decade ago. The default view engine used in MVC 1 and 2 was commonly called the Web Forms view engine, because it uses the same ASPX/ASCX/MASTER files and syntax used in Web Forms. It works, but it was designed to support editing controls in a graphical editor, and that legacy shows. An example of this syntax in a Web Forms page is shown here:
<%@ Page Language="C#" MasterPageFile="</Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcMusicStore.ViewModels.StoreBrowseViewModel>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Browse Albums </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <div class="genre"> <h3><em><%: Model.Genre.Name %></em> Albums</h3> <ul id="album-list"> <% foreach (var album in Model.Albums) { %> <li> <a href="<%: Url.Action("Details", new { id = album.AlbumId }) %>"> <img alt="<%: album.Title %>" src="<%: album.AlbumArtUrl %>" /> <span><%: album.Title %></span> </a> </li> <% } %> </ul> </div> </asp:Content>
Razor was designed specifically as a view engine syntax. It has one main focus: code-focused templating for HTML generation. Here's how that same markup would be generated using Razor:
@model MvcMusicStore.Models.Genre @{ViewBag.Title = "Browse Albums";} <div class="genre"> <h3><em>@Model.Name</em> Albums</h3> <ul id="album-list"> @foreach (var album in Model.Albums) { <li> <a href="@Url.Action("Details", new { id = album.AlbumId })"> <img alt="@album.Title" src="@album.AlbumArtUrl" /> <span>@album.Title</span> </a> </li> } </ul> </div>
The Razor syntax is easier to type, and easier to read. Razor doesn't have the XML-like heavy syntax of the Web Forms view engine.
We've talked about how working with the Razor syntax feels different. To put this in more quantifiable terms, let's look at some of the team's design goals in creating the Razor syntax:
@foreach (var album in Model.Albums) { <li> <a href="@Url.Action("Details", new { id = album.AlbumId })"> <img alt="@album.Title" src="@album.AlbumArtUrl" /> <span>@album.Title</span> </a> </li> }
“I kept […] going cross-eyed when I was trying to figure out what the syntax rules were for Razor until someone said stop thinking about it, just type an “at” sign and start writing code and I realize that there really is no Razor.”
—Hanselminutes #249: On Webmatrix with Rob Conery
http://hanselminutes.com/default.aspx?showid=268
Validation is an important part of building web applications, but it's never fun. I've always wanted to spend as little time as possible writing validation code, as long as I was confident that it worked correctly.
MVC 2's attribute-driven validation system removed a lot of the pain from this process by replacing repetitive imperative code with declarative code. However, support was focused on a short list of top validation scenarios. There were plenty of cases where you'd get outside of the “happy path” and have to write a fair amount more code. MVC 3 extended the validation support to cover most scenarios you're likely to encounter. For more information on validation in ASP.NET MVC, see Chapter 6.
MVC 2 was compiled against .NET 3.5 and thus didn't support any of the .NET 4 Data Annotations enhancements. MVC 3 picks up some new, very useful validation features available due to .NET 4 support. Some examples include:
MVC 3's support for the .NET 4 IValidatableObject interface deserves individual recognition. You can extend your model validation in just about any conceivable way by implementing this interface on your model class and implementing the Validate method, as shown in the following code:
public class VerifiedMessage : IValidatableObject { public string Message { get; set; } public string AgentKey { get; set; } public string Hash { get; set; } public IEnumerable<ValidationResult> Validate( ValidationContext validationContext) { if (SecurityService.ComputeHash(Message, AgentKey) != Hash) yield return new ValidationResult("Agent compromised"); } }
Unobtrusive JavaScript is a general term that conveys a general philosophy, similar to the term REST (Representational State Transfer). The high-level description is that unobtrusive JavaScript doesn't intermix JavaScript code in your page markup. For example, rather than hooking in via event attributes like onclick and onsubmit, the unobtrusive JavaScript attaches to elements by their ID or class, often based on the presence of other attributes (such as HTML5 data- attributes).
Unobtrusive JavaScript makes a lot of sense when you consider that your HTML document is just that — a document. It's got semantic meaning, and all of it — the tag structure, element attributes, and so on — should have a precise meaning. Strewing JavaScript gunk across the page to facilitate interaction (I'm looking at you, _____doPostBack!) harms the content of the document.
MVC 3 added support for unobtrusive JavaScript in two ways:
MVC 2 shipped with jQuery, but used Microsoft Ajax for validation. MVC 3 completed the transition to using jQuery for Ajax support by converting the validation support to run on the popular jQuery Validation plugin. The combination of Unobtrusive JavaScript support (discussed previously) and jQuery validation using the standard plugin system means that the validation is both extremely flexible and can benefit from the huge jQuery community.
Client-side validation was turned on by default for MVC 3 projects, and can be enabled site-wide with a web.config setting or by code in global.asax for upgraded projects.
MVC 3 included JavaScript Object Notation (JSON) binding support via the new JsonValueProviderFactory, enabling your action methods to accept and model-bind data in JSON format. This is especially useful in advanced Ajax scenarios like client templates and data binding that need to post data back to the server.
MVC 3 introduced a new concept called a dependency resolver, which greatly simplified the use of dependency injection in your applications. This made it easier to decouple application components, making them more configurable and easier to test.
Support was added for the following scenarios:
This is a big enough topic that we've devoted an entire new chapter (Chapter 12) to it.
MVC 2 action filters gave you hooks to execute code before or after an action method ran. They were implemented as custom attributes that could be applied to controller actions or to an entire controller. MVC 2 included some filters in the box, like the Authorize attribute.
MVC 3 extended this with global action filters, which apply to all action methods in your application. This is especially useful for application infrastructure concerns like error handling and logging.
The MVC 4 release is building on a pretty mature base and is able to focus on some more advanced scenarios. Some top features include:
The following sections provide an overview of these features. We'll be going into them in more detail throughout the book.
ASP.NET MVC was designed for creating websites. Throughout the platform are obvious design decisions that indicate the assumed usage: responding to requests from browsers and returning HTML.
However, ASP.NET MVC made it really easy to control the response down to the byte, and the MVC pattern was really useful in creating a service layer. ASP.NET developers found that they could use it to create web services that returned XML, JSON, or other non-HTML formats, and it was a lot easier than grappling with other service frameworks, such as Windows Communication Foundation (WCF), or writing raw HTTP handlers. It still had some quirks, as you were using a website framework to deliver services, but many found that it was better than the alternatives.
MVC 4 includes a better solution: ASP.NET Web API (referred to as Web API), a framework that offers the ASP.NET MVC development style but is tailored to writing HTTP services. This includes both modifying some ASP.NET MVC concepts to the HTTP service domain and supplying some new service-oriented features.
Here are some of the Web API features that are similar to MVC, just adapted for the HTTP service domain:
Web API also adds some new concepts and features specific to HTTP service development:
Although ASP.NET Web API is included with MVC 4, it can be used separately. In fact, it has no dependencies on ASP.NET at all, and can be self-hosted — that is, hosted outside of ASP.NET and IIS. This means you can run Web API in any .NET application, including a Windows Service or even a simple console application. For a more detailed look at ASP.NET Web API, see Chapter 11.
The visual design of the default template for MVC 1 projects had gone essentially unchanged through MVC 3. When you created a new MVC project and ran it, you got a white square on a blue background, as shown in Figure 1.2. (The blue doesn't show in this black and white book, but you get the idea.)
In MVC 4, both the HTML and CSS for the default template have been completely redesigned. A new MVC application appears as shown in Figure 1.3.
In addition to a more modern design (or, some would say, any thought to design at all), the new template also features support for mobile browsers through adaptive layout. Adaptive layout is a technique for designing fluid web layouts that respond to differing screen dimensions through CSS media queries. When the site is viewed at lower than 850px width (such as on a phone or tablet), the CSS automatically reconfigures to optimize for the small form factor, as shown in the mobile emulator in Figure 1.4.
While your sites deserve their own custom design, it's nice that the underlying HTML and CSS in an MVC 4 project are set up using modern markup and CSS that responds well to the growing mobile browser viewership.
If you're going to be creating sites that will only be viewed in mobile browsers, you can make use of the new Mobile Project template. This template preconfigures your site to use the popular jQuery Mobile library, which provides styles that look good and work well on mobile devices, as shown in Figure 1.5. jQuery Mobile is touch optimized, supports Ajax navigation, and uses progressive enhancement to support mobile device features.
Display modes use a convention-based approach to allow selecting different views based on the browser making the request. The default view engine first looks for views with names ending with.Mobile.cshtml when the browser's user agent indicates a known mobile device. For example, if you have a generic view titled Index.cshtml and a mobile view titled Index.Mobile.cshtml, MVC 4 will automatically use the mobile view when viewed in a mobile browser.
Additionally, you can register your own custom device modes that will be based on your own custom criteria — all in just one code statement. For example, to register a WinPhone device mode that would serve views ending with .WinPhone.cshtml to Windows Phone devices, you'd use the following code in the Application_Start method of your Global.asax:
DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("WinPhone") { ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf ("Windows Phone OS", StringComparison.OrdinalIgnoreCase) >= 0) });
ASP.NET 4 supports the same bundling and minification framework that is included in ASP.NET 4.5. This system reduces requests to your site by combining several individual script references into a single request. It also “minifies” the requests through a number of techniques, such as shortening variable names and removing whitespace and comments. This system works on CSS as well, bundling CSS requests into a single request and compressing the size of the CSS request to produce equivalent rules using a minimum of bytes, including advanced techniques like semantic analysis to collapse CSS selectors.
The bundling system is highly configurable, allowing you to create custom bundles that contain specific scripts and reference them with a single URL. You can see some examples by referring to default bundles listed in /App_Start/BundleConfig.cs in a new MVC 4 application using the Internet template.
One nice byproduct of using bundling and minification is that you can remove file references from your view code. This means that you can add or upgrade script libraries and CSS files that have different filenames without having to update your views or layout, since the references are made to script and CSS bundles rather than individual files. For example, the MVC Internet application template includes a jQuery bundle that is not tied to the version number:
bundles.Add(new ScriptBundle("∼/bundles/jquery").Include( "∼/Scripts/jquery-{version}.js"));
This is then referenced in the site layout (_Layout.cshtml) by the bundle URL, as follows:
@Scripts.Render("∼/bundles/jquery")
Since these references aren't tied to a jQuery version number, updating the jQuery library (either manually or via NuGet) will be picked up automatically by the bundling and minification system without requiring any code changes.
MVC project templates have long been including top open source libraries like jQuery and Modernizr. As of MVC 3, these were included via NuGet, which makes it even simpler to upgrade them and manage dependencies. MVC 4 project templates include a few new libraries:
MVC 4 includes a lot of features not listed previously. The full list is in the release notes, available at http://www.asp.net/whitepapers/mvc4-release-notes. Some of the most interesting ones that don't fit into any of the preceding themes are listed here.
Single Page Application
Recipes
ASP.NET MVC has been under an open source license since the initial release, but it was just open source code rather than a full open source project. You could read the code; you could modify code; you could even distribute your modifications; but you couldn't contribute your code back to the official MVC code repository.
That changed with the ASP.NET Web Stack open source announcement in May 2012. This announcement marked the transition of ASP.NET MVC, ASP.NET Web Pages (including the Razor view engine), and ASP.NET Web API from open source licensed code to fully open source projects. All code changes and issue tracking for these projects is done in public code repositories, and these projects are allowed to accept community code contributions (aka pull requests) if the team agrees that the changes make sense.
Even in the short time since the project has been opened, several bug fixes and feature enhancements have already been accepted into the official source and will ship with the MVC 4 release. External code submissions are reviewed and tested by the ASP.NET team, and when released will be supported by Microsoft just as any previous ASP.NET MVC releases have been.
Even if you're not planning to contribute any source code, the public repository makes a huge difference in visibility. While in the past you needed to wait for interim releases to see what the team was working on, you can view source check-ins as they happen (at http://aspnetwebstack.codeplex.com/SourceControl/list/changesets) and even run nightly releases of the code to test out new features as they're written.