Migration from WebForms to Xafari MVC

This topic describes how to migrate XAF Main Demo Web to the MVC platform. Follow the instructions below:

Open the Main Demo solution in Visual Studio and remove all unnecessary projects leaving only MainDemo.Module, MainDemo.Module.Web and MainDemo.Web as shown in the picture below:

mvc_20

Add a new MainDemo.Mvc project to the application. Use the Xafari v.XX.X.XXXX ASP.NET MVC Application template as shown in the picture below:

mvc_21

The structure of a new project is shown in the screenshot below:

mvc_22

Build project, then the Views and App_Code directories will be added.

mvc_23

Then, add a new XAF Module Project and name it MainDemo.Module.Mvc. Copy the content of the folders Controllers and DatabaseUpdate from MainDemo.Module.Web to MainDemo.Module.Mvc. Add all required references to the MainDemo.Module.Mvc project:

mvc_24

In the MainDemo.Module.Mvc project replace the contents of the DatabaseUpdate/Update.cs file with the following code:

  • c#
  • VB

using System;
using System.Web.UI.WebControls;
using DevExpress.Data.Filtering;
using DevExpress.Data.PivotGrid;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.PivotChart;
using DevExpress.ExpressApp.Updating;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Web.Mvc;
using DevExpress.XtraPivotGrid;
using DevExpress.XtraPivotGrid.Data;
using MainDemo.Module.DatabaseUpdate;
using Xafari.PivotChart.Mvc.MVCx;
using Chart = DevExpress.XtraCharts.Native.Chart;
namespace MainDemo.Module.Web.DatabaseUpdate
{
  public class Updater : ModuleUpdater
  {
    public Updater(IObjectSpace objectSpace, Version currentDBVersion)
      : base(objectSpace, currentDBVersion)
    {
    }
    public override void UpdateDatabaseAfterUpdateSchema()
    {
      base.UpdateDatabaseAfterUpdateSchema();
      new TaskAnalysis1LayoutUpdater().Update(ObjectSpace.FindObject<Analysis>(CriteriaOperator.Parse("Name='Completed tasks'")));
      new TaskAnalysis2LayoutUpdater().Update(ObjectSpace.FindObject<Analysis>(CriteriaOperator.Parse("Name='Estimated and actual work comparison'")));
      ObjectSpace.CommitChanges();
    }
  }
  public class TaskAnalysis1LayoutUpdater : TaskAnalysis1LayoutUpdaterBase
  {
    protected override IAnalysisControl CreateAnalysisControl()
    {
      return new AnalysisControlUpdater();
    }
    protected override IPivotGridSettingsStore CreatePivotGridSettingsStore(IAnalysisControl control)
    {
      return new MVCxPivotGridSettingsStore(((AnalysisControlUpdater)control).PivotGrid, ((AnalysisControlUpdater)control).PivotGridSettings);
    }
  }
  public class TaskAnalysis2LayoutUpdater : TaskAnalysis2LayoutUpdaterBase
  {
    protected override IAnalysisControl CreateAnalysisControl()
    {
      return new AnalysisControlUpdater();
    }
    protected override IPivotGridSettingsStore CreatePivotGridSettingsStore(IAnalysisControl control)
    {
      return new MVCxPivotGridSettingsStore(((AnalysisControlUpdater)control).PivotGrid, ((AnalysisControlUpdater)control).PivotGridSettings);
    }
  }
  public class AnalysisControlUpdater : IAnalysisControl, ISupportPivotGridFieldBuilder
  {
    private IAnalysisDataSource _dataSource;
    private PivotGridFieldBuilder _pivotGridFieldBuilder;
    private MVCxPivotGrid _pivotGrid = new MVCxPivotGrid();
    private PivotGridSettings _pivotGridSettings = new PivotGridSettings();
    public AnalysisControlUpdater()
    {
      _pivotGridFieldBuilder = new PivotGridFieldBuilder(this);
      _pivotGrid.OptionsChartDataSource.DataProvideMode = PivotChartDataProvideMode.UseCustomSettings;
      _pivotGrid.EncodeHtml = true;
      _pivotGrid.Width = Unit.Percentage(100);
    }
    public PivotGridSettings PivotGridSettings
    {
      get
      {
        return this._pivotGridSettings;
      }
    }
    public MVCxPivotGrid PivotGrid
    {
      get
      {
        return _pivotGrid;
      }
    }
    public void AddPivotGridField(string fieldCaption, string fieldName, PivotSummaryType summaryType)
    {
      PivotGridField field = new PivotGridField { FieldName = fieldName, Caption = fieldCaption, SummaryType = summaryType };
      Fields.Add(field);
    }
    public void BeginUpdate()
    {
    }
    public Chart Chart
    {
      get
      {
        throw new NotImplementedException();
      }
    }
    public event EventHandler<EventArgs> ChartSettingsChanged;
    public IAnalysisDataSource DataSource
    {
      get
      {
        return _dataSource;
      }
      set
      {
        _dataSource = value;
        if (_dataSource != null)
        {
          FieldBuilder.RebuildFields();
        }
      }
    }
    public void EndUpdate()
    {
    }
    public PivotGridFieldCollectionBase Fields
    {
      get
      {
        return _pivotGrid.Fields;
      }
    }
    public PivotGridOptionsChartDataSourceBase OptionsChartDataSource
    {
      get
      {
        throw new NotImplementedException();
      }
    }
    public event EventHandler<EventArgs> PivotGridSettingsChanged;
    public bool ReadOnly
    {
      get
      {
        throw new NotImplementedException();
      }
      set
      {
        throw new NotImplementedException();
      }
    }
    public PivotGridFieldBuilder FieldBuilder
    {
      get
      {
        return _pivotGridFieldBuilder;
      }
      set
      {
        _pivotGridFieldBuilder = value;
      }
    }
  }
}

