Skip to content

Generate ModuleUpdater code for security roles created by XAF developers at runtime in test databases.

License

Notifications You must be signed in to change notification settings

DevExpress-Examples/XAF_How-to-get-role-code-from-the-UI

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

79 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

How to generate database updater code for security roles created via the application UI in a development environment

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

If this solution does not work for you, you can dump required data records from the development database to an XML file and then load this XML file from an application using the production database or transfer data using the built-in RDBMS capabilities. For more information, please review Security - Best Practices for Export/Import Role Permissions at runtime (without releasing a new application version to clients).


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. Reference the System.Configuration.dll assembly from the YourSolutionName.Module project and add the following files to your XAF solution projects

Step 3. Modify the YourSolutionName.Win/App.config and YourSolutionName.Web/Web.config files to add the EnableRoleGeneratorAction key under the appSettings section.

<appSettings>
    ...
  <add key="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 System
Imports DevExpress.ExpressApp
Imports System.Collections.Generic
Imports DevExpress.ExpressApp.Updating

Namespace YourSolutionName.Module {
  Public NotInheritable Partial Class YourSolutionNameModule
   Inherits ModuleBase
    Public Overrides Function 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)
        Return New ModuleUpdater() {updater, roleUpdater}
    End Function
'...

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 System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Linq
Imports DevExpress.ExpressApp
Imports DevExpress.ExpressApp.Actions
Imports DevExpress.ExpressApp.Security
Imports DevExpress.Persistent.Base
Imports RoleGeneratorSpace
Imports XafSolution.Security

Namespace XafSolution.Module.Controllers
    Public MustInherit Class RoleGeneratorController
        Inherits ViewController(Of ListView)
'...
        Protected Sub RoleGeneratorAction_Execute(ByVal sender As Object, ByVal e As SimpleActionExecuteEventArgs) Handles roleGeneratorAction.Execute
            Dim roleGenerator As New RoleGenerator(roleType)
            AddHandler roleGenerator.CustomizeCodeLines, AddressOf RoleGenerator_CustomizeCodeLines
            Dim roleList As IEnumerable(Of IPermissionPolicyRole) = e.SelectedObjects.OfType(Of IPermissionPolicyRole)()
            Dim updaterCode As String = roleGenerator.GetUpdaterCode(roleList)
            SaveFile(updaterCode)
        End Sub
		
        Private Sub RoleGenerator_CustomizeCodeLines(ByVal sender As Object, ByVal e As CustomizeCodeLinesEventArg)
            Dim exRole As ExtendedSecurityRoleTS = TryCast(e.Role, ExtendedSecurityRoleTS)
            If exRole IsNot Nothing Then
                e.CustomCodeLines.Add(String.Format("role.CanExport = {0}", exRole.CanExport))
            End If
        End Sub
      
    End Class
End Namespace

'...

Note: You can find the solution for .NET Core, ASP.NetCore Blazor in the 21.2.4 branch

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Releases

No releases published

Packages

No packages published