Description of the example of adding user settings and system settings to training application Xafari Nortwind using component Xafari.BC.Settings.

Background information on Xafari.BC.Settings

From the conceptual angle, with the typical use of the component functionality, the 'Setting' is a stored value of a global variable within the limits of the system. The value of the Setting either can be stored as a global value (applicable to all users of the application system), or it can be specified for certain user or role. In order to implement such behavior, the concept of 'layer' is used. The layer allows to redefine the value of the setting in the following layer, for example, layer 'by users' allows to determine the values: 1) Global value 2) Value for the layer 3) Value for the user. This functionality can be used for the purposes of the application as well, for example, the Setting can depend on the document type, in which case the document type is the layer.

The concept of Settings has the following specifics:

  1. The Setting is a stored global variable.
  2. It is only possible to add a new Setting in the Visual Studio.
  3. It is possible to set value for the Setting in the application (special forms, intended for the user and for the administrator, are used for this purpose).
  4. Values of Settings are stored in the server database.

Training task definition

The following discussion refers to training application Xafari Nortwind. It is necessary to add Settings to the application. The Settings must be accessible for the user so that the user can set values of the Settings. The list of the required Settings is shown in the table:

SettingSetting type
CategoryCategory (persistent)
EmployeeEmployee (persistent)

We also raise an additional requirement that the Settings must be combined in the following groups:
xafari application settings
It is necessary to allow the user to set values of the settings at the following levels:

  1. Global value — for all users
  2. At the user's subdivision level
  3. At the user level

To achieve this, it is necessary to define three layers, respectively:

  1. Default layer
  2. Layer based on object type 'Department'
  3. Layer based on object type 'InheritedUser'

Each element of the second layer will be based on an instance of 'Department', and elements based on the instances of 'InheritedUser', that belong to the specified 'Department', will be its descendants.
xafari instances and descendands

Connecting modules

To start the work with application settings, it is necessary to connect the following modules:
XafariBCSettingsModule has to be connected to a platform-independent part of the application solution.
A link to the respective library will be added to directory 'References' of the project.
Recommendation: Link the library again manually.

Connecting modules

  • Connect module XafariBCSettingsModule to the platform-independent part of the application solution.
  • A link to library XafariBCSettings will be added to directory 'References' of the project.
  • Recommendation: Link the library again manually.
  • Connect XafariBCSettingsWinModule or XafariBCSettingsWebModule to the respective platform-dependent part of the application solution.
  • A link to the respective library will be added to directory 'References' of the respective project.
  • Recommendation: Link the respective libraries again manually.

Description of setting layers

Description of the last layer:
public class NorthwindSettingsInheritedUser : SettingValueSlice
        public override List ChildrenSlices
            get { return new List(); }

This code tells that instances of class 'NorthwindSettingsInheritedUser' will represent the last layer in the layer hierarchy, and also:

  • They will be based on object type 'InheritedUser'
  • The parent layer for this layers will have type 'NorthwindSettingsDepartment'
  • An empty collection will always be returned when calling the list of child layers
Description of an interim layer:
public class NorthwindSettingsDepartment : SettingValueSlice
        public override string Name
            get { return this.SliceObject.Name; }
        public override IEnumerable GetChildrenFromNextSlice()
            var users = this.ObjectSpace.GetObjects(CriteriaOperator.Parse("Department = ?", this.SliceObject));
            return users.Select(user => (NorthwindSettingsInheritedUser)this.GetChildSlice(user)).ToList();

This code tells that instances of class NorthwindSettingsDepartment will represent an interim layer in the layer hierarchy, and also:

  • It will be based on object type Department
  • A layer of type NorthwindSettingsDefaultValueSlice will be a parent layer for the described layer
  • Layers of type NorthwindSettingsInheritedUser will be child layers for the described layer
  • Method GetChildrenFromNextSlice() describes the logic of getting child layers of the child layers of the described layer
  • When field Name is called, it will return the Name fields of a Department type object (the object, based on which this layer was obtained)
Default layer description:
public class NorthwindSettingsDefaultValueSlice : SettingDefaultValueSlice
        public override IEnumerable GetChildrenFromNextSlice()
            var departments = this.ObjectSpace.GetObjects();
            return departments.Select(slice1 => (NorthwindSettingsDepartment)this.GetChildSlice(slice1)).ToList();

This code tells that instances of class NorthwindSettingsDefaultValueSlice will represent the default layer in the layer hierarchy, and also:

  • Layers of type NorthwindSettingsDepartment will be child layers for this layer
  • Method GetChildrenFromNextSlice() describes the logic of getting child layers of the child layers of the described layer
  • Null will be the parent layer for this layer.
Description of settings and setting groups

