This example illustrates how to store user UI settings (so-called model differences) in the application database instead of the file system (in Windows Forms applications) and session (in ASP.NET appications).
By default, an XAF Windows Forms application stores user customizations of the Application Model in the Model.User.xafml file, located in the application's directory. The application's model difference storage is also file-based (Model.xafml file). These two layers are superimposed when running an application. All model-related changes made by the end-user (e.g., layout customizations) are saved to the Model.User.xafml. The potential disadvantages of this default approach are:
- The Model.xafml file is not shared (except when the application is deployed to the terminal server). So even if this file is modified by an administrator, it must be re-deployed to all users to take effect;
- Since model differences are stored in a plain XML format, anyone who has access to XAFML files can easily influence the work of the application. So, it is possible to affect a critical setting that will cause the application to stop functioning;
- Several users sharing the same copy of the application cannot have individual customizations. This can be resolved by changing the user differences file location to the user profile folder (by setting the UserModelDiffsLocation key value to the CurrentUserApplicationDataFolder in the application configuration file). However, the problem persists if users are working under the same system account.
By default, an XAF ASP.NET application stores user customizations of the Application Model in the session. The global application model difference storage is file-based (Model.xafml file located in the web application folder). These two layers are superimposed when running an application. All model-related changes (e.g., columns order and visibility in List Views, dashboard layouts, etc.) made by end-users are saved to cookies. If a user accesses the ASP.NET application via several different devices (desktop, laptop or tablet), settings are not synchronized.
Generally, you can use the default storage in most scenarios. However, the disadvantages listed above become critical if you wish to give more power to application administrators and enhance application security. This example provides a solution that eliminates all these disadvantages. The main idea is to store all model differences in the application's database. Follow the instructions below to use the database model difference storage in your XAF application.
Build the DatabaseUserSettings.dll Assembly
- Download the solution attached to this example.
- Upgrade the downloaded solution up to your currently installed version of DXperience. Use the Project Converter utility for this purpose.
- Open the converted solution in Visual Studio. Switch to the Release configuration and build the DatabaseUserSettings project (this project contains the module that we are going to use).
- Copy the DatabaseUserSettings.dll assembly to an appropriate location in your development workstation.
Add the DatabaseUserSettings Module to Your XAF Solution
- Open your XAF solution that will use the DatabaseUserSettings module.
- Add the DatabaseModelStrorage.dll reference to the platform-agnostic module project.
- Right-click the Module.cs file and choose View Code. Modify the module's constructor in the following manner.
[C#]publicsealedpartialclassMySolutionModule:ModuleBase{publicMySolutionModule(){InitializeComponent();this.RequiredModuleTypes.Add(typeof(DatabaseUserSettings.DatabaseUserSettingsModule));}}
Note:Alternatively, you can add the DatabaseUserSettings in the Module Designer.But you should register the DatabaseUserSettingsModule toolbox item first (see How to: Add Items to the Toolbox).
Now you can logon using different credentials and apply different customizations for each user. For instance, you can change the active skin for each user. Different users will have different skins selected after the application is restarted. Users should have read/write access to the XPUserSettings and XPUserSettingsAspect persistent types (these types are provided by the DatabaseUserSettings module and are used to store model differences).
The Configurator Account
To manage default model settings applied to users, a special Configurator account can be used. All customizations made by Configurator in the Model Editor or directly in the UI will be stored to the shared Application Model layer. To create such an account, do the following.
- Add a Role named "Configurator" (this name is declared by the DatabaseUserSettingsModule.ConfiguratorRoleName constant).
- For the added Role, grant full access to the XPUserSettings and XPUserSettingsAspect persistent types and read access to the UserName member of the type that represent users in your application (SecuritySystemUser by default). Alternatively, you can simply mark this role as administrative (see SecuritySystemRoleBase.IsAdministrative).
- Add a User named "Configurator" (this name is declared by the DatabaseUserSettingsModule.ConfiguratorUserName constant), and associate this user with the "Configurator" role.
Refer to the Updater.cs file to see the code.
The ManageUserSettings Action
The Configurator user has access to the ManageUserSettings Action. This Action of the PopupWindowShowActiontype is provided by the ManageUserSettingsWindowController Controller implemented in the DatabaseUserSettings module. This Action is intended to import a user setting from one user to another.
See Also
Core - Provide an easy way to store administrator and user model differences in a custom store (e.g., in a database)
A reusable XAF module for storing model settings in the database (security system type insensitive!)
ImportantNotes
1. Be aware of the following issue with this example: User settings may be duplicated/overridden under certain circumstances after merging configurator and user settings applied to the same element
2. This example solution is not yet tested in the middle-tier and SecuredObjectSpaceProvider scenario and most likely, it will have to be modified to support its specifics.
3. This example solution is not yet tested with custom fields.
Question Comments
Added By: Pawel Rymarczyk 1 at: 5/20/2012 6:35:40 AM
Hi,
Not working with DbUpdater 11.2.
Ticket: http://www.devexpress.com/Support/Center/Question/Details/Q400938
Added By: Sandro Welter (Intelligix) at: 7/6/2012 10:14:37 AMHi,
I need this example in 12.1 version. Thanks.
Added By: Robert Fuchs at: 7/11/2012 8:25:44 AM> Take special note that it is important to grant write permissions for
> your persistent model differences classes to the anonymous user:
AFAIR the new security system does not need an anonymous user any more?
Added By: Miles at: 7/12/2012 12:44:42 PM12.1 version please!
Added By: Frank (DataJunxion) at: 8/10/2012 11:00:41 PM12.1 version?
Added By: John Botibol at: 9/12/2012 1:09:39 AMHi Guys, the Issue (Q421353) mentioned above as one to be aware of is marked as private so this is quite tricky!
Added By: Paolo Parente at: 10/31/2012 7:21:27 AMHi, is there a way to download the whole solution, without select every single file?
Thanks,
Paolo
Ok, i did it.
But now i've a question: i can i deploy the new Model.xafml when a new version of the application has been developed?
Thanks,
Paolo
I have the same problem as Paolo: How to handle the case when a new softare version with another Model.xafml must be distributed? Is there a ay to do this?
Added By: Dennis (DevExpress Support) at: 11/6/2012 12:03:35 PMI have answered your question about deploying the new version in http://www.devexpress.com/Support/Center/Issues/ViewIssue.aspx?issueid=Q443198
Added By: Robert Fuchs at: 12/15/2012 10:38:45 AMhttp://www.devexpress.com/issue=Q421353 is still private.
Is it fixed in the 12.2 example?
Iuse linq queries and Custom fields on model.xafml following http://www.devexpress.com/Support/Center/Example/Details/E859. I get exception on project start up: An error with number 1009 has occurred.
Error message: Error occurs while adding the 'FieldName_Linq' custom property ('System.Double' property type) to the 'MyClassName' type: 'Object reference not set to an instance of an object.'
Guys, please refer to the public http://www.devexpress.com/issue=Q470416 ticket instead of the private Q421353 one.
Added By: Mr292 at: 1/30/2013 5:44:44 PMDennis, Thanks a lot for this. I had implemented something similar before but I have now moved to your code so as to take advantage of any future changes.
I have a few questions though
1. Does the Model.xafml in the Program Folder get hit at all? It does not seem like it from the code, but wanted to be sure.
2. I had implemented a feature where on exit, the configurator would be prompted to store changes. I have modified this to do the same but in my implementation, the user was being prompted twice. This I have noticed is an issue with a lot of functions in XAF but is usually solvable easily. In this instance, what should I check for to disable the consecutive prompt?
3. Lastly, Just so some users are aware I was having issues saving Chart/Pivot Settings as XML in MySQL if I use latin1 in innodb. Not your fault but I had implemented a BLOB save instead to get over that.
How can I logon by Configurator user, if domain authentication used?
Added By: Nate Laff at: 4/12/2013 8:09:31 AMImplemented this yesterday after using the example of this from a long time ago (admin mode) and overall I like it.
Administrator users in my opinion shouldn't be able to see the User Settings navigation item. Unfortunately Q485525 prevents this from happening easily. Or am I missing something that this should be visible to Administrator. Seems like only Configurator should see it.
Added By: Nate Laff at: 4/16/2013 2:29:56 PMAlso, this has been an issue since the first iterations of this. If you make changes to the Win model at the highest level (Model.xafml) such as moving the location of MyDetails, these changes always get messed up. In the current scenario, MyDetails shows up in the navigation group I specified, but also gets duplicated in the default group after you logon with the Configurator user. Does this happen to anyone else?
Added By: Nate Laff at: 4/16/2013 3:03:33 PMAlso, what's the process here? Let's say you want to make a global change to a view as Configurator..
Log on as Configurator
Make changes
Exit
Log on as Configurator
Manage User Settings action, import from source Configurator to all users
Exit
Log on as User
Verify changes
Is that the process? Am I missing something. The exits are required?
Also, you can't reset to defaults without opening Model Editor as configurator, resetting there, exiting, manage user settings and import from Configurator source again?
Just trying to make sure I have this process down correctly.
Added By: Nate Laff at: 5/2/2013 11:06:59 AMDennis?
Added By: zacarias de prado habela at: 7/26/2013 4:31:49 AMHi:
Where is "XPManageUserSettingsParameter", "XPUserSettings", XPUserSettingsAspect defined?
Thanks
These classes are defined in the DatabaseUserSettings module. Use the Visual Studio search facilities to locate them...
Added By: Gabriel at: 9/24/2013 10:54:17 AMMy happy day :D
Added By: Carlitos at: 1/4/2014 5:32:43 PMQuick question on the IMPORTANT NOTES:
1 - the bug was corrected right?
2 - Will there be a middle-tier and SecuredObjectSpaceProvider example?
Thanks
Carlitos
Added By: Elvis Serret at: 9/30/2014 8:49:04 AMI have made this work with my Win app in multi-tier using remoting, how can I make it work for ASP.NET web app
Added By: Dennis (DevExpress Support) at: 9/30/2014 8:54:01 AM@Elvis: Exactly the same approach should be used for the Web app. What does not work for you in a Web app, or what can't you implement there?
Added By: Elvis Serret at: 10/30/2014 12:33:54 AMIn Web App it seems that the changes are not saved to the database for any of the users. Works fine in Win App
Added By: Elvis Serret at: 10/30/2014 12:36:35 AMAlso after making changes in Win App, Web App does not pick up the changes of same user when login