Cloud Data Source

#Custom software development #.NET

SHARE

 
Recently Kentico presented cloud solution for content management, which works great for client side and MVC applications. But what about old and nice Portal Engine Kentico sites? - In this post, I’d like to walk you through development process of Kentico data source web part that will load content from the cloud.

 

Our goal is getting content from Kentico Cloud and presenting it on a page. In order to do so the first thing we need is Kentico Cloud account. Once you register/sign in create some content type and a couple of content items.

Next step would be installation of Kentico Deliver SDK: open your solution in Visual Studio, open Nuget Package Manager and search for KenticoCloud.Deliver package and install it.

So now we are in a good shape to start actual development. I’m not going to focus on data source web part development, as you can find this in Kentico Documentation. I’m going to focus on getting data from a cloud and processing it.

Kentico Deliver API is quite simple and obvious: you have to initiate DeliverClient and call GetItemsAsync method of it to get some data. In order to specify what data you want to receive you have to pass a list of IFilter objects. There are a couple of filters like InFilter, OrderFilter, EqualsFilter, etc., those allow us to filter out content we don’t need, order it or split into multiple pages. Here is a sample of Delivery client usage:


private readonly DeliverClient client = new DeliverClient("project_id");

var filters = new List<IFilter> {

  new InFilter("system.type", ContentType)),

                new Order("elements."+OrderBy, OrderDirection)

            };

client.GetItemsAsync(filters);

I think everyone agrees that this looks very simple, however there are some challenges when doing this in a user control. First challenge is that DeliveryClient does async call, which does not work well in Web Forms. We can work around this using System.Threading.Task:


var data = System.Threading.Tasks.Task.Run(() => client.GetItemsAsync(filters)).Result.Items;

The next challenge is to convert received data to some structured collection. We receive a collection of dynamic objects. It is possible to process them using reflection: get a list of properties and their values. But I’ve chosen much easier way – using data table:


var content = BuildDataTable(Columns);

 

        foreach(var a in data)

        {

            var res = content.NewRow();

            foreach (var col in Columns)

            {

                res[col] = a.GetString(col.ToLower());

            }

            content.Rows.Add(res);

        }

…

private DataTable BuildDataTable(string [] columns)

    {

        var dt = new DataTable();

        dt.Columns.AddRange(columns.Select(x => new DataColumn(x)).ToArray());

        return dt;

    }

As you might notice we used collection of columns to build a data table. This puts a constraint onto our web part: Columns field is required. I don’t see this to be an issue as specifying Columns for any listing/viewer web part is best practice and it improves performance.

So, let’s put all those pieces together and build a web part.

According to Kentico documentation data source web part consists of two user controls: one implements CMSBaseDataSource and another – CMSAbstractWebPart.

Let’s start from CMSBaseDataSource. In addition to the code from documentation we need to add properties we will use for filtering content coming from a Cloud. I’ve added just a couple of very basic properties:


public string ContentType { get; set; }

 

    public OrderDirection OrderDirection { get; set; }

 

    public string[] Columns { get; set; }

You are more than welcome to add any other property you may need, e.g. Skip, Take, etc. By the way CMSBaseDataSource class already contains properties like OrderBy, WhereCondition, etc.

Also, we need an instance of Delivery client:


private readonly DeliverClient client = new DeliverClient("project_id");

You can find project ID by opening your project in Kentico Cloud and navigating to Development tab in the left pane. Also, it would be better to store project ID in the web.config, Kentico custom setting or even as web part setting.

Last step with this control is implementation of GetDataSource


protected override object GetDataSourceFromDB()

    {

        // Initializes the data properties according to the filter settings

        if (SourceFilterControl != null)

        {

            SourceFilterControl.InitDataProperties(this);

        }

 

        var filters = new List<IFilter> {

                new Order("elements."+OrderBy, OrderDirection)
            };
 
        if(!string.IsNullOrEmpty(ContentType))
        {
            filters.Add(new InFilter("system.type", ContentType));
        }
        if (Columns == null || Columns.Length <= 0)
        {
            return null;
        }
        else
        {
            filters.Add(new ElementsFilter(Columns));
        }
        if(TopN > 0)
        {
            filters.Add(new LimitFilter(TopN));
        }
 
        var data = System.Threading.Tasks.Task.Run(() => client.GetItemsAsync(filters)).Result.Items;
        //.Select(x => x.Elements);
 
        var content = BuildDataTable(Columns);
 
        foreach(var a in data)
        {
            var res = content.NewRow();
            foreach (var col in Columns)
            {
                res[col] = a.GetString(col.ToLower());
            }
            content.Rows.Add(res);
        }
 
        return content;
    }
 
    private DataTable BuildDataTable(string [] columns)
    {
        var dt = new DataTable();
        dt.Columns.AddRange(columns.Select(x => new DataColumn(x)).ToArray());
        return dt;
    }
 