Let us describe the interface containing settings for application Northwind:

public interface IModelNorthwindSettings

We extend model node Setting in the platform-independent module (file Module.cs) by adding a setting node for application Northwind:

 public override void ExtendModelInterfaces(ModelInterfaceExtenders extenders)

We add 3 setting groups, Documents, Classifiers, Olap. Settings interface IModelNorthwindSettings will be as shown below:
public interface IModelNorthwindSettings

        Documents Documents { get; }
        Classifiers Classifiers { get; }
        IModelOlapSettings Olap { get; }

The following code was used to describe settings group Documents:

public interface Documents : IModelBCSettingsGroup
        Order Order { get; }

Group Documents includes group Order:

public interface Order : IModelBCSettingsGroup
        IModelKeyEmployeeObject Employee { get; }
        IModelKeyDateTime ShippedDate { get; }

Group Order includes 2 settings. Setting ShippedDate is of type IModelKeyDateTime, which is provided by platform XAFARI. Setting Employee is of type IModelKeyEmployeeObject and is persistent, the code describing the setting of type IModelKeyEmployeeObject:

public interface IModelKeyEmployeeObject : IModelBCSettingsObjectItem
public class IModelKeyEmployeeObjectLogic : IModelBCSettingsXPObjectItemLogic
        public IModelKeyEmployeeObjectLogic(IModelKeyEmployeeObject instance) : 
        base(instance) { }

Please note that when describing a persistent type setting, it is necessary that the setting interface is inherited from interface IModelBCSettingsObjectItem, and the domain logic of the setting is inherited from class IModelBCSettingsXPObjectItemLogic. The remaining parts of the process of creation of the persistent type interface do not differ from the process of creation of the non-persistent type setting.
Let's return to the description of settings for application Northwind.
Setting group Classifiers is described as shown below:

public interface Classifiers : IModelBCSettingsGroup
        Product Product { get; }
        Territory Territory { get; }
        Supplier Supplier { get; }

In the description we can see, that group Classifiers includes groups Product, Territory, and Supplier. These groups and the settings contained in them are described, as shown below:
Group Product:

public interface Product : IModelBCSettingsGroup
        IModelKeyCategoryObject Category { get; }
        IModelKeyString ShortName { get; }

Setting Category, which is a member of group Product, is described, as shown below:

public interface IModelKeyCategoryObject : IModelBCSettingsObjectItem
    public class IModelKeyCategoryObjectLogic : IModelBCSettingsXPObjectItemLogic
        public IModelKeyCategoryObjectLogic(IModelKeyCategoryObject instance) :
            base(instance) { }

Group Territory:

public interface Territory : IModelBCSettingsGroup
        IModelKeyString TerritoryName { get; }
        IModelKeyString Code { get; }

Group Supplier:

public interface Supplier : IModelBCSettingsGroup
        IModelKeyString HomePage {  get; }
        IModelKeyString Region { get; }
Using SettingsAccessor

At this phase, we have described the setting layers and the settings properly.
All work with the settings and layers is done by means of an Instance of class SettingsAccessor. Therefore, to work with the settings for application Northwind, it is necessary to implement one's own class SettingsAccessor based on the base class:

public class NorthwindSettingsAccessor : SettingsAccessor
        public NorthwindSettingsAccessor(XafApplication application)
            : base(application)
            this.RootSlice = new NorthwindSettingsDefaultValueSlice();
            this.SliceTypes = new[]
                                    typeof (NorthwindSettingsDepartment),
                                    typeof (NorthwindSettingsInheritedUser),

It is necessary to inherit class NorthwindSettingsAccessor from class SettingsAccessor and specify some properties of class SettingsAccessor:

  • RootSlice is the property, to which we need to assign an instance of the default layer.
  • SliceTypes is the property to which it is necessary to assign an array of the layer types used in this layer hierarchy, except the default layer type.

After the above manipulations are completed, it is necessary to assign an instance of the class described above to property Instance of class SettingsAccessor (this assignment is made based on event LoggedOn of the application):

void Application_LoggedOn(object sender, LogonEventArgs e)
        var application = sender as XafApplication;
        if (application == null) return;
        if (SettingsAccessor.Instance != null) return;
        SettingsAccessor.Instance = new NorthwindSettingsAccessor(application);
        SettingsAccessor.Instance.CurrentSlice = SettingsAccessor.Instance.GetSlice(
        ((InheritedUser)SecuritySystem.CurrentUser).Department, SecuritySystem.CurrentUser);

We can see in the code, that a layer corresponding to the current user is assigned to property CurrentSlice; if nothing is assigned, then property CurrentSlice will correspond to the default layer.
You can see the results of the work described above in the Xafari demo center:

Examples of settings in the demo center

Write US