Scenario
XAF developers often create initial security roles via the administrative UI (at runtime) in non-production databases of their test environments. The visual approach is often faster than writing C# or VB.NET code manually, especially for complex permissions with criteria (check screenshots). If you create initial roles at runtime with test databases, you need to eventually transfer this data to production databases on customer sites.
Solution
ModuleUpdater API and DBUpdater are standard means to seed initial data in databases with XAF.
We will demonstrate how to automatically create ModuleUpdater C# or VB.NET code for required roles created by XAF developers at runtime with test databases. XAF developers can easily copy and paste this ready code into their ModuleUpdater descendant and use the standard DBUpdater tool to seed data in production databases. We intentionally skip user creation code, because user names are often unknown at early stages and it is much easier to create and link users to predefined roles later in production environment.
![image]()
Implementation Steps
Step 1. In the Solution Explorer, include RoleGenerator.csproj or RoleGenerator.vbproj into your XAF solution and then reference this RoleGenerator project from the YourSolutionName.Module one.
Step 2. Include the following files into your XAF solution projects
•
YourSolutionName.Module: RoleGeneratorController.cs or RoleGeneratorController.vb;
•
YourSolutionName.Module.Win: RoleGeneratorControllerWin.cs or RoleGeneratorControllerWin.vb;
•
YourSolutionName.Module.Web: RoleGeneratorControllerWeb.cs or RoleGeneratorControllerWeb.vb.
Step 3. Modify the YourSolutionName.Win/App.config and YourSolutionName.Web/Web.config files to add the EnableRoleGeneratorAction
key under the appSettings
section.
[XML]
<appSettings>
...<addkey="EnableRoleGeneratorAction"value="True"/></appSettings>
Step 4. Run the YourSolutionName.Win or YourSolutionName.Web project, select roles in the Role
ListView, and click the Generate Role
Action (in the WinForms project, this Action is under the Tools
menu).
WinForms:
![image]()
ASP.NET WebForms:
![image]()
Step 5. Save the generated file and research its content. It contains code that creates initial roles based on data stored in your test database. To use this file in your XAF solution, consider one of these two strategies:
• Modify the existing
YourSolutionName.Module/DatabaseUpdate/Updater.xx file based on the
CreateUsersRole
method code copied from the generated
Updater.xx file.
• Include the generated
Updater.xx file into the
YourSolutionName.Module/DatabaseUpdate folder and modify the YourSolutionName/Module.cs or YourSolutionName/Module.vb file to use this new
RoleUpdater
class as follows:
// C#
using System;
using DevExpress.ExpressApp;
using System.Collections.Generic;
using DevExpress.ExpressApp.Updating;
namespace YourSolutionName.Module {
public sealed partial class YourSolutionNameModule : ModuleBase {
public override IEnumerable<ModuleUpdater> GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) {
ModuleUpdater updater = new DatabaseUpdate.Updater(objectSpace, versionFromDB);
ModuleUpdater roleUpdater = new RoleUpdater(objectSpace, versionFromDB);
return new ModuleUpdater[] { updater, roleUpdater };
//...
[VB.NET]
Imports SystemImports DevExpress.ExpressAppImports System.Collections.GenericImports DevExpress.ExpressApp.UpdatingNamespace YourSolutionName.Module {PublicNotInheritablePartialClass YourSolutionNameModuleInherits ModuleBasePublicOverridesFunction GetModuleUpdaters(ByVal objectSpace As IObjectSpace, ByVal versionFromDB As Version) As IEnumerable(Of ModuleUpdater)Dim updater As ModuleUpdater = New DatabaseUpdate.Updater(objectSpace, versionFromDB)Dim roleUpdater As ModuleUpdater = New DatabaseUpdate.RoleUpdater(objectSpace, versionFromDB)ReturnNew ModuleUpdater() {updater, roleUpdater}EndFunction
Customization for Custom Security Roles
If you have a custom security role class (for instance, ExtendedSecurityRole
as in these examples: one, two) and this class has custom properties, you need to include these properties into the generated code. To do this, handle the RoleGenerator.CustomizeCodeLines
event in the RoleGeneratorController
class added at Step 2:
// C#
using System.Collections.Generic;
using System.Linq;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using DevExpress.Persistent.Base;
using RoleGeneratorSpace;
namespace XafSolution.Module.Controllers {
public abstract class RoleGeneratorController : ViewController<ListView> {
//...
protected void RoleGeneratorAction_Execute(object sender, SimpleActionExecuteEventArgs e) {
RoleGenerator roleGenerator = new RoleGenerator(roleType);
roleGenerator.CustomizeCodeLines += RoleGenerator_CustomizeCodeLines;
IEnumerable<IPermissionPolicyRole> roleList = e.SelectedObjects.OfType<IPermissionPolicyRole>();
string updaterCode = roleGenerator.GetUpdaterCode(roleList);
SaveFile(updaterCode);
}
private void RoleGenerator_CustomizeCodeLines(object sender, CustomizeCodeLinesEventArg e) {
ExtendedSecurityRole exRole = e.Role as ExtendedSecurityRole;
if(exRole != null) {
e.CustomCodeLines.Add(string.Format("role.CanExport = {0};", exRole.CanExport.ToString().ToLowerInvariant()));
}
}
}
}
[VB.NET]
Imports SystemImports System.Collections.GenericImports System.ComponentModelImports System.LinqImports DevExpress.ExpressAppImports DevExpress.ExpressApp.ActionsImports DevExpress.ExpressApp.SecurityImports DevExpress.Persistent.BaseImports RoleGeneratorSpaceImports XafSolution.SecurityNamespace XafSolution.Module.ControllersPublicMustInheritClass RoleGeneratorControllerInherits ViewController(Of ListView)ProtectedSub RoleGeneratorAction_Execute(ByVal sender AsObject, ByVal e As SimpleActionExecuteEventArgs) Handles roleGeneratorAction.ExecuteDim roleGenerator AsNew RoleGenerator(roleType)AddHandler roleGenerator.CustomizeCodeLines, AddressOf RoleGenerator_CustomizeCodeLinesDim roleList As IEnumerable(Of IPermissionPolicyRole) = e.SelectedObjects.OfType(Of IPermissionPolicyRole)()Dim updaterCode AsString = roleGenerator.GetUpdaterCode(roleList)
SaveFile(updaterCode)EndSubPrivateSub RoleGenerator_CustomizeCodeLines(ByVal sender AsObject, ByVal e As CustomizeCodeLinesEventArg)Dim exRole As ExtendedSecurityRoleTS = TryCast(e.Role, ExtendedSecurityRoleTS)If exRole IsNot NothingThen
e.CustomCodeLines.Add(String.Format("role.CanExport = {0}", exRole.CanExport))EndIfEndSubEndClassEndNamespace