What's New in ASP.NET MVC 2.0?

Introduction

Overall, ASP.NET is one of the most popular web application frameworks along with PHP, Java and others. However, the classic ASP.NET WebForms style of application development also has its limitations. For instance, cleanly separating the user interface from the application logic and database access can be a challenge in WebForms applications. Thus, Microsoft created ASP.NET MVC. MVC stands for Model View Controller.

The ASP.NET MVC technology has already been introduced earlier (see the Resources section at the end of this article), and thus this article focuses on the new and improved features planned for .NET Framework version 4.0 that should become available in Spring, 2010. Originally Microsoft announced Visual Studio 2010 would launch on March 22nd, 2010, but most recent announcements indicate delays. As far as version numbers are concerned, the next version of ASP.NET MVC will be assigned the version number 2.0. In this article, you will learn what's new and improved in the newest Release Candidate (RC) version of ASP.NET MVC 2. At the time of this writing (late December, 2009) the latest beta version of Visual Studio 2010 is Beta 2, and it doesn't yet come with the ASP.NET MVC 2 RC. The unfortunate thing is that if you are using Visual Studio 2010 Beta 2, you cannot yet test MVC 2 RC with that version (you can naturally continue to use the older Beta 2 version). Instead, you must test the MVC 2 RC on Visual Studio 2008 SP1.

Of course, the final versions of ASP.NET MVC 2 are planned to work with both Visual Studio 2008 and 2010, so the current is only an interim situation .

Exploring the new features

ASP.NET MVC 2 is an evolutional update to the framework. The basic features of the original version 1.0 are intact, but new features make development easier and result in cleaner code. The following list summarizes the key new features:

  1. Area support and multi-project routing
  2. Improved syntax for handling posts (form submits) in controllers
  3. HtmlHelper object improvements
  4. Attribute support for field validation in models
  5. Globalization of validation messages
  6. Field templates with custom user controls, and more.

Let's walk through each of these in more detail, starting from the top. In MVC 1.0, each view page was thought of as being a separate unit, and served to the browser as a single unit, possibly combined with a master page. However, if you wanted to combine, say, two views into a single page, you either had to manually render one of the pages or create a user control (.ascx) from one of the views, and then use that control inside the main view page. Although user controls are a fine solution, they break out of the MVC pattern.

In MVC 2, you can utilize so-called areas to solve the problem (Figure 1). With area support, you can combine different view pages into a single, larger view similar to the way you can build master pages (.master) and designate parts of them to be filled with content at run-time. It is possible to combine areas into views both inside a single MVC web project ("intra-project areas"), or combine areas in different projects into views ("inter-project areas"), accessible through direct URLs in the same scope.


Figure 1. Areas can be used to created complex views.

The following paragraphs walk you through using areas inside a single project. If you wanted to combine multiple MVC web projects into a single larger application, you would need to manually edit the .csproj project files of each project part of the overall solution (the edits you need to do are documented in the .csproj XML comments), add proper project references from the child projects to the master project, and then register routes using the MapAreaRoute method of the Routes object in the Global.asax file. In this article, focus is on single-project area support.

To get started with the areas, right-click your project's main node in Solution Explorer, and select the Add/Area command from the popup menu. This will open a dialog box asking for the name of your new area (Figure 2). Unlike with controller names, you don't need to append the word "Area" to the name, but you can if you prefer. However, bear in mind that intra-project areas will be accessed using the default route of /areaname/controllername/action/id. Because of this, you might not want to suffix the word "Area". In this article however, the word "Area" is appended for clarity.


Figure 2. When adding an area, you must give it a name.

Once you have created your area, Visual Studio will add a new folder called "Areas" in your project (Figure 3). This folder will contain a sub-folder with the name of your area, and inside that you will see a familiar layout of folders for controllers, views and models. In fact, you would add controllers, views and models to this area folder just the same as you would add them to your "master" MVC project. All in all, an area is like a mini MVC application inside another. Note also the AreaRegistration.cs code file. This file's definitions are referenced to from the Global.asax.cs file.


Figure 3. Areas occupy their own folder inside your project.

