REST API v3 .NET Examples

Version 2

    I had the opportunity to recently work with the Jive V3 Rest API populating profile information using .NET.

     

    Most of it was pretty strait forward except for updating the profile Image.

     

    However after a bit of rooting around on the web I was able to accomplish it.

     

    Here are code samples for .NET that may make working with the API easier.

     

    License

    This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

     

    This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

     

    Environment Info

    This example uses

    • The .NET Framework 4
    • Unfederated account which has elevated privileges
      • Thanks John Larson!

     

    Data objects

    Data Objects make serializing / deserializing easier

      

    Indvidual People

    The following data objects are for working with individual profiles.

    public class JivePersonObject  
    {

            public int id {get; set;}     

            public string displayName { get; set; }

            public JivePersonInfo jive { get; set; }   

            public List<JiveEmails> emails { get; set;}

            public JiveName name { get; set; }

     

            public JivePersonObject() { }

    }

     

    public class JivePersonInfo

    {

            public JivePersonInfo() { }

            public string username { get; set; }

            public JiveProfiles[] profile { get; set; }

            public bool federated { get; set; }

            public bool enabled { get; set; }  
    }//end class


    public class JiveProfiles

    {

            public JiveProfiles() { }

            public string value { get; set; }

            public string jive_label { get; set; }

    }//end class

     

    public class JiveEmails  
    {

            public JiveEmails(){}

            public string value { get; set; }

            public string type { get; set; }

            public string jive_label { get; set; }

            public string primary { get; set; }  
    }

        
    public class JiveName

    {

            public JiveName(){}

            public string familyName { get; set; }

            public string formatted { get; set; }

            public string givenName { get; set; }  
    }

     

    All People

    The following data objects are for working with all people.

    public class JivePersonList  
    {

            public JivePersonList() { }

            public List<JivePersonObject> list { get; set;}

            public JiveLinks links { get;set; } 
    }

    public class JiveLinks  
    {    

          public JiveLinks() { }

          public string next { get; set; }  
    }

     

    API Example Code

     

    Get All People

    Note in this example I am filtering for specific fields you may need to adjust the filter to meet your needs

            /// <summary>

            /// Gets a list of all users in jive platform

            /// </summary>

            /// <returns>a list of users from jive</returns>

            public List<JivePersonObject> GetUsers()

            {  

                TraceSource ts = WebServiceUtility.InitalizeTrace("Get all users from Jive", WebServiceUtility.SERVER_LOG);

               

                int startIndex = 0;

                string jivePeopleUrl = ConfigurationManager.AppSettings["JiveURI"];

                jivePeopleUrl += "api/core/v3/people";

                jivePeopleUrl += "?count=100&startIndex=" + startIndex;

                jivePeopleUrl += "&fields=ID,displayName,jive.profile,jive.username,jive.federated,jive.enabled,emails,name,federated";

     

                List<JivePersonObject> deserialPersonList = new List<JivePersonObject>();

                JivePersonList tempDeserialPersonList = new JivePersonList();

                int loopCount = 0;//prevent endless loop

     

                tempDeserialPersonList = getUsersPerPage(jivePeopleUrl);

     

                while (loopCount <= 2000 && tempDeserialPersonList.list != null )

                {

                    foreach (JivePersonObject deserialPerson in tempDeserialPersonList.list)

                    {                  

                        if (deserialPerson.jive.profile == null)                      
                             deserialPerson.jive.profile = new JiveProfiles[0];

                      
                        deserialPersonList.Add(deserialPerson);

                    }

                   

                    if (tempDeserialPersonList.links.next != null)

                    {

                        ts.TraceInformation("Loop Count: " + loopCount);

                        ++loopCount;

     

                        startIndex = loopCount * 100;

                        jivePeopleUrl = ConfigurationManager.AppSettings["JiveURI"];

                        jivePeopleUrl += "api/core/v3/people";

                        jivePeopleUrl += "?count=100&startIndex=" + startIndex;

                        jivePeopleUrl += "&fields=ID,displayName,jive.profile,jive.username,jive.federated,jive.enabled,emails,name,federated";

     

                        tempDeserialPersonList = getUsersPerPage(jivePeopleUrl);

                    }

                    else

                        break;

                }//end while

     

                ts.TraceInformation("User Count: " + deserialPersonList.Count);

     

                return deserialPersonList;

            }//end GetUsers

     

            /// <summary>

            /// Gets a list of users in Jive for a specified URL

            /// </summary>

            /// <param name="jivePeopleUrl">a URI with specified Paging and filters</param>

            /// <returns>An object which contains a list of people returned from Jive</returns>

            public JivePersonList getUsersPerPage(string jivePeopleUrl)

            {

                TraceSource ts = WebServiceUtility.InitalizeTrace("Get users from Jive by Page", WebServiceUtility.SERVER_LOG);

                JivePersonList deserialPersonList = new JivePersonList();

     

                string jiveResponse = string.Empty;

                try

                {

                    using (WebClient client = new WebClient())

                    {

                        ts.TraceInformation("setting credentials");

     

                        string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(ConfigurationManager.AppSettings["JiveAccount"] + ":" + ConfigurationManager.AppSettings["JivePassword"]));

                        client.Headers[HttpRequestHeader.Authorization] = "Basic " + credentials;

                        client.Headers[HttpRequestHeader.Accept] = "application/json";

     

                        ts.TraceInformation("getting response");       

                        jiveResponse = client.DownloadString(jivePeopleUrl);                  


                        ts.TraceInformation("response recieved, Raw " + jiveResponse);

     

                        //invalid jason response... https://developers.jivesoftware.com/community/thread/2153  

                        jiveResponse = jiveResponse.Replace("throw 'allowIllegalResourceCall is false.';", String.Empty);                  

     

                        ts.TraceInformation("Deserializing Response");

                        var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();

                        deserialPersonList = serializer.Deserialize<JivePersonList>(jiveResponse);

                    }//end client                  

                }

                catch (Exception ex)

                {

                    ts.TraceEvent(TraceEventType.Error, 1, ex.StackTrace);

                    throw new System.ServiceModel.Web.WebFaultException<string>(ex.Message, HttpStatusCode.InternalServerError);

                }

     

                return deserialPersonList;

            }//end getUsersPerPage

     

    Get a Single Person

           /// <summary>

            /// Gets a user record for a specific user ID. Note is not able to update Admin accounts.

            /// </summary>

            /// <param name="id">Jive ID of the target user</param>

            /// <returns>Returns a Data Object representing the Jive Person</returns>

            public JivePersonObject GetUser(string id)

            {

                TraceSource ts = WebServiceUtility.InitalizeTrace("Get single users from Jive", WebServiceUtility.SERVER_LOG);

                int userId = 0;

     

                #region Input validation

                if(!(int.TryParse(id, out userId)))

                    throw new System.ServiceModel.Web.WebFaultException<string>("Invalid ID", HttpStatusCode.BadRequest);

     

                if(userId < 1)

                    throw new System.ServiceModel.Web.WebFaultException<string>("Invalid ID", HttpStatusCode.BadRequest);

                #endregion

     

                string jivePeopleUrl = ConfigurationManager.AppSettings["JiveURI"];

                    jivePeopleUrl += "api/core/v3/people/";

                    jivePeopleUrl += id;

                    jivePeopleUrl += "?fields=ID,displayName,jive.profile,jive.username";

     

                string jiveResponse = string.Empty;

     

                JivePersonObject deserialPerson = new JivePersonObject();

                try

                {

                    using(WebClient client = new WebClient())

                    {

                        ts.TraceInformation("setting credentials");

                        string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(ConfigurationManager.AppSettings["JiveAccount"] + ":" + ConfigurationManager.AppSettings["JivePassword"]));

                        client.Headers[HttpRequestHeader.Authorization] = "Basic " + credentials;

                        client.Headers[HttpRequestHeader.Accept] = "application/json";

                       

                        ts.TraceInformation("getting response");

                        jiveResponse = client.DownloadString(jivePeopleUrl);

     

                        ts.TraceInformation("response recieved, Raw " + jiveResponse);

     

                        //invalid json response... https://developers.jivesoftware.com/community/thread/2153

                        jiveResponse = jiveResponse.Replace("throw'allowIllegalResourceCall is false.';", String.Empty);

     

                        var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();

     

                        deserialPerson = (JivePersonObject)serializer.Deserialize(jiveResponse, typeof(JivePersonObject));

     

                        #region Debug

                        ts.TraceInformation("returned ID: " + deserialPerson.id);

                        ts.TraceInformation("returned User Name: " + deserialPerson.jive.username);

                        ts.TraceInformation("returned Display Name: " + deserialPerson.displayName);

     

                        if (deserialPerson.jive.profile != null)

                        {

                            ts.TraceInformation("returned Profile size: " + deserialPerson.jive.profile.Length);

     

                            foreach (JiveProfiles profile in deserialPerson.jive.profile)

               {                          
                   ts.TraceInformation("  Profile Label: " + profile.jive_label + " value: " + profile.value);

                            }

                        }

                        #endregion 

                    }//end client                      
                }

                catch (Exception ex)

                {

                    ts.TraceEvent(TraceEventType.Error, 1, ex.StackTrace);

                    throw new System.ServiceModel.Web.WebFaultException<string>(ex.Message, HttpStatusCode.InternalServerError); 
                }

                return deserialPerson;

            }//end GetUser


    Update a person

            /// <summary>

            /// Updates the specified person object with the specified values

            /// </summary>

            /// <param name="person">Object to be updated</param>

            /// <returns>The updated person JSON string</returns>

            public string updateUserProfile(JivePersonObject person)

            {

                TraceSource ts = WebServiceUtility.InitalizeTrace("Updare users in Jive", WebServiceUtility.SERVER_LOG);

               

                //there are cases where managers are not fully loaded skip them

                if (person.name.givenName == null)

                    return "Skipped";

     

                var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();

                string personJSON = serializer.Serialize(person);

     

                personJSON = personJSON.Replace("True", "true");//bug in Jive API fix the tense otherwise Jive will return a 500

                personJSON = personJSON.Replace("null", "\"\"");//serializer sets value as null instead of empty string, adjust string

     

                ts.TraceInformation("Serialized Person: " + personJSON);

     

                string jivePeopleUrl = ConfigurationManager.AppSettings["JiveURI"];

                jivePeopleUrl += "api/core/v3/people/";

                jivePeopleUrl += person.id;

     

                string response = string.Empty;

               try

                {

                    using (WebClient client = new WebClient())

                    {

                        ts.TraceInformation("setting credentials");

                        string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(ConfigurationManager.AppSettings["JiveAccount"] + ":" + ConfigurationManager.AppSettings["JivePassword"]));

                        client.Headers[HttpRequestHeader.Authorization] = "Basic " + credentials;

                        client.Headers[HttpRequestHeader.Accept] = "application/json";

                        client.Headers[HttpRequestHeader.ContentType] = "application/json";

     

                        response = client.UploadString(jivePeopleUrl, "PUT", personJSON);

                        ts.TraceInformation("Response: " + response);

                    }//end client                   

                }

                catch (Exception ex)

                {

                    ts.TraceEvent(TraceEventType.Warning, 1, ex.StackTrace);

                    return ex.Message;

              }

     

                return response;

            }//end updateUserProfile


    Upload Profile Image

                    Note this code can be modified to post an image to the image endpoint

                                    Change the URL

                                    Change code after set profile image to do something with the uploaded image

            /// <summary>

            /// Uploads the specified image for the specified person in next avilable photo slot

            /// </summary>

            /// <param name="person">Must contain the Jive ID as a property of the person</param>

            /// <param name="imageBits">Byte Array that contains the jpg image that should be uploaded</param>

            /// <returns>Temporary Image Object JSON string</returns>

            public string updateImage(JivePersonObject person, byte[] imageBits)

            {

                TraceSource ts = WebServiceUtility.InitalizeTrace("Update users Profile Image", WebServiceUtility.SERVER_LOG);

     

                //upload image

                string jivePictureUrl = ConfigurationManager.AppSettings["JiveURI"];

                jivePictureUrl += "api/core/v3/profileImages/temporary";

                //jivePictureUrl += "api/core/v3/images";

     

                string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(ConfigurationManager.AppSettings["JiveAccount"] + ":" + ConfigurationManager.AppSettings["JivePassword"]));

     

                string boundary = "----------------------" + DateTime.Now.Ticks.ToString("x");

     

                //code leveraged from http://www.paraesthesia.com/archive/2009/12/16/posting-multipartform-data-using-.net-webrequest.aspx

                string HeaderTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n";

                string formKey = "filename";

                string header = String.Format(HeaderTemplate, boundary, formKey, "defProfileImage.jpg", "image/jpg");

                byte[] headerbytes = Encoding.UTF8.GetBytes(header);

     

                string responseString = string.Empty;

     

                ts.TraceInformation("Uploading Image");

                try

                {

                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(jivePictureUrl);

                    request.Method = "POST";

                    request.KeepAlive = true;

                    request.ContentType = "multipart/form-data; boundary=" + boundary;

                    request.Headers[HttpRequestHeader.Authorization] = "Basic " + credentials;

     

                    using (Stream requestStream = request.GetRequestStream())

                    {

                        requestStream.Write(headerbytes, 0, headerbytes.Length);

     

           requestStream.Write(imageBits, 0, imageBits.Length);

     

                        byte[] newlineBytes = Encoding.UTF8.GetBytes("\r\n");

           requestStream.Write(newlineBytes, 0, newlineBytes.Length);

     

                        byte[] endBytes = System.Text.Encoding.UTF8.GetBytes("--" + boundary + "--");

       requestStream.Write(endBytes, 0, endBytes.Length);

       requestStream.Close();

     

                        ts.TraceInformation("Request stream complete");

                        using (WebResponse response = request.GetResponse())

                        {

                            string tempImageLoc = response.Headers["Location"];

                            ts.TraceInformation("Response Header location: " + tempImageLoc);

                            using (StreamReader reader = new StreamReader(response.GetResponseStream()))

                            {

                                ts.TraceInformation("Reading response");

                                responseString = reader.ReadToEnd();

                            };

     

                            //set profile image

                            ts.TraceInformation("Attempting to set profile image");

                            //set image URL

                            string jivePeopleUrl = ConfigurationManager.AppSettings["JiveURI"];

                            jivePeopleUrl += "api/core/v3/people/";

                            jivePeopleUrl += person.id + "/images";

     

                            using (WebClient client = new WebClient())

                            {

      ts.TraceInformation("setting credentials");

                                client.Headers[HttpRequestHeader.Authorization] = "Basic " + credentials;

                                client.Headers[HttpRequestHeader.Accept] = "application/json";                           

     

      System.Collections.Specialized.NameValueCollection myNameValueCollection = new System.Collections.Specialized.NameValueCollection();

      myNameValueCollection.Add("imageURI", tempImageLoc);

     

                                byte[] setImageResponse = client.UploadValues(jivePeopleUrl, myNameValueCollection);

                                ts.TraceInformation("set Image Response: " + setImageResponse.Length);

                            }//end client 

                        }//end response using

                    }//end request stream using

                }//end try

                catch (Exception ex)

                {

                    ts.TraceEvent(TraceEventType.Error, 1, ex.StackTrace);

                    throw new System.ServiceModel.Web.WebFaultException<string>(ex.Message, HttpStatusCode.InternalServerError);

                }

     

                return responseString;

            }//end updateImage