Kentico ListInfo Object Types

ListInfo object types in Kentico - what is it, how and where it can be used.

All Kentico APIs are based on Info and InfoProvider classes that have methods to manage database entities (like UserInfo, UserInfoProvider, AccountInfo, AccountInfoProvider - system data classes or some custom data classes that are generated for your custom entities).

Like Info data object contains information about one data item, ListInfo data object returns information about a collection of data items that might come from different sources (tables). ListInfo objects can be used in UniGrid configuration xml file, or in Kentico REST service in case data should be retrieved from different database tables, or when some data aggregation needed and some complex SQL query is required to get this data list. 

Let's consider an example of the ListInfo class implementation and usage. For example, let's imagine our site has to display some gallery of products and possible colors (here is nothing to do with E-commerce, just display some product information on web site).  We built some custom module for managing the product and product colors entities and created appropriate custom classes BO.Product and BO.ProductColor. In BO.ProductColor we have foreign key ProductID to reference product that this color is related to. Also appropriate classes ProductInfo, ProductInfoProvider, ProductColorInfo and ProuductColorInfoProvider are generated.

So now we have to set up user interface for managing product and product colors. Creation of custom module can be found in the documentation. The first step is to create UI element to display products grid. The only additional requirement is to display number of colors related to that product in the grid. 

Obviously there is no straight way to set this 'Colors Count' column in the grid. Possible way is to create extender to the grid with some external source binding. But another effective way is using ListInfo object type. It gives more flexibility and allows pull appropriate data (even complex request) in one SQL query.

List info class is widely used in Kentico UniGrid definitions. One of such examples is grid that displays Booking Events list in admin. This grid uses cms.bookingeventlist object type that collects data from booking event page types and appropriate tree nodes information and displays attendees count. The class for cms.bookingeventlist is defined in CMS.EventManager namespace (CMS.EventManager.BookingEventListInfo) and has internal modifier.

ListInfo class, similar to other Info classes, is inherited form generic CMS.DataEngine​.AbstractInfo class and is internal. TYPEINFO property is defined and custom Object type name is set. To define list of data that is returned by class, GetDataQueryInternal method  is overridden. This method returns object of IDataQuery type
where appropriate sql query is set. 

Here is an example of ListInfo class for the scenario described above.

using System.Data;
using CMS;
using CMS.DataEngine;
using CMS.Base;

[assembly: RegisterObjectType(typeof(ProductsListInfo), ProductsListInfo.OBJECT_TYPE)]

namespace BO
    internal class ProductsListInfo : AbstractInfo<ProductsListInfo>
        /// <summary>
        /// Type information. 
        /// </summary>
        public static ObjectTypeInfo TYPEINFO = new ObjectTypeInfo("bo.productslist", ProductInfo.TYPEINFO)
            IDColumn = "ProductID",
            ModuleName = "BOProducts",            

        /// <summary>
        /// Object type
        /// </summary>
        public const string OBJECT_TYPE = "bo.productslist";

        public ProductsListInfo()
            : base(ProductsListInfo.TYPEINFO)

        public ProductsListInfo(DataRow dr)
            : base(ProductsListInfo.TYPEINFO, dr)

        /// <summary>
        /// Gets the data query for this object type
        /// </summary>
        protected override IDataQuery GetDataQueryInternal()
            return (IDataQuery)new DataQuery("bo.product", "selectallproducts");

SQL query bo.product.selectallproducts for the example will look like this:

FROM [BO_Product] JOIN 
(SELECT  P.ProductID as ColorProductID, count(P.ProductID) AS ColorsCount
 FROM  [BO_ProductColor] P 
 GROUP BY P.ProductID) C ON C.ColorProductID = [BO_Product].ProductID

So now when class and query is set up we can define UniGrid xml file:

<?xml version="1.0" encoding="utf-8" ?>
    <action name="edit" caption="$general.action$" fonticonclass="icon-edit" fonticonstyle="allow" ></action>
    <column source="ProductNumber" caption="Product number">
      <filter type="text" size="50"/>
    <column source="ProductName" caption="Name">
      <filter type="text" size="100"/>
    <column source="ColorsCount" caption="Colors count"/>
    <key name="DisplayFilter" value="true" />
  <objecttype name="bo.productslist" columns="ProductID, ProductNumber, ProductName, ColorsCount"/>
Please pay attention on bo.productslist object type using in UniGrid definition.

You can use defined bo.productslist object type in Kentico REST requests:
<site domain name>/rest/bo.productslist/?<parameters>