This topic provides details about the structure and usage of personalization in Sitefinity.
Database Schema
In a regular Asp.Net application, the personalization values are stored by the built-in Profile Provider. However, in Sitefinity, the Profile Provider is allocated
for usage by external developers. Hence, we need a similar kind of separate storage to store these personalization settings. Table 1 shows the table’s schema
that will hold the system and module personalization values.
telerik_Personalization
| Field Name |
Data Type |
Notes
|
| ID (PK) |
int (Auto Number) |
Auto Increment |
| Application |
nvarchar(50) |
Application Name. Same as the telerik_Applications |
| UserName (FK) |
nvarchar(250) |
User Name. Same as the Telerik_Users table. |
| ModuleName |
nvarchar(256) |
Name of the module. Will be Global if it is for System. |
| KeyName |
nvarchar(256) |
Key name must be unique along with the ModuleName (For module) for the user. |
| BinaryValue |
varbinary(MAX) |
Stores the serialized value in binary format. |
| XmlValue |
nvarchar(MAX) |
Stores the serialized value in xml format. |
Table 1
The above table contains both personalized system and module values. For example, if the personalization is of type System, the value
of ModuleName should be set to Global. An important field is BinaryValue which holds the value in
binary format. The XmlValue field stores the Xml serialized value. Since not all classes in the .NET Framework are xml-serializable, such as
the Dictionary of the System.Collections namespace, in such cases the field should be left null. To ensure the compatibility of this field,
the class needs to implement the IXmlSerializable interface.
 |
To store custom class in this column, the class needs to be decorated with a serializable attribute or it needs to
implement the ISerializable interface. |
Personalization Component
The component is developed following the provider model like the other Sitefinity components. Apart from provider-related classes, it contains the following interfaces:
IPersonalizedModule, IPersonalizationSetting, IPersonalizedDashboard. The modules and the System User Interface
components need to implement these interfaces in order to support personalization.
Following are the personalization-related methods of the PersonalizationProvider class:
PersonalizationProvider
Figure 1 shows the signature of the PersonalizationProvider abstract class:

Figure 1
|
Copy Code |
|
T GetGlobalValue<T>(string userName, string key)
|
This method returns the personalized value of the system for the specified user.
|
Copy Code |
|
void SaveGlobalValue<T>(string userName,
string key, T value)
|
This method stores the personalized value of the system for the specified user.
|
Copy Code |
|
T GetModuleValue<T>(string userName, string moduleName, string key)
|
This method returns the personalized value of the module for the specified user.
|
Copy Code |
|
void SaveModuleValue<T>(string userName,
string moduleName, string key, T value)
|
This method stores the personalized value of the module for the specified user.
|
Copy Code |
|
IDictionary<string, object>
GetGlobalValues(string userName, string[]
keys)
|
This method returns a Dictionary of the system personalized values for the specified user. Since the data type of the values in the Dictionary is not strongly typed, the
developer is responsible to cast back to the original data type. This method will be useful when more than one personalized setting should be loaded. An example for this
is loading the settings for the screen of My Preferences.
|
Copy Code |
|
void SaveGlobalValues(string userName,
IDictionary<string, object>
keyValuePairs)
|
This method saves the specified system personalization values embedded in a dictionary for the specified user. This method will be useful when multiple
values should be saved. An example for this is the settings screen of My Preferences.
|
Copy Code |
|
IDictionary<string, object>
GetModuleValues(string userName, string moduleName, string[] keys)
|
This method returns a Dictionary of the module personalized values for the specified user. This is similar to the GetGlobalValues method but it is for modules
where more than one value should be loaded for the specified user. It is especially useful for making screens like that of My Preferences.
|
Copy Code |
|
void SaveModuleValues(string userName,
string moduleName, IDictionary<string,
object> keyValuePairs)
|
This method is similar to the SaveGlobalValues method but module values are saved instead.
 |
Each of the above methods also has an overloaded version which does not have the userName as a parameter.
Instead, the Membership.GetUser() method is used to get the Current user name. |
IPersonalizedModule
The IPersonalizedModule interface is one of the interfaces that should be implemented by modules and system user interface components in order
to provide custom screens for modifying the personalization values. Figure 2 shows the signature of this interface:

