This post describes features that have been introduced in the ASP.NET MVC 3 Beta release (taken from ASP.NET MVC Beta release notes) ASP.NET MVC 3 includes NuPack Package Manager, which is an integrated package management tool for adding libraries and tools to Visual Studio projects. For the most part, it automates the steps that developers take today to get a library into their source tree.
You can work with NuPack as a command line tool, as an integrated console window inside Visual Studio 2010, from the Visual Studio context menu, and as set of PowerShell cmdlets.
When you create a new project, the New Project dialog box now lets you specify the view engine as well as an ASP.NET MVC project type.
Support for modifying the list of templates and view engines listed in the dialog box is not included in this release.
The default templates are the following:
· Empty. Contains a minimal set of files for an ASP.NET MVC project, including the default directory structure for ASP.NET MVC projects, a small Site.css file that contains the default ASP.NET MVC styles, and a Scripts directory that contains the default JavaScript files.
· Internet Application. Contains sample functionality that demonstrates how to use the membership provider within ASP.NET MVC.
The way to specify the model type for strongly typed Razor views has been simplified by using the new @model directive for CSHTML views and @ModelType directive for VBHTML views. In earlier versions of ASP.NET MVC, you would specify a strongly typed model for Razor views this way:
@inherits System.Web.Mvc.WebViewPage
|
In this release, you can use the following syntax:
@model MyModelNamespace.MyModelType
|
The new ASP.NET Web Pages technology includes a set of helper methods that are useful for adding commonly used functionality to views and controllers. ASP.NET MVC 3 supports using these helper methods within controllers and views (where appropriate). These methods are contained in the System.Web.Helpers assembly. The following table lists a few of the ASP.NET Web Pages helper methods.
Helper | Description |
Chart | Renders a chart within a view. Contains methods such as Chart.ToWebImage, Chart.Save, and Chart.Write. |
Crypto | Uses hashing algorithms to create properly salted and hashed passwords. |
WebGrid | Renders a collection of objects (typically, data from a database) as a grid. Supports paging and sorting. |
WebImage | Renders an image. |
WebMail | Sends an email message. |
A quick reference topic that lists the helpers and basic syntax is available as part of the ASP.NET Razor syntax documentation at the following URL:
Building on the ASP.NET MVC 3 Preview 1 release, the current release includes added support for two new services and four existing services, and improved support for dependency resolution and the Common Service Locator.
New IControllerActivator Interface for Fine-Grained Controller Instantiation
The new IControllerActivator interface provides more fine-grained control over how controllers are instantiated via dependency injection. The following example shows the interface:
namespace System.Web.Mvc {
using System.Web.Routing;
public interface IControllerActivator {
IController Create(RequestContext requestContext, Type controllerType);
}
}
|
Contrast this to the role of the controller factory. A controller factory is an implementation of the IControllerFactory interface, which is responsible both for locating a controller type and for instantiating an instance of that controller type.
Controller activators are responsible only for instantiating an instance of a controller type. They do not perform the controller type lookup. After locating a proper controller type, controller factories should delegate to an instance of IControllerActivator to handle the actual instantiation of the controller.
The DefaultControllerFactory class has a new constructor that accepts an IControllerFactory instance. This lets you apply Dependency Injection to manage this aspect of controller creation without having to override the default controller-type lookup behavior.
IServiceLocator Interface Replaced with IDependencyResolver
Based on community feedback, the ASP.NET MVC 3 Beta release has replaced the use of the IServiceLocator interface with a slimmed-down IDependencyResolver interface specific to the needs of ASP.NET MVC. The following example shows the new interface:
namespace System.Web.Mvc {
using System.Collections.Generic;
public interface IDependencyResolver {
object GetService(Type serviceType);
IEnumerable< object > GetServices(Type serviceType);
}
}
|
As part of this change, the ServiceLocator class was also replaced with the DependencyResolver class. Registration of a dependency resolver is similar to earlier versions of ASP.NET MVC:
DependencyResolver.SetResolver(myResolver);
|
Implementations of this interface should simply delegate to the underlying dependency injection container to provide the registered service for the requested type.
When there are no registered services of the requested type, ASP.NET MVC expects implementations of this interface to return null from GetService and to return an empty collection from GetServices.
The new DependencyResolver class lets you register classes that implement either the new IDependencyResolver interface or the Common Service Locator interface (IServiceLocator). For more information about Common Service Locator, see http://commonservicelocator.codeplex.com/. New IViewActivator Interface for Fine-Grained View Page Instantiation
The new IViewPageActivator interface provides more fine-grained control over how view pages are instantiated via dependency injection. This applies to both WebFormView instances and RazorView instances. The following example shows the new interface:
namespace System.Web.Mvc {
public interface IViewPageActivator {
object Create(ControllerContext controllerContext, Type type);
}
}
|
These classes now accept an IViewPageActivator constructor argument, which lets you use dependency injection to control how the ViewPage, ViewUserControl, and WebViewPage types are instantiated.
New Dependency Resolver Support for Existing Services
The new release includes dependency resolution support for the following services:
· Model validation providers. Classes that implement ModelValidatorProvider can be registered in the dependency resolver, and the system will use them to support client- and server-side validation.
· Model metadata provider. A single class that implements ModelMetadataProvider can be registered in the dependency resolver, and the system will use it to provide metadata for the templating and validation systems.
· Value providers. Classes that implement ValueProviderFactory can be registered in the dependency resolver, and the system will use them to create value providers that are consumed by the controller and during model binding.
· Model binders. Classes that implement IModelBinderProvider can be registered in the dependency resolver, and the system will use them to create model binders that are consumed by the model binding system.
ASP.NET MVC includes Ajax helper methods such as the following:
· Ajax.ActionLink
· Ajax.RouteLink
· Ajax.BeginForm
· Ajax.BeginRouteForm
These methods use JavaScript to invoke an action method on the server rather than using a full postback. This functionality has been updated to take advantage of jQuery in an unobtrusive manner. Rather than intrusively emitting inline client scripts, these helper methods separate the behavior from the markup by emitting HTML5 attributes using the data-ajax prefix. Behavior is then applied to the markup by referencing the appropriate JavaScript files. Make sure that the following JavaScript files are referenced:
· jquery-1.4.1.js
· jquery.unobtrusive.ajax.js
By default, ASP.NET MVC 3 Beta uses jQuery validation in an unobtrusive manner in order to perform client-side validation. To enable unobtrusive client validation, make a call like the following from within a view:
Html.EnableClientValidation();
|
This requires that ViewContext.UnobtrusiveJavaScriptEnabled property is set to true, which you can do by making the following call:
Html.EnableUnobtrusiveJavaScript();
|
Also make sure the following JavaScript files are referenced.
· jquery-1.4.1.js
· jquery.validate.js
· jquery.validate.unobtrusive.js
You can enable or disable client validation and unobtrusive JavaScript globally using static members of the HtmlHelper class, as in the following example:
HtmlHelper.ClientValidationEnabled = true ;
HtmlHelper.UnobtrusiveJavaScriptEnabled = true ;
|
The default project templates enable unobtrusive JavaScript by default. You can also enable or disable these features in the root Web.config file of your application using the following settings:
< configuration >
< appSettings >
< add key = "ClientValidationEnabled" value = "true" />
< add key = "UnobtrusiveJavaScriptEnabled" value = "true" />
</ appSettings >
</ configuration >
|
Because you can enable these features by default, new overloads were introduced to the HtmlHelper class that let you override the default settings, as shown in the following examples:
public void EnableClientValidation();
public void EnableClientValidation( bool enabled);
public void EnableUnobtrusiveJavaScript();
public void EnableUnobtrusiveJavaScript( bool enabled);
|
For backward compatibility, both of these features are disabled by default.
You can now put a file named _viewstart.cshtml (or _viewstart.vbhtml) in the Views directory and add code to it that will be shared among multiple views in that directory and its subdirectories. For example, you might put the following code into the _viewstart.cshtml page in the ~/Views folder:
@{
Layout = "~/Views/Shared/_Layout.cshtml" ;
}
|
This sets the layout page for every view within the Views folder and all its subfolders recursively. When a view is being rendered, the code in the _viewstart.cshtml file runs before the view code runs. The _viewstart.cshtml code applies to every view in that folder.
By default, the code in the _viewstart.cshtml file also applies to views in any subfolder. However, individual subfolders can have their own version of the _viewstart.cshtml file; in that case, the local version takes precedence. For example, to run code that is common to all views for the HomeController, put a _viewstart.cshtml file in the ~/Views/Home folder.
The previous ASP.NET MVC preview included support for views using Razor syntax based on C#. These views use the .cshtml file extension. As part of ongoing work to support Razor, the ASP.NET MVC 3 Beta introduces support for the Razor syntax in Visual Basic, which uses the .vbhtml file extension.
For an introduction to using Visual Basic syntax in VBHTML pages, see the tutorial at the following URL:
ASP.NET MVC has always included the ValidateInputAttribute class, which invokes the core ASP.NET request validation infrastructure to make sure that the incoming request does not contain potentially malicious input. By default, input validation is enabled. It is possible to disable request validation by using the ValidateInputAttribute attribute, as in the following example:
[ValidateInput( false )]
public ActionResult SomeAction() {
return View();
}
|
However, many web applications have individual form fields that need to allow HTML, while the remaining fields should not. The ValidateInputAttribute class now lets you specify a list of fields that should not be included in request validation.
For example, if you are developing a blog engine, you might want to allow markup in the Body and Summary fields. These fields might be represented by two input element, each with a name attribute corresponding to the property name (“Body” and “Summary”). To disable request validation for these fields only, specify the names (comma-separated) in the Exclude property of the ValidateInput class, as in the following example:
[ValidateInput( true , Exclude= "Body, Summary" )]
public ActionResult About() {
return View();
}
|
Helper methods let you specify attribute name/value pairs using an anonymous object, as in the following example:
Html.TextBox( "Name" , "Value" , new {title = "Title" })
|
This approach doesn’t let you use hyphens in the attribute name, because a hyphen cannot be used for a property name in ASP.NET. However, hyphens are important for custom HTML5 attributes; for example, HTML5 uses the “data-“ prefix.
At the same time, underscores cannot be used for attribute names in HTML, but are valid within property names. Therefore, if you specify attributes using an anonymous object, and if the attribute names include an underscore,, helper methods will convert the underscores to hyphens. For example, the following helper syntax uses an underscore:
Html.TextBox( "Name" , "Value" , new {data_required = "true" })
|
The previous example renders the following markup when the helper runs:
<input data-required= "true" id= "Name" name= "Name" type= "textbox" value= "Value" />
|
· The default object template for the EditorFor and DisplayFor template helpers now supports the ordering specified in the DisplayAttribute.Order property. (In previous versions, the Order setting was not used.)
· Client validation now supports validation of overridden properties that have validation attributes applied.
· JsonValueProviderFactory is now registered by default.
· 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 value. In ASP.NET MVC 3, this order has been reversed so that the most specific exception handler executes first. As in earlier versions, if the Order property is explicitly specified, the filters are run in the specified order.
· During installation, the EULA acceptance dialog box displays the license terms in a window that is smaller than intended.
· Razor views do not have IntelliSense support nor syntax highlighting. It is anticipated that support for Razor syntax in Visual Studio will be included as part of a later release.
· When using the @model syntax to specify a strongly typed CSHTML view, language-specific shortcuts for types are not recognized. For example, @model int will not work, but @model Int32 will work. The workaround for this bug is to use the actual type name when you specify the model type.
· When using the @model syntax to specify a strongly typed CSHTML view (or @ModelType to specify a strongly typed VBHTML view), nullable types and array declarations are not supported. For example, @model int? is not supported. Instead, use @model Nullable<Int32>. The syntax @model string[] is also not supported; instead, use @model IList<string>.
· When you upgrade an ASP.NET MVC 2 project to ASP.NET MVC 3, make sure to add the following to the appSettings section of the Web.config file:
< appSettings >
< add key = "enableSimpleMembership" value = "false" />
</ appSettings >
|
· There’s a known issue that causes Forms Authentication to always redirect unauthenticated users to ~/Account/Login, ignoring the forms authentication setting used in Web.config. The workaround is to add the following app setting.
From ASP.NET MVC 3 beta release notes.