Loading

Consume REST service on the server

In my previous post I showed you how to consume REST service on the client side. Today I want to share my experience of consumption it on the server side.

Sometimes there are situation when you need to get some data from Kentico application by either third party application, or, even, another Kentico application. Of course, you might think about connection directly to it's database, using staging, etc. But direct access to database might give third party app more access, than we'd like, staging either requires manual action to stage only object you need, or automatic staging will stage more than you really, etc. 

So after a few minutes of analysis of the requirements, I decided to use Kentico REST service in order to get needed data. The benefit of this approach is that I can control from within the Kentico what object could be accessed and whether this only read or read/write access. This could be configured either in REST settings or with role.

Role is enough flexible approach as I can allow read/write permission to one object, but read only to another. With this approach you need to setup Basic authentication for REST service and create user account you are going to use for REST service. Now you have to create a role and configure the least permissions for it and add just created user account to it. In my case I need to read all user accounts. So I've created RestUserReader role and granted it with Read permission for User module:
 


Also I've configured REST service to use Basic authentication and allowed to read CMS.User objects only, but the last one is not applicable when you need to read one object and read/write another, as mentioned above. So my settings look like this:
 

So now we are ready to write code within any .NET application, which will read users from Kentico. Actually Kentico documentation contains appropriate article, which shows us how to achieve this, but I don't like the fact that they are getting string object, meanwhile REST service always returns either XML or JSON. So I've decided to utilize HttpClient with Media Type Formatters, those are already in pipeline, in order to automatically deserialize response to a particular strongly typed object. Here my code sample:
 

using (var client = new HttpClient())

        {

            client.BaseAddress = new Uri(this.URL);

            client.DefaultRequestHeaders.Accept.Clear();

            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));



            var byteArray = Encoding.ASCII.GetBytes(string.Format("{0}:{1}", this.username, this.pass));

            client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));



            client.Timeout = new TimeSpan(0, 0, 30);



            Task<HttpResponseMessage> t = client.GetAsync(this.getUsersURLPath);

            HttpResponseMessage response = t.Result;

            if (response.IsSuccessStatusCode)

            {

                Task<Rootobject> tsk = response.Content.ReadAsAsync<Rootobject>();

                Rootobject responseData = tsk.Result;

                return responseData.cms_users.FirstOrDefault().CMS_User;

            }

        }



You might notice the weird way to access the actuall list of users I was looking for, as well strange type Rootobject. Let me explain...

If you'll request data from Kentico REST like this:
http://domain.com/rest/cms.user?topn=1&columns=username,fullname,firstname,lastname&format=json

You'll find response message also formatted in a bit weird way:
{"cms_users": 
    [
        {"CMS_User": 
            [
                {"fullname":"A Abcd","firstname":"A","username":"laberna","lastname":"Abcd"}
            ]
        },{
        "TotalRecords": 
            [
                {"TotalRecords":"1"}
            ]
        }
    ]
}
I believe Kentico team ahs really good reason to format data like this, but unfortunately, I coundn't recognize it yet. 

Anyway, when reading data from HttpResponseMessage object, Media Type Formatter requires to specify the type of the object we are expecting to read from the response. To be honest with you, I really had hard times to build that object on my own. But suddenly I've recollected one sweet feature of Visual Studio: Paste Specials -> Paste JSON as Classes, so I simply copied JSON from the response (like above) and Visual Studio built following objects for me:
 

    class Rootobject

    {

        public Cms_Users[] cms_users { get; set; }

    }



    class Cms_Users

    {

        public CMS_User[] CMS_User { get; set; }

        public Totalrecord[] TotalRecords { get; set; }

    }



    class CMS_User

    {

        public string fullname { get; set; }

        public string firstname { get; set; }

        public string username { get; set; }

        public string email { get; set; }

        public string lastname { get; set; }

    }



    class Totalrecord

    {

        public string TotalRecords { get; set; }

    }



So that was the a final step and now you should be able to get users, or any other object you need, consuming REST service. It works preatty well for me: I'm reading 5 columns of ~25K records in JSON format, which turned to be less than 4 MB, which, in my opinion, is fine to be trasfered over HTTP. 

Hope you will find this post useful. Let us know what you think about this or feel free to ask questions if any.