Now we can switch to web part implementation. All we need is adding appropriate properties and passing their values to the child control we’ve just built. So here are properties:


public string OrderBy
    {
        get
        {
            return ValidationHelper.GetString(this.GetValue("OrderBy"), "");
        }
        set
        {
            this.SetValue("OrderBy", value);
            CloudDataSource.OrderBy = value;
        }
    }
 
    public string Columns
    {
        get
        {
            return ValidationHelper.GetString(this.GetValue("Columns"), "");
        }
        set
        {
            this.SetValue("TopN", value);
            CloudDataSource.Columns = value.Split(',').Select(x => x.Trim()).ToArray();
        }
    }
 
    public string ContentType
    {
        get
        {
            return ValidationHelper.GetString(this.GetValue("ContentType"), "");
        }
        set
        {
            this.SetValue("ContentType", value);
            CloudDataSource.ContentType = value;
        }
    }
 

And we need to pass them to an actual data source in the SetupControl method like this:


protected void SetupControl()
    {
        if (this.StopProcessing)
        {
        }
        else
        {
            this.CloudDataSource.OrderBy = this.OrderBy;
            this.CloudDataSource.Columns = this.Columns.Split(',').Select(x => x.Trim()).ToArray();
            this.CloudDataSource.ContentType = this.ContentType;
            this.CloudDataSource.FilterName = (string)this.GetValue("WebPartControlID");
            this.CloudDataSource.SourceFilterName = this.FilterName;
        }
    }

Last step in this process is registering of a web part in Kentico. While adding properties to the web part make sure Columns property is required. Once this is completed you’re ready to start using the data source with viewer web part, get content from the Cloud and presenting it on a page with a transformation. I’ve used Text/XML transformation with a macro for getting fields – just put {%field_name%} into the transformation. You may use any column name specified in Column property of a data source. The intension of this post is showing the simplicity of Deliver SDK and Cloud usage. Current implementation is very basic and requires extra logic for data verification, exception handling, etc. in order to use it on the live site. Also it states that you don’t need to rebuild your application with MVC or any other platform in order to start using Kentico Cloud, or, even if you plan to move there, it will make migration much smoother.

Please feel free to leave your feedback or share your experience with similar problems - we highly appreciate this!

Author

Check other articles

Bitsorchestra
5 5

What our clients say

Bits Orchestra team are outstanding developers​. They listen carefully to our business needs and easily turns our business objectives into a well thought out and executed development effort. Roman is very bright and definitely the most capable developer that has worked on our site. He is not only a Kentico expert but has successfully tackled other complicated development assignments demonstrating expertise in both front and backend development. Roman takes initiative to suggest enhancements that make site maintenance easier while improving the customer experience. The team is very responsive to our work requests and has great follow up. They have also worked very business partners and this has reflected positively on our company. Roman is a true partner for us and a tremendous asset to our organization. We will continue to work with them and would highly recommend Roman and his team for your development needs. He and his team will exceed your expectations!
 Alan Lehmann
Alan Lehmann
President at In energy sector

What our clients say

The Bits Orchestra team does excellent work. They are always available and I appreciate our frequent calls and screen-shares together. Their dedication to the projects and knowledge of Kentico is outstanding. They truly care about the quality of their work, and became a part of our team easily!
Shena Lowe
Shena Lowe
Managing Partner at Consensus Interactive

What our clients say

We hired Roman for a Kentico analysis project and have been very satisfied. He is very skilled and professional. We are looking to hire him and his team again on future projects.
Sylvain Audet
Sylvain Audet
CEO at MyDevPartner.com

What our clients say

Roman and team have taken over an existing Kentico EMS site for a large US Oil Company. So far, they have handled every single request that we have thrown at them and these were diverse, challenging, often bespoke, usually urgent and almost daily, over the last 11 months. Their work is of an extremely high quality, they are capable, quick and we have great confidence in the support that we are getting.
Jon Hollis
Jon Hollis
Head of Web Development at confidential

What our clients say

Bits Orchestra team was very helpful, they had a good understanding of the brief and deep knowledge of the system. They were always keen to provide advice and recommendations that benefit the project substantially.
Ramon Lapenta
Ramon Lapenta
Senior Front End Developer at Cyber-Duck Ltd