Custom Properties

advertisement
Custom Properties
Problem
DNN has the ability to store custom properties for a variety of entities in the platform.
This capability has traditionally only been available to developers through a common API
pattern. It should be possible to allow end users to create and manage custom properties
as well.
Background
Custom properties are typically stored in a Settings table which is directly related to a
platform entity. A Settings table contains key/value pairs as individual items, and also
stores audit information for each item including the user and datetime of when the item
was created or last modified. Setting names must be unique for an entity. Setting values
are stored as strings ( nvarchar(max) is the optimal database column definition as it does
not constrain the size of string, nor the localized format ) and if the data is a non-string
datatype or rich object, it is up to the developer to implement their own serialization
scheme. Custom properties are serialized during import and export to allow for
portability.
The API for custom settings is exposed in a consistent manner which allows developers
to easily save and retrieve properties using a simple, intuitive, and high performance
programming interface.
Ie.
public Hashtable GetTabSettings(int tabId)
public void DeleteTabSetting(int tabId, string settingName)
public void UpdateTabSetting(int tabId, string settingName, string
settingValue)
Goals




We do not want to change the public API pattern that developers use to
save/retrieve custom properties
We want end users to be able to create and manage some custom properties
through the user interface
Not all properties should be exposed through the user interface
We want the solution to be simple, lightweight, and not cause upgrade challenges
Solution
We need a way to define custom properties. The recommended industry approach is to
use the concept of “metadata” to define custom properties. The DNN platform already
uses a “metadata” approach in a number of areas. In fact, the existing custom Profile
properties matches our business requirements very closely and contains existing code we
can leverage for the display and entry of custom properties.
A MetaData table can be related to an existing Settings table so that the API for storing
and retrieving custom property values are unaffected. The reason for using a separate
MetaData table rather than simply adding the MetaData fields to the Settings table is
because we want to abstract the definition from the data and because there is a business
need to define “global” MetaData which can relate to multiple entities.
The MetaData table will contain the following fields:
FieldName
ID
DataType
int
Nullable
no
EntityID
int
yes
SettingName
nvarchar(50)
no
CategoryName
nvarchar(50)
no
Title
nvarchar(50)
no
Description
nvarchar(255)
yes
DataType
nvarchar(50)
no (default=string)
DefaultValue
nvarchar(255)
yes
MaxLength
int
no (default=0)
ViewOrder
int
no
Comment
Primary Key.
Identity.
Links to the entity
similar to the
Settings table. If ID
is null it means that
the MetaData item
is a “global”
definition and could
be applied to ANY
entity
Key which
corresponds to an
item in the Settings
table
Method to group
items in the user
interface
Title of field to
display in the UI
Description of field
to be used as field
level help text
Used for input
validation in UI –
supports a limited
number of values
( ie. text, integer,
date )
Optional default
value for field. Can
also be a comma
delimited list of
allowable values
that would be
displayed in a
dropdownlist in the
UI ( ie.
Red,White,Blue )
Optional maximum
length of the input
value
Used in conjunction
with
CategoryName to
ReadOnly
bit
no (default=0)
Visible
bit
no (default=1)
CreatedByUserID
CreatedOnDate
LastModifiedByUserID
LastModifiedOnDate
int
datetime
int
datetime
no
no
no
no
enable you to
specify the order of
items within a
category
Specifies if the item
is read only in the
UI
Indicates whether
the item should be
surfaced in the UI
or should be
hidden.
Audit
Audit
Audit
Audit
We will not worry about granular permissions related to Settings in the initial
implementation. Data entry security will be constrained to those people who can view the
specific administrative tab in the user interface which relates to the entity. And publishing
will depend on the module or skin object surfacing the Setting value.
Some new API methods would need to be created to interact with the new MetaData
table.
public list GetTabSettingsMetaData(int tabId)
public void AddTabSettingMetaData(TabSettingMetaDataInfo
TabSettingMetaData)
public void UpdateTabSettingMetaData(TabSettingMetaDataInfo
TabSettingMetaData)
public void DeleteTabSettingMetaData(TabSettingMetaDataInfo
TabSettingMetaData)
A user interface will need to be created where an administrator can create/modify/remove
custom properties, as well as edit/save Setting values:
Only those Settings items which have an associated MetaData record that is flagged as
Visible would be surfaced through the UI. If a module developer wants their Settings to
be manageable through the UI, they would need to create MetaData records during
installation.
Add – you can add a Metadata record as long as a Metadata with the Name does not
already exist. If no Metadata record exists, but a Settings record exists with the Name, it
will ask if you wish to associate the MetaData with the Setting.
Delete – when you delete a Metadata record it will not delete the related records in the
Settings table unless the user specifies that they wish to do so.
Setting values are automatically serialized during import/export of site/page templates.
We will also need to enhance the platform so that the MetaData info is also serialized
during import/export.
Localization
For consistency, the localized values for UI metadata fields such as Category, Title, and
Description will be stored in the core RESX file where the other localized UI values are
stored for the administrative user interface.
Usage
The usage of custom properties will depend on the entity. The storage of Settings values
have not changed, so the API for using Settings will stay the same in skins and modules.
For example, TabSettings can be used within a skin using the following code:
<%= PortalSettings.ActiveTab.TabSettings[“SettingName”] %>
If you need more elaborate logic for utilizing Settings then you can build a module or
skin object which has the full capabilities of ASP.NET.
On upgrade, we will not automatically create any MetaData records, which means that
any Settings items that already exist will NOT be surfaced through the UI automatically.
Scope
We will initially implement this in the Page Settings area. And once we are satisfied with
the implementation, we will implement this in Host, Site, Module, and Role management
areas.
Business Challenge
None. Low Risk, High Reward.
References
http://www.dotnetnuke.com/Community/CommunityVoice/cid/138568.aspx#138568.aspx
http://www.dotnetnuke.com/Resources/Forums/forumid/108/threadid/435773/scope/posts
/threadpage/1.aspx
Download