Changes in ASP.NET MVC 3 Beta

This article shows changes and bug fixes from article of Imran Baloch blog - bug Fixes and Changes in ASP.NET MVC 3 Beta  Few days ago when ASP.NET MVC team released ASP.NET MVC 3 Beta. This beta release includes some new features, some changes, some improvements and bug fixes. For detail of this beta release see Announcing NuPack, ASP.NET MVC 3 Beta, and WebMatrix Beta 2. In this article, we can see the most important changes and bug fixes. Seeing and knowing new changes will help you when you start using MVC 3 Beta from MVC 3 Preview 1 or MVC 2 because some properties and some classes are renamed in MVC 3 Beta. On the other hand, seeing and knowing bug fixes shows that how quickly ASP.NET MVC team fixes the bugs discussed in forums, which is appreciable.

New Features in ASP.NET MVC 3 Beta

This section describes features that have been introduced in the ASP.NET MVC 3 Beta release.

NuPack Package Manager

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. For more information about NuPack, visit http://nupack.codeplex.com/ and read the Getting Started Guide.

Improved New Project Dialog Box

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.

Simplified Way to Specify Strongly Typed Models in Razor Views

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:

 

In this release, you can use the following syntax:

 

Support for New ASP.NET Web Pages Helper Methods

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: http://www.asp.net/webmatrix/tutorials/asp-net-web-pages-api-reference

Additional Dependency Injection Support

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

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:

 

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.

New Support for Unobtrusive jQuery-Based Ajax

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

This feature is enabled by default in the Web.config file in the ASP.NET MVC 3 new project templates, but is disabled by default for existing projects. For more information, see Added application-wide flags for client validation and unobtrusive JavaScript later in this document.

New Support for Unobtrusive jQuery Validation

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:

 

This requires that ViewContext.UnobtrusiveJavaScriptEnabled property is set to true, which you can do by making the following call:

 

Also make sure the following JavaScript files are referenced.

· jquery-1.4.1.js

· jquery.validate.js

· jquery.validate.unobtrusive.js

This feature is enabled on by default in the Web.config file in the ASP.NET MVC 3 new project templates, but is disabled by default for existing projects. For more information, see New application-wide flags for client validation and unobtrusive JavaScript later in this document.

New Application-Wide Flags for Client Validation and Unobtrusive JavaScript

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.

New Support for Code that Runs Before Views Run

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.

New Support for the VBHTML Razor Syntax

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: http://www.asp.net/webmatrix/tutorials/asp-net-web-pages-visual-basic

More Granular Control over ValidateInputAttribute

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();
}

 

 

Helpers Convert Underscores to Hyphens for HTML Attribute Names Specified Using Anonymous Objects

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" />

Bug Fixes

· 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.

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 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.

Known Issues

· 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 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.

· 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.

<add key="autoFormsAuthentication" value="false" />

So let's see the latest changes and bug fixes in this release, LayoutPage Property is Renamed: In MVC 3 Preview 1 you can set the layout page using LayoutPage property of Razor views,

 

    @{

            LayoutPage = "~/Views/Shared/_Layout.cshtml";

     }

This property is renamed in MVC 3 Beta 1 to Layout,
    @{

            Layout = "~/Views/Shared/_Layout.cshtml";

     }

 

Razor View Engine Classes are Renamed: In MVC 3 Preview 1, razor view and razor viewengine were named as CshtmlView and CshtmlViewEngine. In MVC 3 Beta, they are renamed to RazorView and RazorViewEngine. This makes much sense to rename Cshtml to Razor because it will clear the confusion.

Razor Views Namespaces are now Configurable: In MVC 3 Preview 1, if you use a razor view then you can register global namespaces using CodeGeneratorSettings.AddGlobalImport method in Global.asax.cs,

 
1 CodeGeneratorSettings.AddGlobalImport("Namespace");

 This class is removed in ASP.NET MVC 3 Beta because you can now register global namespaces via web.config. Just open the web.config inside Views folder of ASP.NET MVC 3 beta project, you will find the following configuration,

<system.web.webPages.razor>

        <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

          <namespaces>

            <add namespace="System.Web.Mvc" />

            <add namespace="System.Web.Mvc.Ajax" />

            <add namespace="System.Web.Mvc.Html" />

            <add namespace="System.Web.Routing" />

          </namespaces>

        </pages>

    </system.web.webPages.razor>

 

 Request Validation becomes More Granular: ASP.NET helps in preventing Cross Site Scripting (XSS) (which is the most dangerous attack) via Request Validation. In previous versions of ASP.NET MVC, you can control request validation using ValidateInputAttriubte or globally control request validation by using a technique discussed in my past article. In the previous MVC versions, all the posted forms, headers, cookies and query string values are validated. In ASP.NET MVC 3 Beta, you can exclude some properties from request validation by introducing a new property Exclude on ValidateInputAttribute. For more details see this article. It is worth here to see how ASP.NET MVC team make granular request validation possible. So let's see. Default request validator will throw an exception when he see < followed by an exclamation(like <!) or < followed by the letters a through z(like <s) or & followed by a pound sign(like &#123) as a part of querystring, posted form, headers and cookie collection. It is very interesting to note that a particular key value is only validated once when this key value is read first time. For example, just run an ASP.NET MVC 2 application and append this query string, /?A=<s, you will get a dangerous input exception. Now just update your action as,

public ActionResult Index()
    {
        try
        {
            string s=Request.QueryString["A"];

        }
        catch
        {

        }
        return View();
    }

 

Again run your application with the same query string, you will get no exception. This shows that request validation for a particular key value only occur when this key value is read first time. Now let's see an interesting difference between MVC 2 and MVC 3 Beta. Create and add the following action in both ASP.NET MVC 2 project and ASP.NET MVC 3 project and run both application, then append the above query string in both applications URL. Make sure you don't set requestValidationMode to 2.0,

[ValidateInput(false)]
    public ActionResult Index()
    {
        return View();
    }

 

In this case you will only get exception in MVC 2 and you will not get any exception in MVC 3. It shows that in ASP.NET MVC 3 Beta someone had already read this query string first time, but who? The answer is GranularValidationModule HTTP Module. You may wonder that GranularValidationModule is not registered in your project's web.config and it is not present in your project. The answer is that GranularValidationModule is present in System.Web.WebPages assembly and it is registered using a new ASP.NET 4 feature, PreApplicationStartMethodAttribute, using the same technique discussed by Nikhil at Config-free IHttpModule Registration. One thing that may comes into your mind is that what will happen if you have a web form in your MVC 3 Beta project. The ASP.NET MVC team has been aware of this issue, that's why they add a new array list ValidatingArrayList(which is inherited from ArrayList) in System.Web.WebPages assembly. This array list is responsible for calling request validation again. GranularValidationModule is responsible for setting Request.Form, Request.QueryString etc, internal property to ValidatingArrayList instead of ArrayList. For proving this, just add a web form in ASP.NET MVC 3 Beta project, then run this page with the above appended query string and see the exception stack trace. If you have classic ASP or PHP pages in MVC Beta 3 project then Granular request validation will affect them ,as discussed at here and here . A quick work around (provided by Levi(ASP.NET MVC team member)) is to call InsertEntityBody method of HttpRequest in BeginRequest event. Here is the sample, which will add and register HTTP module,

 

public class ReinsertionModule : IHttpModule
{
public void Dispose()
{
// no-op

}

public void Init(HttpApplication context)
{
// hands Request.Form back to IIS for duplication
context.BeginRequest += (sender, e) =>
{
((HttpApplication)sender).Request.InsertEntityBody();
};
}
}

 

 

 Enhanced Dependency Injection Support: In ASP.MVC 3 Beta, new services for dependency resolution has been added. For details see Brad(ASP.NET MVC team member) Dependency Injection Series here. Unobtrusive Ajax and  Unobtrusive Client Side Validation is Supported: In my previous article, about how you can move your client side script at bottom in here. In ASP.MVC 3 Beta, there is no need for doing this because now it separate the javascript behavior from the HTML by emitting HTML5 attributes. For details see Brad's Moving ASP.NET MVC Client Side Validation Scripts to Bottom and Unobtrusive Client Validation in ASP.NET MVC 3 article. Razor Improvements, Code Run Before, VBHTML Support, New Helpers: In MVC 3 Beta, Razor syntax is enhanced, new helper methods has been added and vbhtml is supported. Also now you can execute some code before your views execute. For details see these release notesViews with Application Relative Path Problem is Fixed: If you have the following action in MVC 3 preview 1 then it will throws an exception.