Imports System
Imports System.Web.UI.WebControls
Imports DevExpress.Data.Filtering
Imports DevExpress.Data.PivotGrid
Imports DevExpress.ExpressApp
Imports DevExpress.ExpressApp.PivotChart
Imports DevExpress.ExpressApp.Updating
Imports DevExpress.Persistent.Base
Imports DevExpress.Persistent.BaseImpl
Imports DevExpress.Web.Mvc
Imports DevExpress.XtraPivotGrid
Imports DevExpress.XtraPivotGrid.Data
Imports MainDemo.[Module].DatabaseUpdate
Imports Xafari.PivotChart.Mvc.MVCx
Imports Chart = DevExpress.XtraCharts.Native.Chart
Namespace MainDemo.Module.Web.DatabaseUpdate
  Public Class Updater
    Inherits ModuleUpdater
    Public Sub New(ByVal objectSpace As IObjectSpace, ByVal currentDBVersion As Version)
      MyBase.New(objectSpace, currentDBVersion)
    End Sub
    Public Overrides Sub UpdateDatabaseAfterUpdateSchema()
      MyBase.UpdateDatabaseAfterUpdateSchema()
      New TaskAnalysis1LayoutUpdater().Update(ObjectSpace.FindObject(Of Analysis)(CriteriaOperator.Parse("Name='Completed tasks'")))
      New TaskAnalysis2LayoutUpdater().Update(ObjectSpace.FindObject(Of Analysis)(CriteriaOperator.Parse("Name='Estimated and actual work comparison'")))
      ObjectSpace.CommitChanges()
    End Sub
  End Class
  Public Class TaskAnalysis1LayoutUpdater
    Inherits TaskAnalysis1LayoutUpdaterBase
    Protected Overrides Function CreateAnalysisControl() As IAnalysisControl
      Return New AnalysisControlUpdater()
    End Function
    Protected Overrides Function CreatePivotGridSettingsStore(ByVal control As IAnalysisControl) As IPivotGridSettingsStore
      Return New MVCxPivotGridSettingsStore(CType(control, AnalysisControlUpdater).PivotGrid, CType(control, AnalysisControlUpdater).PivotGridSettings)
    End Function
  End Class
  Public Class TaskAnalysis2LayoutUpdater
    Inherits TaskAnalysis2LayoutUpdaterBase
    Protected Overrides Function CreateAnalysisControl() As IAnalysisControl
      Return New AnalysisControlUpdater()
    End Function
    Protected Overrides Function CreatePivotGridSettingsStore(ByVal control As IAnalysisControl) As IPivotGridSettingsStore
      Return New MVCxPivotGridSettingsStore(CType(control, AnalysisControlUpdater).PivotGrid, CType(control, AnalysisControlUpdater).PivotGridSettings)
    End Function
  End Class
  Public Class AnalysisControlUpdater
    Implements ISupportPivotGridFieldBuilder, IAnalysisControl
    Private __dataSource As IAnalysisDataSource
    Private __pivotGridFieldBuilder As PivotGridFieldBuilder
    Private __pivotGrid As MVCxPivotGrid = New MVCxPivotGrid()
    Private __pivotGridSettings As PivotGridSettings = New PivotGridSettings()
    Public Sub New()
      __pivotGridFieldBuilder = New PivotGridFieldBuilder(Me)
      __pivotGrid.OptionsChartDataSource.DataProvideMode = PivotChartDataProvideMode.UseCustomSettings
      __pivotGrid.EncodeHtml = True
      __pivotGrid.Width = Unit.Percentage(100)
    End Sub
    Public ReadOnly Property PivotGridSettings As PivotGridSettings
      Get
        Return Me.__pivotGridSettings
      End Get
    End Property
    Public ReadOnly Property PivotGrid As MVCxPivotGrid
      Get
        Return __pivotGrid
      End Get
    End Property
    Public Sub AddPivotGridField(ByVal fieldCaption As String, ByVal fieldName As String, ByVal summaryType As PivotSummaryType)
      Dim field As PivotGridField = New PivotGridField() With {.FieldName = fieldName, .Caption = fieldCaption, .SummaryType = summaryType}
      Fields.Add(field)
    End Sub
    Public Sub BeginUpdate()
    End Sub
    Public ReadOnly Property Chart As Chart
      Get
        Throw New NotImplementedException()
      End Get
    End Property
    Public Event ChartSettingsChanged As EventHandler(Of EventArgs)
    Public Property DataSource As IAnalysisDataSource
      Get
        Return __dataSource
      End Get
      Set
        __dataSource = value
        If __dataSource IsNot Nothing Then
          FieldBuilder.RebuildFields()
        End If
      End Set
    End Property
    Public Sub EndUpdate()
    End Sub
    Public ReadOnly Property Fields As PivotGridFieldCollectionBase
      Get
        Return __pivotGrid.Fields
      End Get
    End Property
    Public ReadOnly Property OptionsChartDataSource As PivotGridOptionsChartDataSourceBase
      Get
        Throw New NotImplementedException()
      End Get
    End Property
    Public Event PivotGridSettingsChanged As EventHandler(Of EventArgs)
    Public Property [ReadOnly] As Boolean
      Get
        Throw New NotImplementedException()
      End Get
      Set
        Throw New NotImplementedException()
      End Set
    End Property
    Public Property FieldBuilder As PivotGridFieldBuilder
      Get
        Return __pivotGridFieldBuilder
      End Get
      Set
        __pivotGridFieldBuilder = value
      End Set
    End Property
  End Class
