Razor View Engine
The Razor view engine is a new view engine option for ASP.NET MVC that supports the Razor templating syntax. The Razor syntax is a streamlined approach to HTML templating designed with the goal of being a code driven minimalist templating approach that builds on existing C#, VB.NET and HTML knowledge. The result of this approach is that Razor views are very lean and do not contain unnecessary constructs that get in the way of you and your code.
ASP.NET MVC 3 Preview 1 only supports C# Razor views which use the .cshtml file extension. VB.NET support will be enabled in later releases of ASP.NET MVC 3. For more information and examples, see Introducing “Razor” – a new view engine for ASP.NET on Scott Guthrie’s blog.
Dynamic View and ViewModel Properties
A new dynamic View property is available in views, which provides access to the ViewData object using a simpler syntax. For example, imagine two items are added to the ViewData dictionary in the Index controller action using code like the following:
public ActionResult Index() {
ViewData["Title"] = "The Title";
ViewData["Message"] = "Hello World!";
}
Those properties can be accessed in the Index view using code like this:
<h2>View.Title</h2>
<p>View.Message</p>
There is also a new dynamic ViewModel property in the Controller class that lets you add items to the ViewData dictionary using a simpler syntax. Using the previous controller example, the two values added to the ViewData dictionary can be rewritten using the following code:
public ActionResult Index() {
ViewModel.Title = "The Title";
ViewModel.Message = "Hello World!";
}
“Add View” Dialog Box Supports Multiple View Engines
The Add View dialog box in Visual Studio includes extensibility hooks that allow it to support multiple view engines, as shown in the following figure:
Service Location and Dependency Injection Support
ASP.NET MVC 3 introduces improved support for applying Dependency Injection (DI) via Inversion of Control (IoC) containers. ASP.NET MVC 3 Preview 1 provides the following hooks for locating services and injecting dependencies:
- Creating controller factories.
- Creating controllers and setting dependencies.
- Setting dependencies on view pages for both the Web Form view engine and the Razor view engine (for types that derive from ViewPage, ViewUserControl, ViewMasterPage, WebViewPage).
- Setting dependencies on action filters.
Using a Dependency Injection container is not required in order for ASP.NET MVC 3 to function properly.
Global Filters
ASP.NET MVC 3 allows you to register filters that apply globally to all controller action methods. Adding a filter to the global filters collection ensures that the filter runs for all controller requests. To register an action filter globally, you can make the following call in the Application_Start method in the Global.asax file:
GlobalFilters.Filters.Add(new MyActionFilter());
The source of global action filters is abstracted by the new IFilterProvider interface, which can be registered manually or by using Dependency Injection. This allows you to provide your own source of action filters and choose at run time whether to apply a filter to an action in a particular request.
New JsonValueProviderFactory Class
The new JsonValueProviderFactory class allows action methods to receive JSON-encoded data and model-bind it to an action-method parameter. This is useful in scenarios such as client templating. Client templates enable you to format and display a single data item or set of data items by using a fragment of HTML. ASP.NET MVC 3 lets you connect client templates easily with an action method that both returns and receives JSON data.
Support for .NET Framework 4 Validation Attributes and IvalidatableObject
The ValidationAttribute class was improved in the .NET Framework 4 to enable richer support for validation. When you write a custom validation attribute, you can use a new IsValid overload that provides a ValidationContext instance. This instance provides information about the current validation context, such as what object is being validated.
This change enables scenarios such as validating the current value based on another property of the model. The following example shows a sample custom attribute that ensures that the value of PropertyOne is always larger than the value of PropertyTwo:
public class CompareValidationAttribute : ValidationAttribute {
protected override ValidationResult IsValid(object value,
ValidationContext validationContext) {
var model = validationContext.ObjectInstance as SomeModel;
if (model.PropertyOne > model.PropertyTwo) {
return ValidationResult.Success;
}
return new ValidationResult("PropertyOne must be larger than PropertyTwo");
}
}
Validation in ASP.NET MVC also supports the .NET Framework 4 IValidatableObject interface. This interface allows your model to perform model-level validation, as in the following example:
public class SomeModel : IValidatableObject {
public int PropertyOne { get; set; }
public int PropertyTwo { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (PropertyOne <= PropertyTwo) {
yield return new ValidationResult(
"PropertyOne must be larger than PropertyTwo");
}
}
}
New IClientValidatable Interface
The new IClientValidatable interface allows the validation framework to discover at run time whether a validator has support for client validation. This interface is designed to be independent of the underlying implementation; therefore, where you implement the interface depends on the validation framework in use. For example, for the default data annotations-based validator, the interface would be applied on the validation attribute.
Support for .NET Framework 4 Metadata Attributes
ASP.NET MVC 3 now supports .NET Framework 4 metadata attributes such as DisplayAttribute.
New IMetadataAware Interface
The new IMetadataAware interface allows you to write attributes that simplify how you can contribute to the ModelMetadata creation process. Before this interface was available, you needed to write a custom metadata provider in order to have an attribute provide extra metadata.
This interface is consumed by the AssociatedMetadataProvider class, so support for the IMetadataAware interface is automatically inherited by all classes that derive from that class (notably, the DataAnnotationsModelMetadataProvider class).
New Action Result Types
In ASP.NET MVC 3, the Controller class includes two new action result types and corresponding helper methods.
HttpNotFoundResult Action
The new HttpNotFoundResult action result is used to indicate that a resource requested by the current URL was not found. The status code is 404. This class derives from HttpStatusCodeResult. The Controller class includes an HttpNotFound method that returns an instance of this action result type, as shown in the following example:
public ActionResult List(int id) {
if (id < 0) {
return HttpNotFound();
}
return View();
}
HttpStatusCodeResult Action
The new HttpStatusCodeResult action result is used to set the response status code and description.
Permanent Redirect
The HttpRedirectResult class has a new Boolean Permanent property that is used to indicate whether a permanent redirect should occur. A permanent redirect uses the HTTP 301 status code. Corresponding to this change, the Controller class now has several methods for performing permanent redirects:
- RedirectPermanent
- RedirectToRoutePermanent
- RedirectToActionPermanent
These methods return an instance of HttpRedirectResult with the Permanent property set to true.
Breaking Changes
The order of execution for exception filters has changed for exception filters that have the same Order value. In ASP.NET MVC 2 and earlier, exception filters on the controller with the same Order as those on an action method were executed before the exception filters on the action method. This would typically be the case when exception filters were applied without a specified order Order value. In MVC 3, this order has been reversed in order to allow the most specific exception handler to execute first. As in earlier versions, if the Order property is explicitly specified, the filters are run in the specified order.
Known Issues
When you are editing a Razor view (CSHTML file), the Go To Controller menu item in Visual Studio will not be available, and there are no code snippets.