Figure 2
The interface has only one method, which in turn returns the IPersonalizationSetting interface. The
CreateSettingPanel method creates the control which appears when the left-side text of the My Preferences link is clicked. This
method is similar to the WebModule.CreateControlPanel() method. Currently, the Blogs, Forums, Lists, News, and Polls modules implement the
IPersonalizedModule interface.
IPersonalizationSetting
Figure 3 shows the signature of the IPersonalizationSetting interface:

Figure 3
|
Copy Code |
|
bool CanBecomeVisible
|
This property allows the developer to decide whether to show the Settings screen in My Preferences or not. The My Preferences page loads these setting screens
dynamically, so the settings-screen developer could set the property to allow or deny dynamic loading of the screen. For example, when the News or Blogs modules have more than one
provider available, a new setting screen is created and displayed in My Preference. This enables the user to choose which provider should be used for the given module. However, if
the CanBecomeVisible property is set to false, the page My Preferences would not load that setting screen.
|
Copy Code |
|
int SettingOrder
|
This property returns the order number of the item in which the module will appear in the left side of the page My Preferences. Setting
Order is zero-based index and is usually configured in the web.config file. The page My Preferences uses this order number to sort the
left-side menu. If more than one module is uses the same order number, the left-side items of the page My Preferences will be sorted by the
SettingText property, and then displayed.
|
Copy Code |
|
string SettingText
|
This text appears on the left side of the page My Preferences for the setting screen.
|
Copy Code |
|
string TemplatePath
|
The template path of the control.
PersonalizationSettingPanel
Figure 4 shows the signature of the PersonalizationSettingPanel abstract class:

Figure 4
This is a base control which implements the IPersonalizationSetting interface. The PersonalizationSettingPanel class could be used as a base
class for creating the setting control for both module and system personalization. Currently, the Blogs, Forums, Lists, News, and Polls modules have inherited the class
for personalized setting screens. For system Personalization, Telerik.Cms contains the General, Dashboard and PageEditor settings classes that inherit
from the PersonalizationSettingPanel class.
Personalized Setting Screen Configuration
As mentioned above, Sitefinity contains two kinds of personalization: module and system. The module developer is responsible for creating
the module setting screen by implementing the IPersonalization interface. There is also a repository ModuleManager in the
Telerik.Framework namespace which could be queried to find out which are the currently loaded modules. However, there is no
stored collection of setting screens for system personalization. For this reason, a list of the system setting screens needs to be stored in the
web.config file under the <personalization> tag.
|
Copy Code |
|
<personalization defaultProvider="Sitefinity">
<providers>
<clear/>
<add
name="Sitefinity"
securityProviderName=""
type="Telerik.Personalization.Data.DefaultProvider, Telerik.Personalization.Data"
connectionStringName="DefaultConnection"
/>
</providers>
<systemPersonalizations>
<add
type="Telerik.Personalization.GenerelSetting,
Telerik.Personalization"
templatePath="~/Sitefinity/Admin/ControlTemplates/Personalization/Generel.ascx"
/>
<add
type="Telerik.Personalization.DashboardSetting,
Telerik.Personalization"
templatePath="~/Sitefinity/Admin/ControlTemplates/Personalization/Dashboard.ascx"
/>
<add
type="Telerik.Personalization.DashboardSetting,
Telerik.PageEditor"
templatePath="~/Sitefinity/Admin/ControlTemplates/Personalization/PageEditor.ascx"
/>
</systemPersonalizations>
</personalization>
|
Loading the Settings Screen in the Page My Preferences
The page My Preferences first queries the Personalization Component configuration to get the list of system setting screens. Once it gets the screen list,
it will iterate each item to check whether it can be visible. If it can become visible, it will store the control in a local list. The following shows the code that does that:
|
Copy Code |
|
List<IPersonalization> settings = new List<IPersonalization>(); foreach (PersonalizationPanelElement item in ConfigHelper.Handler.SystemPersonalizations)
{
Type type = TypeResolutionService.ResolveType(item.TypeName);
IPersonalization setting = Activator.CreateInstance(type);
if (setting.CanBecomeVisible)
{
setting.TemplatePath = item.TemplatePath;
settings.Add(setting);
}
}
|
Next, the page queries the ModuleManager to get the list of modules which supports personalized settings. The following shows the code:
|
Copy Code |
|
foreach (IWebModule module in ModuleManager.GetWebModulesValues())
{
IPersonalization setting = module as IPersonalization;
if (setting != null) // This will make sure the module supports Personalization
{
if (setting.CanBecomeVisible)
{
settings.Add(setting);
}
}
}
|
Once the list is created for the setting screens, the page will sort it by the SettingOrder property. Then, it will iterate the list to create the
left-side HyperLinkButtons and attach the Command event as the list index as command argument. So that when a button is clicked, we can load the
corresponding screen in the right side of the My Preference page.
IPersonalizedDashboard
The new Dashboard page of the admin section supports displaying recently modified items for both modules and system components. Personalization will allow to host other modules
and system components to show its recent items. These can be turned on/off from My Preferences -> Dashboard Settings screen. By implementing
this interface, the component will be able to host the recent items in the Dashboard page. Currently, the Blogs, Forums, News, and Lists module implement this interface. Figure 5
shows the signature of this interface:

