Kentico CMS 7.0 Developer's Guide

Customizing system objects with custom data or objects

Customizing system objects with custom data or objects

Previous topic Next topic Mail us feedback on this topic!  

Customizing system objects with custom data or objects

Previous topic Next topic JavaScript is required for the print function Mail us feedback on this topic!  

You can extend system objects in Kentico CMS by adding your own fields (i.e. properties).

 

To do this, create a custom data class containing the required fields and connect it to the appropriate system object. All standard system objects implement the IRelatedData interface, which allows you to connect any type of object:

 

Through the RelatedData property

Dynamically by handling the OnLoadRelatedData event

 

If the connected object implements the IDataContainer interface, the data stored in the custom fields can then be accessed as part of the system object via the API (GetValue and SetValue methods) or macro expressions.

 

Example

 

The following sections demonstrate how to extend the SiteInfo object, which represents sites in Kentico CMS. The example adds two custom properties for sites:

 

SiteOwner (string)

SiteValidUntil (DateTime)

 

Defining the custom data class

 

1. Open your web project in Visual Studio.

 

2. Create a new class named SiteRegistrationData.cs.

oPlace the class file into the App_Code folder if your Kentico CMS installation is a Web site project.

 

3. Write the code of the class.

oThe class must implement the IDataContainer interface.

oDefine your custom properties and all required IDataContainer members (as shown in the code below).

 
[C#]
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
using CMS.SettingsProvider;

 
public class SiteRegistrationData : IDataContainer
{
   #region "Variables"

 
  private string mSiteOwner = null;
  private DateTime mSiteValidUntil = DateTime.MinValue;

 
   #endregion
 

 
   #region "Properties"

 
  /// <summary>
  /// Gets or sets the name of the site owner.
  /// </summary>
  public string SiteOwner
   {
      get
       {
          return mSiteOwner;
       }
      set
       {
           mSiteOwner = value;
       }
   }

 
  /// <summary>
  /// Gets or sets the date until which the site is valid.
  /// </summary>
  public DateTime SiteValidUntil
   {
      get
       {
          return mSiteValidUntil;
       }
      set
       {
           mSiteValidUntil = value;
       }
   }

 
   #endregion
 
 
   #region "IDataContainer members"

 
  /// <summary>
  /// Gets a list of column names.
  /// </summary>
  public List<string> ColumnNames
   {
      get
       {
          return new List<string>() { "SiteOwner", "SiteValidUntil" };
       }
   }
 
  /// <summary>
  /// Returns true if the class contains the specified column.
  /// </summary>
  /// <param name="columnName"></param>
  public bool ContainsColumn(string columnName)
   {
      switch (columnName.ToLower())
       {
          case "siteowner":
          case "sitevaliduntil":
              return true;
 
          default:
              return false;
       }
   }

 
  /// <summary>
  /// Gets the value of the specified column.
  /// </summary>
  /// <param name="columnName">Column name</param>
  public object GetValue(string columnName)
   {
      switch (columnName.ToLower())
       {
          case "siteowner":
              return mSiteOwner;

 
          case "sitevaliduntil":
              return mSiteValidUntil;

 
          default:
              return null;
       }
   }

 
  /// <summary>
  /// Sets the value of the specified column.
  /// </summary>
  /// <param name="columnName">Column name</param>
  /// <param name="value">New value</param>
  public bool SetValue(string columnName, object value)
   {
      switch (columnName.ToLower())
       {
          case "siteowner":
               mSiteOwner = (string)value;
              return true;

 
          case "sitevaliduntil":
               mSiteValidUntil = (DateTime)value;
              return true;

 
          default:
              return false;
       }
   }

 
  /// <summary>
  /// Returns a boolean value indicating whether the class contains the specified column.
  /// Passes on the specified column's value through the second parameter.
  /// </summary>
  /// <param name="columnName">Column name</param>
  /// <param name="value">Return value</param>
  public bool TryGetValue(string columnName, out object value)
   {
      switch (columnName.ToLower())
       {
          case "siteowner":
               value = mSiteOwner;
              return true;

 
          case "sitevaliduntil":
               value = mSiteValidUntil;
              return true;

 
          default:
               value = null;
              return false;
       }
   }
 
   /// <summary>
  /// Gets or sets the value of the column.
  /// </summary>
  /// <param name="columnName">Column name</param>
  public object this[string columnName]
   {
      get
       {
          return GetValue(columnName);
       }
      set
       {
           SetValue(columnName, value);
       }
   }

 
   #endregion
 
}

 

Connecting the custom data class to the system object

 

You need to bind the custom SiteRegistrationData class to the SiteInfo object. The example uses the OnLoadRelatedData event, which you can handle for specific object types, including SiteInfo objects. This type of binding is dynamic, which means that the system loads the data only when it is requested.

 

1. Create a new class file in the App_Code folder (or Old_App_Code if your project was installed as a web application).

 

2. Delete the default class declaration and instead extend the CMSModuleLoader partial class.

 

3. Create a new class inside the CMSModuleLoader that inherits from CMSLoaderAttribute.

 

4. Add the attribute defined by the internal class before the declaration of the CMSModuleLoader partial class.

 

5. Override the Init method inside the attribute class, and assign a handler to the SiteInfo.TYPEINFO.OnLoadRelatedData event.

 

6. Define the handler method for the OnLoadRelatedData event:

oThe handler must return an instance of your custom data class (with appropriate values assigned to the class's fields).

 

[C#]

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

 
using CMS.SettingsProvider;
using CMS.SiteProvider;

 
[SystemObjectCustomizationLoader]
public partial class CMSModuleLoader
{
  /// <summary>
  /// Custom attribute class for the CMSModuleLoader.
  /// </summary>
  private class SystemObjectCustomizationLoaderAttribute : CMSLoaderAttribute
   {
      /// <summary>
      /// Called automatically when the application starts.
      /// </summary>
      public override void Init()
       {
          // Assigns a handler to the OnLoadRelatedData event of the SiteInfo object type
          SiteInfo.TYPEINFO.OnLoadRelatedData += new TypeInfo.ObjectLoadRelatedDataEventHandler(SiteInfo_OnLoadRelatedData);
       }
     
      /// <summary>
      /// Handler method for the OnLoadRelatedData event of the SiteInfo class.
      /// Gets the related data from the custom storage class (must implement the IDataContainer interface).
      /// </summary>
      static object SiteInfo_OnLoadRelatedData(BaseInfo infoObj)
       {          
          SiteRegistrationData siteData = new SiteRegistrationData();

 
           siteData.SiteOwner = "John Smith";
           siteData.SiteValidUntil = DateTime.Now.AddDays(1);

 
          return siteData;
       }
   }
}

 

Result

 

You can now work with the custom fields of site objects using the API.

 

For example, open your website in CMS Desk and add the following code into the ASCX layout of one of your website's pages:

 

<asp:Label runat="server" id="lblSiteInfo" />

<script runat="server">

protected void Page_PreRender(object sender, EventArgs e)

 {

   CMS.SiteProvider.SiteInfo currentSite = CMSContext.CurrentSite;

 

   this.lblSiteInfo.Text = String.Format("Site '{0}' is valid until {1} and owned by {2}.", currentSite.DisplayName, currentSite.GetValue("SiteValidUntil"), currentSite.GetValue("SiteOwner"));

 }

</script>

 

The GetValue method allows you to retrieve the data stored in the custom properties, just like with native fields of the SiteInfo object.

 

The label control displays information on the page in the following format:

 

Site 'Corporate Site' is valid until 1/15/2013 1:00:00 PM and owned by John Smith.

 

Accessing properties through macros:

 

You can also load the values of custom properties using macro expressions. For example:

 

1.Add the Static text web part to the page (via the Design tab).

2.Copy the following text into the web part's Text property.

 

<ul>

 <li>Site: {% CurrentSite.SiteDisplayName %}</li>

 <li>Valid until: {% CurrentSite.SiteValidUntil %}</li>

 <li>Owned by: {% CurrentSite.SiteOwner %}</li>

</ul>

 

The web part displays a list of information about the current website, including the values of the custom fields.