Areas can be used in multiple ways. Because they are directly accessible using the previously mentioned default route, you can utilize them like any other link inside your application. Or, if you had an area controller action that would return a snippet of HTML code to be used inside a larger HTML page (a normal view page), you could use the HtmlHelper.RenderAction method as follows:

<% Html.RenderAction("NetworkStatus", "Application", new { Area = "StatusArea" }); %>

Notice how there's an anonymous object being used to specify which area you want to use. Because areas can be completely independent of the master project, you can easily create usable parts or building blocks from your MVC applications and then combine them into larger solutions.

Area support is a very welcome addition to the framework. Luckily to us developers, area support is by no means the only new feature in ASP.NET MVC 2, like the next sections show.

Handling posts and encoding

When you need to handle form posts in your MVC applications, you generally write a new, overloaded controller action method to process the submitted data, and store it for example in a database. Since you only want these methods to be called using the HTTP protocol POST verb, you add an attribute at the beginning of the method like this:

  [AcceptVerbs(HttpVerbs.Post)]
  public ActionResult MyAction(MyObject data)
  ...

Although there's nothing wrong in the AcceptVerbs attribute, ASP.NET MVC 2 allows you to achieve the same thing with a shorter attribute declaration:

  [HttpPost]
  public ActionResult MyAction(MyObject data)
  ...

Even though this is a small improvement, it is very likely that all MVC developers give it a warm welcome. Another useful new improvement is the support for automatically encoded output tags in view pages. Strictly speaking, this is not a new ASP.NET MVC feature, but instead a feature in ASP.NET 4.0. Even so, this new tag type is especially useful in MVC applications.

To illustrate the new tag, consider the following very common need to encode output for HTML:

  <%= Model.CustomerName %>

This is a very simple tag, and works well in many situations. However, if the customer name were to contain certain special characters, you would need to encode the output to avoid user interface mess-ups and cross-site scripting attacks. A straightforward MVC method would do the trick:

  <%= Html.Encode(Model.CustomerName) %>

All these ways to encode output are not inconvenient, but a shorter syntax would be great. This is what the nifty new "code block" tag does:

  <%: Model.CustomerName %>

Notice the colon (:) immediately after the opening tag. It is a new way to encode output. The old equal sign syntax (which itself is a shortcut for Response.Write) is not going away. You can continue to use the old way, but the colon-syntax encoding is there to make the view page syntax cleaner.

Note that at this writing, you cannot use ASP.NET MVC 2 RC within Visual Studio 2010 Beta 2. Thus, you cannot effectively use this combination to test these code block tags, but you can test them in regular ASP.NET 4.0 applications (or with the older MVC Beta 2).

Using lambda expressions with the HtmlHelper object

If you have used ASP.NET MVC 1.0, then you've most probably also created a model object and enabled editing of its details with HTML code similar to the following:

  <%= Html.TextBox("Name", Model.Name) %>

Although this is fine for many purposes, the problem is that you still have to enter a string constant. Because it is a string, the compiler will not complain if you later change the property name in the model class, but forget to change the HTML tag. Also, the syntax is somewhat verbose (at least to some developers), and requires you to manually create one field per model object property.

In ASP.NET MVC 2, you can use the new TextBoxFor method. Just like the previous HtmlHelper methods like Label, ListBox, and so on, there are now multiple *For methods that all accept a lambda expression returning the correct object value.

Thus, to create a new editing control for the Name property, you could write code like this:

  <%= Html.TextBoxFor(c => c.Name) %>

Here, the lambda expression parameter "c" is replaced at runtime with the model object instance, and in addition to getting rid of the string value, you will get full IntelliSense support just like before with the model object.

ASP.NET MVC 2 also brings support for a convenient way to create editing forms for complex objects quickly. For instance, if you had a model object with three fields, you could either manually create labels and text boxes for each of the three fields, or use a new extension method called EditorForModel. This method will create form fields for each visible property in the model:

  <%= Html.EditorForModel() %>

This method is really convenient, if you don't have special formatting requirements for your editing forms.