End Namespace

Then, it is required to modify the code of the Controllers.

ChooseTemplateController. Replace the original ChooseTemplateAction_Execute method with the following code:

  • c#
  • VB

public partial class ChooseTemplateController : ViewController
{
  //...
  private void ChooseTemplateAction_Execute(object sender, DevExpress.ExpressApp.Actions.SingleChoiceActionExecuteEventArgs e)
  {
    WebApplication.PreferredApplicationWindowTemplateType = (TemplateType)e.SelectedChoiceActionItem.Data;
    MvcApplication.Instance.ShowViewStrategy.RefreshWindowContent(true);
  }
}

Public Partial Class ChooseTemplateController
  Inherits ViewController
  '...
  Private Sub ChooseTemplateAction_Execute(ByVal sender As Object, ByVal e As DevExpress.ExpressApp.Actions.SingleChoiceActionExecuteEventArgs)
    WebApplication.PreferredApplicationWindowTemplateType = CType(e.SelectedChoiceActionItem.Data, TemplateType)
    MvcApplication.Instance.ShowViewStrategy.RefreshWindowContent(True)
  End Sub
End Class

Rename WebNullTextEditorController into MvcNullTextEditorController and replace its initial code with the snippet below:

  • c#
  • VB

using System;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Utils;
using DevExpress.Web;
using Xafari.Mvc.Editors;
using Xafari.Mvc.MVCx.Editors;
namespace MainDemo.Module.Mvc.Controllers
{
  public partial class MvcNullTextEditorController : ViewController
  {
    public MvcNullTextEditorController()
    {
      InitializeComponent();
      RegisterActions(components);
    }
    private void InitNullText(MvcPropertyEditor propertyEditor)
    {
      if (propertyEditor.ViewEditMode == DevExpress.ExpressApp.Editors.ViewEditMode.Edit)
      {
        ((MVCxDateTimePropertyEditor)propertyEditor.Editor).NullValueText = CaptionHelper.NullValueText;
      }
    }
    private void WebNullTextEditorController_Activated(object sender, EventArgs e)
    {
      MvcPropertyEditor propertyEditor = ((DetailView)View).FindItem("Anniversary") as MvcPropertyEditor;
      if (propertyEditor != null)
      {
        if (propertyEditor.Control != null)
        {
          InitNullText(propertyEditor);
        }
        else
        {
          propertyEditor.ControlCreated += new EventHandler<EventArgs>(propertyEditor_ControlCreated);
        }
      }
    }
    private void propertyEditor_ControlCreated(object sender, EventArgs e)
    {
      InitNullText((MvcPropertyEditor)sender);
    }
  }
}

Imports System
Imports DevExpress.ExpressApp
Imports DevExpress.ExpressApp.Utils
Imports DevExpress.Web
Imports Xafari.Mvc.Editors
Imports Xafari.Mvc.MVCx.Editors
Namespace MainDemo.Module.Mvc.Controllers
  Public Partial Class MvcNullTextEditorController
    Inherits ViewController
    Public Sub New()
      InitializeComponent()
      RegisterActions(components)
    End Sub
    Private Sub InitNullText(ByVal propertyEditor As MvcPropertyEditor)
      If propertyEditor.ViewEditMode = DevExpress.ExpressApp.Editors.ViewEditMode.Edit Then
        CType(propertyEditor.Editor, MVCxDateTimePropertyEditor).NullValueText = CaptionHelper.NullValueText
      End If
    End Sub
    Private Sub WebNullTextEditorController_Activated(ByVal sender As Object, ByVal e As EventArgs)
      Dim propertyEditor As MvcPropertyEditor = TryCast(CType(View, DetailView).FindItem("Anniversary"), MvcPropertyEditor)
      If propertyEditor IsNot Nothing Then
        If propertyEditor.Control IsNot Nothing Then
          InitNullText(propertyEditor)
        Else
          propertyEditor.ControlCreated += New EventHandler(Of EventArgs)(propertyEditor_ControlCreated)
        End If
      End If
    End Sub
    Private Sub propertyEditor_ControlCreated(ByVal sender As Object, ByVal e As EventArgs)
      InitNullText(CType(sender, MvcPropertyEditor))
    End Sub
  End Class
End Namespace

Rename WebPermissionsController into MvcPermissionsController.

Add a new controller named MyMvcModificationsController and replace its default code with this one:

  • c#
  • VB

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using MainDemo.Module.BusinessObjects;
using Xafari.Mvc;
using Xafari.Mvc.Controllers;
namespace MainDemo.Module.Mvc.Controllers
{
  public partial class MyMvcModificationsController : MvcModificationsController
  {
    public MyMvcModificationsController()
    {
      InitializeComponent();
      RegisterActions(components);
    }
    protected override void SaveAndClose(SimpleActionExecuteEventArgs args)
    {
      View view = View;
      base.SaveAndClose(args);
      if (!view.IsDisposed && (view is DetailView) && (((DetailView)view).ObjectTypeInfo.Type == typeof(Contact)))
      {
        view.Close();
      }
    }
  }
}

Imports DevExpress.ExpressApp
Imports DevExpress.ExpressApp.Actions
Imports MainDemo.[Module].BusinessObjects
Imports Xafari.Mvc
Imports Xafari.Mvc.Controllers
Namespace MainDemo.Module.Mvc.Controllers
  Public Partial Class MyMvcModificationsController
    Inherits MvcModificationsController
    Public Sub New()
      InitializeComponent()
      RegisterActions(components)
    End Sub
    Protected Overrides Sub SaveAndClose(ByVal args As SimpleActionExecuteEventArgs)
      Dim view As View = View
      MyBase.SaveAndClose(args)
      If Not view.IsDisposed AndAlso (TypeOf view Is DetailView) AndAlso (CType(view, DetailView).ObjectTypeInfo.Type = GetType(Contact)) Then
        view.Close()
      End If
    End Sub
  End Class
End Namespace

No changes should be done to WebTooltipController.

The next step is to add all required modules to the MainDemoMvcModule project and the MainDemoMvcApplication project as described below.

The list below shows the modules required for MainDemoMvcModule:

  • MainDemo.Module.MainDemoModule
  • DevExpress.ExpressApp.Validation.ValidationModule
  • DevExpress.ExpressApp.Scheduler.SchedulerModuleBase

The list below shows the modules required for MainDemoMvcApplication:

  • Xafari.XafariModule
  • Xafari.Mvc.XafariMvcModule
  • Xafari.Mvc.MVCx.XafariMVCxModule
  • DevExpress.ExpressApp.Security.SecurityModule
  • DevExpress.ExpressApp.Objects.BusinessClassLibraryCustomizationModule
  • DevExpress.ExpressApp.AuditTrail.AuditTrailModule
  • Xafari.FileAttachment.Mvc.MVCx.XafariFileAttachmentMvcMVCxModule
  • DevExpress.ExpressApp.ReportsV2.ReportsModuleV2
  • Xafari.ReportsV2.Mvc.MVCx.ReportsMvcModuleV2
  • DevExpress.ExpressApp.Validation.ValidationModule
  • Xafari.Validation.Mvc.XafariValidationMvcModule
  • DevExpress.ExpressApp.ViewVariantsModule.ViewVariantsModule
  • DevExpress.ExpressApp.ConditionalAppearance.ConditionalAppearanceModule
  • MainDemo.Module.MainDemoModule
  • MainDemo.Module.Mvc.MainDemoMvcModule
  • DevExpress.ExpressApp.Scheduler.SchedulerModuleBase
  • Xafari.Scheduler.Mvc.MVCx.XafariSchedulerMvcModule
  • DevExpress.ExpressApp.PivotChart.PivotChartModuleBase
  • Xafari.PivotChart.Mvc.MVCx.PivotChartMvcModule
  • DevExpress.ExpressApp.ScriptRecorder.ScriptRecorderModuleBase
  • DevExpress.ExpressApp.Notifications.NotificationsModule
  • Xafari.Notifications.Mvc.MVCx.XafariNotificationsMvcModule

Add the following references to the MainDemo.Mvc project:

  • DevExpress.Charts.vXX.X.Core
  • DevExpress.CodeParser.vXX.X
  • DevExpress.Data.vXX.X
  • DevExpress.DataAccess.vXX.X
  • DevExpress.DataAccess.vXX.X.UI
  • DevExpress.ExpressApp.AuditTrail.vXX.X
  • DevExpress.ExpressApp.ConditionalAppearance.vXX.X
  • DevExpress.ExpressApp.Images.vXX.X
  • DevExpress.ExpressApp.Notifications.vXX.X
  • DevExpress.ExpressApp.Objects.vXX.X
  • DevExpress.ExpressApp.PivotChart.vXX.X
  • DevExpress.ExpressApp.PivotGrid.vXX.X
  • DevExpress.ExpressApp.ReportsV2.vXX.X
  • DevExpress.ExpressApp.Scheduler.vXX.X
  • DevExpress.ExpressApp.ScriptRecorder.vXX.X
  • DevExpress.ExpressApp.Security.vXX.X
  • DevExpress.ExpressApp.TreeListEditors.vXX.X
  • DevExpress.ExpressApp.vXX.X
  • DevExpress.ExpressApp.Validation.vXX.X
  • DevExpress.ExpressApp.ViewVariantsModule.vXX.X
  • DevExpress.ExpressApp.Web.vXX.X
  • DevExpress.ExpressApp.Xpo.vXX.X
  • DevExpress.Office.vXX.X.Core
  • DevExpress.Persistent.Base.vXX.X
  • DevExpress.Persistent.BaseImpl.vXX.X
  • DevExpress.PivotGrid.vXX.X.Core
  • DevExpress.Printing.vXX.X.Core
  • DevExpress.RichEdit.vXX.X.Core
  • DevExpress.SpellChecker.vXX.X.Core
  • DevExpress.Spreadsheet.vXX.X.Core
  • DevExpress.Utils.vXX.X
  • DevExpress.Utils.vXX.X.UI
  • DevExpress.Web.ASPxGauges.vXX.X
  • DevExpress.Web.ASPxHtmlEditor.vXX.X
  • DevExpress.Web.ASPxPivotGrid.vXX.X
  • DevExpress.Web.ASPxRichEdit.vXX.X
  • DevExpress.Web.ASPxScheduler.vXX.X
  • DevExpress.Web.ASPxSpellChecker.vXX.X
  • DevExpress.Web.ASPxSpreadsheet.vXX.X
  • DevExpress.Web.ASPxThemes.vXX.X
  • DevExpress.Web.ASPxTreeList.vXX.X
  • DevExpress.Web.Mvc5.vXX.X
  • DevExpress.Web.vXX.X
  • DevExpress.Xpo.vXX.X
  • System.Web.Mvc
  • System.Web.Razor
  • System.Web.WebPages
  • System.Web.WebPages.Deployment
  • System.Web.WebPages.Razor
  • System.Windows.Forms
  • System.Xml.Linq
  • System.Web
  • System.Web.Extensions
  • System.Web.Abstractions
  • System.Web.Routing
  • System.Xml
  • System.Configuration
  • System.Web.Services
  • System.EnterpriseServices
  • Xafari.Licensing
  • Xafari.Web.Utils
  • Xafari.FileAttachment.Mvc.MVCx
  • Xafari.Images
  • Xafari.Mvc.MVCx
  • Xafari.Mvc
  • Xafari.Notifications.Mvc.MVCx
  • Xafari.PivotChart.Mvc.MVCx
  • Xafari.PivotGrid.Mvc.MVCx
  • Xafari.ReportsV2.Mvc.MVCx
  • Xafari.Scheduler.Mvc.MVCx
  • Xafari.TreeListEditors.Mvc.MVCx
  • Xafari.Utils
  • Xafari.Validation.Mvc
  • Xafari
  • MainDemo.Module.Mvc
  • MainDemo.Module

Specify the connection string in the MainDemo.Mvc  project. To do it, open the web.config file and choose or add the required DB connection string depending on the DB server in use.

Modify the Model.xafml file by declaring the menu items:

  • xml

<?xml version="1.0" encoding="utf-8"?>
 <Application>
     <NavigationItems>
     <Items>
      <Item Id="Default">
         <Items>
          <Item Id="Contact_ListView" Index="0" Caption="Contact" />
          <Item Id="DemoTask_ListView" Index="1" />
          <Item Id="Department_ListView" Index="2" />
          <Item Id="Event_ListView" Index="3" Caption="Scheduler Event" />
          <Item Id="MyDetails" Index="4" />
          <Item Id="Note" Index="5" />
          <Item Id="Payment_ListView" Index="6" />
          <Item Id="Position_ListView" Index="7" />
          <Item Id="Resume_ListView" Index="8" />
          <Item Id="SecuritySystemRole_ListView" Index="9" />
          <Item Id="SecuritySystemUser_ListView" Index="10" />
         </Items>
      </Item>
      <Item Id="Reports" Caption="Reports">
         <Items>
          <Item Id="Analysis_ListView" Index="0" Caption="Analysis" />
          <Item Id="ReportsV2" Index="1" Caption="Reports" />
         </Items>
      </Item>
     </Items>
  </NavigationItems>
 </Application>

The migration is completed. Run the MainDemo.Mvc project and authorize.

mvc_25

When authorizied, make sure that the newly created MVC application has all functions of the original XAF Main Demo.

mvc_26