Manual Integration into an Existing Project
- 13 minutes to read
This topic explains how to manually incorporate DevExpress Extensions for ASP.NET MVC into ASP.NET MVC applications. Note that all actions listed below are performed automatically when creating an MVC application, using specially designed DevExpress project templates.
To use DevExpress Extensions for ASP.NET MVC in a project, perform the following steps within your application.
Note
The version numbers mentioned in this document (24.
#Step 1. Reference the Required Assemblies
References to the following assembly files should be added to the ASP.NET MVC application (refer to the Redistributable Assemblies topic to learn more).
- DevExpress.Charts.v24.1.Core
- DevExpress.Dashboard.v24.1.Core
- DevExpress.Dashboard.v24.1.Web
- DevExpress.Dashboard.v24.1.Web.Mvc
- DevExpress.Data.v24.1
- DevExpress.DataAccess.v24.1
- DevExpress.Office.v24.1.Core.dll
- DevExpress.PivotGrid.v24.1.Core
- DevExpress.Printing.v24.1.Core
- DevExpress.RichEdit.v24.1.Core.dll
- DevExpress.SpellChecker.v24.1.Core
- DevExpress.Spreadsheet.v24.1.Core
- DevExpress.Utils.v24.1
- DevExpress.Web.ASPxDiagram.v24.1
- DevExpress.Web.ASPxGantt.v24.1
- DevExpress.Web.ASPxGauges.v24.1
- DevExpress.Web.ASPxHtmlEditor.v24.1
- DevExpress.Web.ASPxPivotGrid.v24.1
- DevExpress.Web.ASPxRichEdit.v24.1
- DevExpress.Web.ASPxScheduler.v24.1
- DevExpress.Web.ASPxSpellChecker.v24.1
- DevExpress.Web.ASPxSpreadsheet.v24.1
- DevExpress.Web.ASPxThemes.v24.1
- DevExpress.Web.ASPxTreeList.v24.1
- DevExpress.Web.Mvc.v24.1 (or DevExpress.Web.Mvc5.v24.1 if using ASP.NET MVC 5)
- DevExpress.Web.v24.1
- DevExpress.Xpo.v24.1
- DevExpress.XtraCharts.v24.1
- DevExpress.XtraCharts.v24.1.Web
- DevExpress.XtraGauges.v24.1.Core
- DevExpress.XtraGauges.v24.1.Presets
- DevExpress.XtraPivotGrid.v24.1
- DevExpress.XtraReports.v24.1
- DevExpress.XtraReports.v24.1.Web
- DevExpress.XtraScheduler.v24.1.Core
Typically, after installation, the required DevExpress assemblies have already been registered in the GAC, so you can open the Reference Manager dialog (for instance, using the PROJECT | Add Reference… menu item), and select these assemblies within the dialog’s .NET tab.
Depending on your development and deployment strategy, you can then set the CopyLocal property of the referenced DevExpress assemblies to True, or add the following lines to the ‘configuration → system.web → compilation → assemblies‘ section of the application’s Web.config file.
Web.config:
...
<assemblies>
...
<add assembly="DevExpress.Data.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.ASPxDiagram.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.ASPxGantt.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.ASPxHtmlEditor.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.ASPxSpellChecker.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.ASPxTreeList.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.ASPxThemes.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.ASPxPivotGrid.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Utils.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Office.v24.1.Core, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.RichEdit.v24.1.Core, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.ASPxRichEdit.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.SpellChecker.v24.1.Core, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Charts.v24.1.Core, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.XtraCharts.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.XtraGauges.v24.1.Core, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.XtraGauges.v24.1.Presets, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.ASPxGauges.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.XtraCharts.v24.1.Web, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Printing.v24.1.Core, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.XtraReports.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.XtraReports.v24.1.Web, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.XtraPivotGrid.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.PivotGrid.v24.1.Core, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.XtraScheduler.v24.1.Core, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.ASPxScheduler.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Spreadsheet.v24.1.Core, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.ASPxSpreadsheet.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Xpo.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.DataAccess.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Dashboard.v24.1.Core, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Dashboard.v24.1.Web, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Dashboard.v24.1.Web.Mvc, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
<add assembly="DevExpress.Web.Mvc.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
...
</assemblies>
Note
When using the ASP.
...
<assemblies>
...
<add assembly="DevExpress.Web.Mvc5.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
...
</assemblies>
#Step 2. Register DevExpress HTTP Handlers within the Application’s Web.config File
Registering the service ASPxHttpHandlerModule in two sections of the application’s Web.config file (‘configuration → system.web → httpModules‘ and ‘configuration → system.webServer → modules‘) is required.
Web.config:
<system.web>
...
<httpModules>
...
<add type="DevExpress.Web.ASPxHttpHandlerModule, DevExpress.Web.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=B88D1754D700E49A" name="ASPxHttpHandlerModule"/>
</httpModules>
</system.web>
<system.webServer>
...
<modules runAllManagedModulesForAllRequests="true">
...
<add type="DevExpress.Web.ASPxHttpHandlerModule, DevExpress.Web.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=B88D1754D700E49A" name="ASPxHttpHandlerModule"/>
</modules>
</system.webServer>
If the UploadControl’s progress panel functionality is utilized in an application, registering the ASPxUploadProgressHttpHandler (within the Web.config’s ‘configuration → system.web → httpHandlers‘ and ‘configuration → system.webServer → handlers‘ sections) is also required.
Web.config:
<system.web>
...
<httpHandlers>
<add type="DevExpress.Web.ASPxUploadProgressHttpHandler, DevExpress.Web.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=B88D1754D700E49A" verb="GET,POST" path="ASPxUploadProgressHandlerPage.ashx" validate="false" />
</httpHandlers>
...
</system.web>
<system.webServer>
...
<handlers>
<add type="DevExpress.Web.ASPxUploadProgressHttpHandler, DevExpress.Web.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=B88D1754D700E49A" verb="GET,POST" path="ASPxUploadProgressHandlerPage.ashx" name="ASPxUploadProgressHandler" preCondition="integratedMode" />
</handlers>
</system.webServer>
#Step 3. Register the Required Namespaces within the ~/Views/Web.config File
Razor uses a specific configuration section to globally define namespace imports for its views. This is the <system.web.webPages.razor> section, which is located within the Views folder’s Web.config file. This section should contain the required DevExpress namespaces to make the DevExpress Extensions available for use within web project pages. Note that if you create a web project using a DevExpress project template, all required information is automatically added to the configuration files. Otherwise, you need to modify the configuration section manually.
Web.config:
<system.web.webPages.razor>
...
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
<add namespace="System.Web.UI.WebControls" />
<add namespace="DevExpress.Utils" />
<add namespace="DevExpress.Web.ASPxDiagram" />
<add namespace="DevExpress.Web.ASPxGantt" />
<add namespace="DevExpress.Web.ASPxTreeList" />
<add namespace="DevExpress.Web.ASPxHtmlEditor" />
<add namespace="DevExpress.Web.ASPxSpellChecker" />
<add namespace="DevExpress.Web.ASPxThemes" />
<add namespace="DevExpress.XtraCharts" />
<add namespace="DevExpress.XtraCharts.Web" />
<add namespace="DevExpress.XtraReports" />
<add namespace="DevExpress.XtraReports.UI" />
<add namespace="DevExpress.XtraReports.Web" />
<add namespace="DevExpress.XtraReports.Web.DocumentViewer" />
<add namespace="DevExpress.XtraPivotGrid" />
<add namespace="DevExpress.Data.PivotGrid" />
<add namespace="DevExpress.Web.ASPxPivotGrid" />
<add namespace="DevExpress.Web.Mvc" />
<add namespace="DevExpress.Web.Mvc.UI" />
<add namespace="DevExpress.XtraScheduler" />
<add namespace="DevExpress.XtraScheduler.Native" />
<add namespace="DevExpress.Web.ASPxScheduler" />
<add namespace="DevExpress.DashboardWeb.Mvc" />
<add namespace="DevExpress.Web.ASPxSpreadsheet" />
<add namespace="DevExpress.Web.ASPxRichEdit" />
</namespaces>
</pages>
</system.web.webPages.razor>
Note
If using the Razor view engine, register these namespaces within the ‘configuration → system.
As an alternative, you can manually insert @using directives into view pages to import the required namespaces.
View:
Access and customization of DevExpress MVC Extensions is now permitted within the application’s view pages, including the use of IntelliSense. However, DevExpress Extensions are not yet fully functional at this stage, because they also require script and style files to be attached in order to work properly. By design, the required script and style sheet files are not referenced automatically for MVC extensions, so you should attach them manually, as described in the steps below.
#Step 4. Register the DevExpress Configuration Section in the Web.config File
Different aspects of DevExpress functionality can be centrally controlled through configuration options provided by a specially designed DevExpress configuration section. Register this section in the application’s Web.config file using the following code.
<configuration>
<configSections>
<sectionGroup name="devExpress">
<section name="themes" type="DevExpress.Web.ThemesConfigurationSection, DevExpress.Web.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" requirePermission="false" />
<section name="compression" type="DevExpress.Web.CompressionConfigurationSection, DevExpress.Web.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" requirePermission="false" />
<section name="settings" type="DevExpress.Web.SettingsConfigurationSection, DevExpress.Web.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" requirePermission="false" />
<section name="errors" type="DevExpress.Web.ErrorsConfigurationSection, DevExpress.Web.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" requirePermission="false" />
<section name="resources" type="DevExpress.Web.ResourcesConfigurationSection, DevExpress.Web.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" requirePermission="false" />
</sectionGroup>
</configSections>
...
<devExpress>
<themes enableThemesAssembly="true" styleSheetTheme="" theme="Metropolis" customThemeAssemblies="" baseColor="Green" font="30px 'Callibri'" />
<compression enableHtmlCompression="false" enableCallbackCompression="true" enableResourceCompression="true" enableResourceMerging="true" />
<settings doctypeMode="Html5" rightToLeft="false" ieCompatibilityVersion="edge" />
<errors callbackErrorRedirectUrl="" />
<resources>
<add type="ThirdParty" />
<add type="DevExtreme" />
</resources>
</devExpress>
</configuration>
Note
In order to properly register the DevExpress ASP.
#Step 5. Attach the Required JavaScript Files
#Attaching External Libraries
All the DevExpress ASP.NET MVC extensions require attaching the jQuery library and some of them also require attaching additional libraries.
For an ASP.NET MVC extension to work properly, you either need to manually add the required external libraries, or enable the control to load them automatically by adding the following references to the “resources” section in the Web.config file.
<devExpress>
<!-- ... -->
<resources>
<add type="ThirdParty" />
<add type="DevExtreme" />
</resources>
</devExpress>
These settings specify the following resources.
- “ThirdParty“ - adds references to external libraries required by a specific control. For a complete list of these references, see External Client Libraries.
- “DevExtreme“ - adds a reference to the DevExtreme package. For a complete list of these references, see the 3rd-Party Frameworks Integration API document.
The above resources are automatically added to the Web.config file on adding a DevExpress web control to a new application created using the DevExpress template gallery. In this case, all necessary client-side libraries are automatically passed to the client.
When manually adding such controls to a web page, you need to explicitly specify which of the client libraries must be deployed on the client by the control. By default, on adding such a DevExpress control, it loads only the DevExtreme library to a web page without loading third-party libraries.
To avoid automatic loading of any libraries by a control (e.g., when such libraries are already referenced on the web page), declare an empty “resources” section and manually attach DevExtreme resources and the required third-party libraries to the web page.
<resources>
</resources>
Deleting the DevExpress “resources” section from the Web.config file will enable the default behavior (with automatic loading of only DevExtreme, without adding third-party libraries).
On adding such DevExpress controls to a project, the “resources” section should automatically become registered in the application’s Web.config file.
<configuration>
<configSections>
<sectionGroup name="devExpress">
<!-- ... -->
<section name="resources" type="DevExpress.Web.ResourcesConfigurationSection, DevExpress.Web.v24.1, Version=24.1.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" requirePermission="false" />
</sectionGroup>
</configSections>
<!-- ... -->
</configuration>
When updating your project version using the Project Converter, you are required to manually register this section in the Web.config file.
#Attaching the DevExpress specific scripts
To attach the required DevExpress JavaScript files, use the ExtensionsFactory.GetScripts (or ExtensionsFactory.RenderScripts, if your project uses the Razor view engine) method within the View page’s head
tag. Typically, scripts can be attached to all Views in a central location within the layout View.
If the resources section of an application’s Web.config file contains a reference to the ThirdParty
and/or DevExtreme
libraries, the GetScripts
method will attach the corresponding libraries and additional resources to the View.
The code sample below demonstrates how to attach the jQuery library and the DevExpress specific scripts to your project.
<head>
...
<!--
Attach the jQuery script if the "resources" section of an application's Web.config file contains a reference to the "ThirdParty" libraries.
-->
<script src="@Url.Content("~/Scripts/jquery-3.5.1.min.js")" type="text/javascript"></script>
<!-- The DevExpress ASP.NET MVC Extensions' scripts -->
@Html.DevExpress().GetScripts(
new Script { ExtensionSuite = ExtensionSuite.NavigationAndLayout },
new Script { ExtensionSuite = ExtensionSuite.HtmlEditor },
new Script { ExtensionSuite = ExtensionSuite.GridView },
...
)
...
</head>
Important
If you attach the j
If you bundled your Java
#Step 6. Attach the Required Style Sheets
To attach the required style sheets, use the ExtensionsFactory.GetStyleSheets extension method within the View page’s HEAD (not BODY) tag. Typically, style sheets can be attached to all Views in a central location within the layout View (before the @RenderBody() expression).
The code sample below demonstrates how to attach style sheets for the specified extension set(s).
View (or layout View) Code (Razor):
<head>
...
@Html.DevExpress().GetStyleSheets(
new StyleSheet { ExtensionSuite = ExtensionSuite.NavigationAndLayout },
new StyleSheet { ExtensionSuite = ExtensionSuite.Diagram },
new StyleSheet { ExtensionSuite = ExtensionSuite.Gantt },
new StyleSheet { ExtensionSuite = ExtensionSuite.Editors },
new StyleSheet { ExtensionSuite = ExtensionSuite.HtmlEditor },
new StyleSheet { ExtensionSuite = ExtensionSuite.GridView },
new StyleSheet { ExtensionSuite = ExtensionSuite.PivotGrid },
new StyleSheet { ExtensionSuite = ExtensionSuite.Chart },
new StyleSheet { ExtensionSuite = ExtensionSuite.Report },
new StyleSheet { ExtensionSuite = ExtensionSuite.Scheduler },
new StyleSheet { ExtensionSuite = ExtensionSuite.TreeList },
new StyleSheet { ExtensionSuite = ExtensionSuite.Spreadsheet },
new StyleSheet { ExtensionSuite = ExtensionSuite.RichEdit },
new StyleSheet { ExtensionSuite = ExtensionSuite.SpellChecker }
)
...
</head>
After attaching the style sheets, define the theme that will be applied to the DevExpress ASP.NET MVC extensions using one of the following approaches.
- Assign the theme name to the static DevExpressHelper.Theme property. This programmatically applies the theme to all DevExpress extensions within an application.
- Assign the theme name to the DevExpress Theme Name option in the Web.config file. This declaratively applies the theme to all DevExpress extensions within an application.
The following code demonstrates how the “Aqua” theme can be globally applied to all DevExpress ASP.NET MVC extensions within an application using the static DevExpressHelper.Theme property.
Global.asax.cs Code:
using DevExpress.Web.Mvc;
...
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) {
DevExpressHelper.Theme = "Aqua";
}
...
Different approaches to attaching and applying DevExpress themes are described in the Applying Themes section of the documentation.
#Step 7. Add Ignore Route Statements
You should include the ignore route statements with the following patterns to prevent requests from being passed to a controller:
{resource}.axd/{*pathInfo}
- for the Web resource files (e.g., scripts, styles);{resource}.ashx/{*pathInfo}
- for the ASHX handler, which processes the file upload functionality of DevExpress ASP.NET MVC extensions (e.g., UploadControl, FileManager, HtmlEditor).
In the registered route collection, add the required ignore route statements above the other route definitions.
// ...
public static void RegisterRoutes(RouteCollection routes)
{
// Ignore route statements.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{resource}.ashx/{*pathInfo}");
// Route definitions.
// ...
}
// ...
Tip
If you use the ASP.
#Step 8. Override the Default Model Binder
When DevExpress editors are bound to data model fields by using Bind (dataObject, propertyName) methods or using strongly typed helpers, the DevExpressEditorsBinder model binder must be used instead of the default model binder to correctly transfer values from DevExpress editors back to corresponding data model fields.
You can specify DevExpressEditorsBinder as a model binder in the following manners.
Decorating the Parameter of Action Method
You can declare DevExpressEditorsBinder as a parameter attribute on an action method: ([ModelBinder(typeof(DevExpressEditorsBinder))]).
Controller:
[HttpPost] public ActionResult ModelBinding([ModelBinder(typeof(DevExpressEditorsBinder))] MyModelData myModel) { ... }
Overriding the Default Model Binder
You can assign DevExpressEditorsBinder to the ModelBinders.Binders.DefaultBinder property to replace the global default model binder.
Global.asax:
protected void Application_Start(){ ... ModelBinders.Binders.DefaultBinder = new DevExpress.Web.Mvc.DevExpressEditorsBinder(); }
Note
DevExpress
#Step 9. Remove CSS Settings Applied using Element Type Selectors
If you create an MVC project using the standard ‘ASP.NET MVC Web Application’ template provided by Visual Studio, the project’s Content folder contains the automatically generated Site.css file. Specific type selectors that are defined in this file and relate directly to HTML element types (such as links, input elements, tables and table cells) may affect the appearance of DevExpress MVC extensions incorrectly. To fix this problem, it is required that you clear the style settings defined in the element type selectors. This requirement also applies to your custom CSS files and rules, if any.
#Step 10. Check the Document Type of View Pages
It is recommended that you use the following document type for Views to ensure that DevExpress MVC extensions will work properly.
<!DOCTYPE html>
Check and correct (if necessary) the document type for all Views containing DevExpress MVC extensions and/or the document type of layout pages used by Views.
#Step 11. Add Extension Code
You can now use DevExpress Extensions within your ASP.NET MVC application. The NavBar extension will be used as an example. Add the following code to the Index View page of the project. (In this example, the project was initially created using the ASP.NET MVC 5 Web Application template.)
View code (Razor):
@Html.DevExpress().NavBar(
settings => {
settings.Name = "myNavBar";
settings.Groups.Add("Group1").Items.Add("Item1-1");
settings.Groups.Add("Group2").Items.Add("Item2-1");
settings.Groups.FindByText("Group2").Expanded = false;
}).GetHtml()
After building and running the application, the Index View page will appear as follows.
Refer to the Get Started topic to learn about the fundamentals of DevExpress ASP.NET MVC Extensions.