What's New in ASP.NET MVC 2.0?

Validating field values with attributes

Validating form fields in ASP.NET MVC applications often raises questions. For instance, you could argue what would be the correct location for view form validation, and whether models should be able to validate themselves, and how errors should be shown on the view.

From the beginning, ASP.NET MVC has had pretty nice support for view validation, for example with the integrated validation summaries and field-by-field messages to the user. But this has been previously done in code by manipulating the ModelState object, accessible from the controller code.

In ASP.NET MVC 2, you can start to use model attributes to define constraints to the values accepted, such as valid value ranges, mandatory fields, and so forth. Many of these attributes are common to for example ASP.NET Dynamic Data technology, and live in the System.ComponentModel.DataAnnotations namespace.

For instance, you could use the Required attribute to specify that certain fields in your model are always required to have a value:

  public class Customer
  {
      [Required]
      public string Name { get; set; }
  
      [Required]
      public string Company { get; set; }
  
      public string Street { get; set; }
      public string City { get; set; }
      public string Zip { get; set; }
  }

With the [Required] tags in place, ASP.NET MVC 2 is able to automatically check mandatory fields without any additional code (Figure 4). And even if the attributes are in place, you can still continue to use code- based validation methods and the ModelState object.

[Attributes.jpg]
Figure 4. Attributes are a new way to validate used input without code.

The attributes in the DataAnnotations namespace include RequiredAttribute, RangeAttribute, RegularExpressionAttribute and StringLength. With the attributes, you can already get far in basic data validation requirements.

Speaking of validation, by default all validation messages are shown in the English language. While this is fine for many applications, equally many applications need a translated set of validation error messages. If you only require a single language, such as Spanish in your application, then it is easy to simply specify those validation strings whenever you manually add a model state error, or use one of the pre-written validation attributes. For instance:

public class Customer { [Required(ErrorMessage = "La informaciC3n es incorrecta")] public string Name { get; set; } ...

In addition to providing the error messages directly in code, you can also use resource files. For instance, you can create .resx files with appropriate resource entries, and then point to those values at development time. Then, at runtime, the ASP.NET engine can load the correct resource files based on the settings in your Web.config file or even based on the user's browser language. For example:

     public class Customer
     {
         [Required(
             ErrorMessageResourceType = typeof(MyStrings),
             ErrorMessageResourceName = "CustomerNameMissing 2")]
         public string Name { get; set; }
        ...
 

Here, the Required attribute is constructed with two additional properties, ErrorMessageResourceType and ErrorMessageResourceName. The former specifies the type of the resource file, and the latter the property value name (key name) in the resource file itself. The value associated with this name is then fetched at runtime from the correct resource file, such as MyStrings.en- US.resx or MyStrings.es-ES.resx.

Adding the resource file to your project is straightforward, but there's one thing you need to do before this works. By default, resource strings are created as internal properties, and thus they don't have the visibility to other assemblies. Because of this, you must change them to public.

Because the MyStrings.Designer.cs file is always auto-generated by a tool from the actual .resx file, there's not much point in editing the designer code file by hand, as it will be overwritten then next time you build. Thus, you need to change the code generation setting as follows. In Solution Explorer, point to the .resx file in question, and then look at the Properties window.

This file has a property called "Custom Tool", and has by default the value of "ResXFileCodeGenerator". Change this value to be "PublicResXFileCodeGenerator", and then do a full rebuild of your solution (Figure 5). Then, the resource strings begin to work as expected. Note that if you misspell the resource value name or don't properly declare the values as public properties, the validation messages will never show. In effect, the validation always succeeds, even if a Required field contains no value.

[Resources.jpg]
Figure 5. For resource strings to work, you must make sure the strings have public visibility.

Field templates with user controls

If you are creating larger ASP.NET MVC applications, chances are your web application will contain multiple forms that allow the user to display information about similar data types. For instance, the customer object might contain DateTime values, which you might with display in a certain format, such as with only the date portion.

If you have only one or two view pages where such DateTime fields are shown, it is probably easiest to simply format the output in the view page itself. However, if you have fifty such pages, the work is clearly tedious. In these situations, field templates, a new feature in ASP.NET MVC 2, become very useful.

Field templates where first used in ASP.NET Dynamic Data applications in .NET 3.5, but they can now be used in MVC applications as well. By using custom user controls (.ascx files), you can specify how each DateTime field in one, some or all view pages should be displayed.

For instance, say you wanted to show all DateTime values in your application without a time value (using the DateTime.ToShortDateString method). To use the templates, you would need to create a new folder called "DisplayTemplates" under your solution's View/Shared folder. The user control should be named the same as the data type you want to change, in this case DateTime.ascx.

The code inside the file would look like this:

  <%@ Control Language="C#" AutoEventWireup="true"
  CodeBehind="DateTime.ascx.cs"
  Inherits="Mvc2Demo.Views.Shared.DisplayTemplates.DateTime" %>
  <%= ((DateTime)Model).ToShortDateString() %>

Here, the Model object contains the value of the singular field that is the source value for this DateTime value. Since the Model is by default of type System.Object, a type cast is required. To get access to the Model object, you need to edit the code-behind file of the user control, so that the class inherits from System.Web.Mvc.ViewUserControl as follows (you could also specify this type directly in the .ascx file and thus avoid creating the code- behind file at all):

  public partial class DateTime : System.Web.Mvc.ViewUserControl
  {
  ...
  }

When the .ascx file is stored in the Views/Shared/DisplayTemplates folder, every view page showing a DateTime object will now use the new formatting. You could also create the DisplayTemplate folder below the Views/MyControllerName folder, in which case the user control would only be used for this particular controller. In a similar fashion, areas can also support custom templates. Also, in your model objects, you can use the UIHint attribute to specify which template type should be used to render the control.

In addition to the DisplayTemplate folder, MVC also supports a different set of templates for editing values. For editing, the MVC framework looks for user controls inside the EditorTemplates subfolder. However, the full details of editor and how the templates work behind the scenes are a topic of another article.

Conclusion

ASP.NET MVC is a great addition to the Microsoft web application development framework. From the very start, MVC has had success in the .NET developer community, and is today a popular model for ASP.NET web applications.

MVC started as a simple technology that was easy to get up to speed with. However, building larger applications with the 1.0 version could easily become quite tedious. In the forth-coming MVC version 2.0, many of these problems are addressed. HTML syntax is becoming clearer, and there's less of code to write. Also, support for areas enable you to combine multiple controllers into a single view, or even multiple projects to form a larger web solution.

Shortly put, ASP.NET MVC 2 is a technology you need to familiarize yourself with if you are serious about web development on the .NET platform.

About the Author

Jani Jarvinen is a software development trainer and consultant in Finland. He is a Microsoft C# MVP and a frequent author and has published three books about software development. He is the group leader of a Finnish software development expert group at ITpro.fi and a board member of the Finnish Visual Studio Team System User Group. His blog can be found at http://www.saunalahti.fi/janij/. You can send him mail by clicking on his name at the top of the article.

Resources

ASP.NET MVC 101
ASP.NET MVC 2 RC for Visual Studio 2008
Visual Studio 2010 Beta 2



About the Author

Jani Jarvinen

Jani Jarvinen is a software development trainer and consultant in Finland. He is a Microsoft C# MVP, a frequent author and has published three books about software development. He is the group leader of a Finnish software development expert group at ITpro.fi and a board member of the Finnish Visual Studio Team System User Group. His blog can be found at http://www.saunalahti.fi/janij/. You can send him mail by clicking on his name at the top of the article.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Is your sales and operations planning helping or hurting your bottom line? Here are 5 useful tips from the experts at Quintiq to guide you to a better S&OP strategy.

  • Live Event Date: July 30, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT You may already know about some of the benefits of Bluemix, IBM's open platform for developing and deploying mobile and web applications. Check out this upcoming eSeminar that focuses on building an Android application using the MobileData service, with a walk-through of the real process and workflow used to build and link the MobileData service within your application. Join IBM's subject matter experts as they show you the way to build a base …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds