How the XAF Application Model Works
- 8 minutes to read
The Application Model is metadata that defines the navigation structure, data presentation formats, and available commands. XAF builds this metadata based on the application code. You can extend or customize the application model to add this functionality to your application. Users can also access the Application Model so that they can adjust their applications.
The following image demonstrates the built-in Model Editor dialog. Try the Edit Model command in any of the eXpressApp Framework demos to access this editor.
How XAF Uses the Application Model
When you run an XAF application, the framework performs the following steps:
- Scans the application’s code to generate the Application Model.
- Populates the Application Model with default values. Learn about node generators and model extenders to understand how this process works and how you can control it. For extension examples, see Extend and Customize the Application Model in Code.
- Looks for previously saved model differences that change default values. (These could be user-made edits from previous application runs.) Applies these changes.
- Creates UI elements based on up-to-date Application Model information.
- You can change the Application Model after XAF creates the application’s UI. In such cases, you need to force a UI refresh to reflect these changes. For a workaround, see the following article: Apply Application Model Changes to the Current View Immediately.
What Code Takes Part in Application Model Generation
XAF calls the GetExportedTypes()/GetControllerTypes() methods for each module to discover classes that take part in the Application Model structure. These methods use reflection to locate the classes listed below.
- Business Object Model
These classes make up the BOModel node. For details on which classes make their way to this node, see Add a Business Class and Non-Persistent Objects.
- Controller and Actions
These classes make up the ActionDesign node. For additional information, see Controllers and Actions.
XAF uses only public classes to build the Application Model.
Application Model API
The Application Model is a tree of nodes. Each node type exposes its own property set.
Node Types / Interfaces
XAF defines an interface for each Application Model node type. All these interfaces share a common ancestor: IModelNode. The members of this base interface allow property modification and access to the parent and child nodes.
One of the descendants is the IModelApplication interface that corresponds to the root node (Application). This interface defines a few application-level properties (Title, Company, Description) and child nodes (ActionDesign, Views, and others).
Review all available node interfaces: Application Model - Built-in Interfaces.
XAF allows you to extend the Application Model - add properties or child nodes to existing nodes. The basic idea is that an “extender” interface (the one with additional properties or children) can attach to a node.
You can use built-in extenders, such as IModelListViewFilters. This interface extends a ListView node with the Filters child. For the complete list of built-in extender interfaces, see Application Model - Built-in Interfaces.
You can also extend Application Model nodes with custom properties and children. For samples, refer to the following article: How to Extend the Application Model.
Access and Modify the Application Model in Code
You can write code that obtains the Application Model object, accesses specific child nodes, and changes their settings. For samples, refer to the following article: Change the Application Model.
Application Model Layers
On the one hand, XAF promotes code re-use and the same Business Model and Controllers can serve in multiple applications for different platforms.
On the other hand, different applications may benefit from variations in UI layout. Different users can also tailor the applications to their own requirements.
This means that XAF must maintain the basic Application Model and variations that apply to the model on different levels:
- The zero layer
XAF generates this layer based on the code of the application modules and referenced modules (as described earlier in this article).
- Module-level differences
These platform-specific differences exist for each application module.
- Administrator differences
These project-specific differences exist for each application project.
- User differences
End-user customizations to the Application Model. These differences exist on each end-user machine.
If different layers have different values for the same property, XAF uses the value from a higher level. For example, a value from the ‘User differences’ layer has a higher priority than that of the ‘Module-level’ layer.
The following image illustrates this layered structure:
Application Model Differences: Storage Types
XAF can store Application Model changes (Model Differences) in different mediums. The
ModelStoreBase class implements the basic storage functionality. The following descendants are available:
FileModelStore- XAFML file
ResourcesModelStore- Project resource
CookiesModelDifferenceStore- Cookies (ASP.NET Web Forms)
The default storage types for the layers are listed in the table below:
|Layer||Blazor||WinForms||ASP.NET Web Forms|
|Module-Level Differences||Assembly resources||Assembly resources||Assembly resources|
|User Differences (No Security System)||(no storage)||
|User Differences (With Security System)||
You can change storage type for Administrator and User differences. Subscribe to the following events:
- Administrator differences: CreateCustomModelDifferenceStore
- User differences: CreateCustomUserModelDifferenceStore
File Storage Details
To store Model Differences in files, XAF uses *.xafml files that can be edited by the Model Editor. There are two types of *.xafml files.
- Model Differences - contains general UI customizations
- Model Difference Aspects - contains localized UI customizations
To learn more about Application Model localization, refer to the following article: Localization Basics.
The table below lists the names and locations of *.xafml files for different Application Model layers.
|Layer||Model Differences||Model Difference Aspects||Location|
|Module Level||Model.DesignedDiffs.xafml||Model.DesignedDiffs.Localization.<language code>.xafml||Assembly resources|
|Administrator Level||Model.xafml||Model.<language code>.xafml||Application folder|
|User Level||Model.User.xafml||Model.User.<language code>.xafml||Application folder or the %USERPROFILE%\AppData folder .|
The User Model Differences location is specified in the App.config file. See the code below.
<appSettings> <!-- ... --> <add key="UserModelDiffsLocation" value="CurrentUserApplicationDataFolder"/> <!-- ... --> </appSettings>
Possible values are:
|None||User differences are not saved.|
|ApplicationFolder||Default value. User differences are stored in the application’s working folder (together with the application executable).|
|CurrentUserApplicationDataFolder||User differences are stored in the user profile (the %USERPROFILE%\AppData folder).|
Database Storage Details
If you need to enable Database Storage in an existing application, refer to the following help topic: Store Application Model Differences in the Database.
XAF uses two entities to store Model Differences in the database. The entities form a one-to-many relationship.
The IModelDifference interface stores a collection of Model Difference Aspects for a user.
Each Model Difference has an associated user (IModelDifference.UserId). An empty UserId means that the current Model Difference is shared by all users and is superimposed with their individual settings.
A Model Difference also defines an IModelDifference.ContextId that corresponds to the target platform. That way, separate sets of differences may be used for the same user when they run applications on a desktop or the web.
Model Difference Aspect
The IModelDifferenceAspect interface stores a changed setting in the IModelDifferenceAspect.Xml property.
The IModelDifferenceAspect.Name property sets the locale for the difference. If the property value is empty, the aspect applies to all languages.
If you use the Integrated security mode or the Middle Tier server, ensure that all users have read/write access to ModelDifference and ModelDifferenceAspect types (users with read-only permissions cannot persist application customizations when exiting). Read and write permissions are required for the Model.xafml file import operation. In the Middle Tier scenario, the Create permission is additionally required.
As an alternative for giving a user read-only permissions, you can use the WinApplication.IgnoreUserModelDiffs property to ignore the User’s Model Differences.
Shared Model Differences Management
The Solution Wizard generates, but comments out the code that enables database storage for shared model differences (administrator settings). That code is available in WinModule.cs (WinModule.vb) and WebModule.cs (WebModule.vb) files.
XAF’s default behavior is to always load design-time settings.
You can uncomment the XafApplication.CreateCustomModelDifferenceStore event subscription. Model.xafml file content will be loaded to the database once the application is started. XAF will ignore further changes to this file if the database record already exists for the shared model differences. To reload settings from Model.xafml, enable the administrative UI and use the Import Shared Model Difference Action (or delete the Shared Model Difference record and restart).
The following combination of features is not supported when used together.
- SecuredObjectSpaceProvider or XPObjectSpaceProvider created using the constructor with the threadSafe parameter set to true (this parameter enables the ThreadSafeDataLayer).
- Application-wide model differences are stored in the database using the XafApplication.CreateCustomModelDifferenceStore event (you can still store user-specific differences in the database using the XafApplication.CreateCustomUserModelDifferenceStore event).
- Custom Persistent Fields declared in the application-level model differences.
In this configuration, your application loads information on custom persistent fields from the database and then updates the database schema. However, a thread-safe data layer does not support altering the data model after the database connection is established.
To store changes for the User Differences (No Security System) layer in Blazor applications, handle the CreateCustomUserModelDifferenceStore event.