Parsing New HTML For Validation

The unobtrusive client validation script automatically parses the initial set of HTML for validation rules when the page has finished loading. If your page dynamically adds new HTML content (perhaps throught Ajax or through client-side application code), you may wish to parse that new HTML for client validation on the new HTML elements. To parse new HTML, you can call the jQuery.validator.unobtrusive.parse() method, passing it a selector for the HTML that you would like to be parsed. You can also call the jQuery.validator.unobtrusive.parseElement() function to parse a single HTML element.

    public ActionResult Index()
    {
        return View("~/Views/Home/Index.cshtml");

    }

 

This bug has been fixed in MVC 3 Beta but not 100% fixed. The following code still throws an exception in MVC 3 Beta.


 

 Supports Client Side Validation for Overridden Properties :In previous MVC versions, client side validation will not trigger for overridden model properties. For example, if you the  following Model then client side validation will not trigger in old MVC versions but it will work in MVC 3 Beta.

 

public class Human

{
public virtual int Age { get; set; }

}
public class Men : Human
{
[Range(10,20,ErrorMessage = "Age is between 10 to 20.")]

public override int Age { get; set; }
}

 

 

 Support for DisplayAttribute : In MVC 2 (and MVC 1), DisplayAttribute is not work because in .NET 3.5 there is no DisplayAttribute and MVC 2 is compiled with .NET 3.5. In MVC 3 preview 1, DisplayAttribute will be honored with the exception of template helpers. Now in MVC 3 Beta, EditorFor and DisplayFor helpers supports the ordering which is specified in the DisplayAttribute.Order property. DisplayNameAttribute bug is Fixed: In MVC 3 preview 1, usage of DisplayNameAttribute was broken. This has been fixed in MVC 3 Beta 1. Page Directive bug is Fixed: In MVC 3 preview 1, if you use any directive after the Page directive(<%@Page) then your page will break. This was a bug in MVC 3 preview 1 which shows on any page where there are any directives after the page directive. This has been fixed in MVC 3 Beta 1. Model Property Name bug is Fixed: In MVC 2 if you have a Model which contains a property named Model and you use it in a HTML helper then it will throws an exception. For example:

 

public class MyModel
{
public string Model { get; set; }

}
<%=Html.TextAreaFor(m => m.Model)%>

 

 

 This will throw an exception in MVC 2 while the same sample is work in MVC 3.

Client Side Validation Support for StringLengthAttribute MinimumLength Property: Client side validation is not supported for StringLengthAttribute MinimumLength property in MVC 2  In MVC 3 client side validation will work for MinimumLength property.

References

JavaScript and ASP.NET MVC Framework Features

ASP.NET MVC 3 preview analyze

Deploying ASP.NET MVC 3 web application to server where ASP.NET MVC 3 is not installed

Summary
In this article
Imran Baloch shows new features and bug fixes in ASP.NET MVC 3 Beta. This will help a lot when you start using ASP.NET MVC 3 Beta. He also showed you how quickly ASP.NET MVC team fixes the bugs discussed in forums. If you have any questions, suggestions, issues or if you found any bugs when working with this release, please post them to the ASP.NET MVC forum, where ASP.NET community members are frequently able to provide informal support. You can also download the MVC 3 Beta source. Hopefully you will enjoy this article too.

Comments (6) -

  • What do you think about changes in ASP.NET MVC 3 beta?
  • I'd like to try out Razor engine in my future projects!
    Do you know some hosting with Razor support?
  • Eugene, Razor it is not connected to hosting. Hosting need to support ASP.NET 3.5 and it will be okay for any ASP.NET MVC 3 Framework features.
  • You need win hosting with ASP .NET 4 support, ASP MVC 3 works only with Net 4.0
  • It is not true BatsIhor, Scott Hanselmann explain how we can install ASP MVC 3 on hosting with .NET 3.5 and it is not difficult.

Add comment

Loading