Figure 5
|
Copy Code |
|
IDictionary<string, string>
DasboardSettings
|
A single module or system component could have multiple recently modified items displayed on the Dashboard page. For example, the Blogs module has Recent Posts
and Recent Comments displayed on the dashboard page. The class that implements this interface returns a dictionary in which the key is the settings key, and the
value is the text, which will be shown My Preferences -> Dashboard Settings screen. This property is iterated when building the checkbox list
in the Dashboard settings screen.
|
Copy Code |
|
IList<IPersonalizedDashboardItem> DasboardItems
|
A single module or system component can have more than one Recently Modified Items on the Dashboard. The DasboardItems property returns the actual UI
for the module or system component which will be hosted on the dashboard screen. This property is also iterated on the dashboard screen when loading the recent items.
IPersonalizedDashboardItem
This is the basic interface of the Recently Modified Items UI that is returned by DashboardItems from the IPersonalizedDashboard interface.
IPersonalizedDashboardItem interface has only one property, PersonalizationServiceUrl, that is set in the dashboard page. Figure 6 shows the
signature:

Figure 6
PersonalizedDashboardItem
This is a custom class which implements the IPersonalizedDashboardItem interface. Currently, all modules that have recent items shown on the dashboard
return this class to show the items. Figure 7 shows the signature of this class:

Figure 7
When returning an instance of the IPersonalizedDashboardItem class in DasboardItems of IPersonalizedDashboard, the
module or the system component is responsible for setting the ModuleName, Title, CloseSettingKey,
RowPerPageKey and the DataSource properties that will be initially shown. ModuleName is blank in case it is
a system component. The CloseSettingKey property makes the IPersonalizedDashboardItem object invisible from the dashboard page; also,
it turns off the appropriate check box of the Dashboard setting screen of My Preferences.
PersonalizationService
This is a wrapper of the PersonalizationManager to perform the Ajax Web Service call. Figure 8 shows the signatures:

Figure 8
|
Copy Code |
|
HideDashboardItem(string key)
|
This method turns off the Recently Modified Items section of an individual component. The key is the property CloseSettingKey of the
class PersonalizedDashBoardItem. This method is called when the user clicks the close button of an individual recent item section.
|
Copy Code |
|
HideMainSection()
|
This method turns off the Main Section visibility of the Dashboard Settings screen of My Preferences. This method is called when the user clicks the Hide this
Panel link of the Dashboard Page.
|
Copy Code |
|
HideFaq()
|
This method turns off the Show FAQs for the General Settings screen of My Preferences. This method is called when the user clicks Hide FAQ.
|
Copy Code |
|
ModuleConstants
|
Contains all the personalized module keys.
|
Copy Code |
|
GlobalContants
|
Contains all the personalized system keys.
See Also