SuiteSocial API Guide - Oracle · 2020-03-19 · Getting Started with the SuiteSocial API 2 6. Note...

64
SuiteSocial API Guide January 15, 2020 2020.1

Transcript of SuiteSocial API Guide - Oracle · 2020-03-19 · Getting Started with the SuiteSocial API 2 6. Note...

SuiteSocial API Guide

January 15, 2020 2020.1

Copyright © 2005, 2019, Oracle and/or its affiliates. All rights reserved.

This software and related documentation are provided under a license agreement containing restrictionson use and disclosure and are protected by intellectual property laws. Except as expressly permittedin your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast,modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by anymeans. Reverse engineering, disassembly, or decompilation of this software, unless required by law forinteroperability, is prohibited.

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing iton behalf of the U.S. Government, then the following notice is applicable:

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software,any programs installed on the hardware, and/or documentation, delivered to U.S. Government endusers are "commercial computer software" pursuant to the applicable Federal Acquisition Regulationand agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, andadaptation of the programs, including any operating system, integrated software, any programs installedon the hardware, and/or documentation, shall be subject to license terms and license restrictionsapplicable to the programs. No other rights are granted to the U.S. Government.

This software or hardware is developed for general use in a variety of information managementapplications. It is not developed or intended for use in any inherently dangerous applications, includingapplications that may create a risk of personal injury. If you use this software or hardware in dangerousapplications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and othermeasures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damagescaused by use of this software or hardware in dangerous applications.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarksof their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarksare used under license and are trademarks or registered trademarks of SPARC International, Inc.AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks ofAdvanced Micro Devices. UNIX is a registered trademark of The Open Group.

This software or hardware and documentation may provide access to or information about content,products, and services from third parties. Oracle Corporation and its affiliates are not responsible for andexpressly disclaim all warranties of any kind with respect to third-party content, products, and servicesunless otherwise set forth in an applicable agreement between you and Oracle. Oracle Corporation andits affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or useof third-party content, products, or services, except as set forth in an applicable agreement between youand Oracle.

If this document is in public or private pre-General Availability status:

This documentation is in pre-General Availability status and is intended for demonstration and preliminaryuse only. It may not be specific to the hardware on which you are using the software. Oracle Corporationand its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect tothis documentation and will not be responsible for any loss, costs, or damages incurred due to the use ofthis documentation.

If this document is in private pre-General Availability status:

The information contained in this document is for informational sharing purposes only and should beconsidered in your capacity as a customer advisory board member or pursuant to your pre-GeneralAvailability trial agreement only. It is not a commitment to deliver any material, code, or functionality, and

should not be relied upon in making purchasing decisions. The development, release, and timing of anyfeatures or functionality described in this document remains at the sole discretion of Oracle.

This document in any form, software or printed matter, contains proprietary information that is theexclusive property of Oracle. Your access to and use of this confidential material is subject to the termsand conditions of your Oracle Master Agreement, Oracle License and Services Agreement, OraclePartnerNetwork Agreement, Oracle distribution agreement, or other license agreement which hasbeen executed by you and Oracle and with which you agree to comply. This document and informationcontained herein may not be disclosed, copied, reproduced, or distributed to anyone outside Oraclewithout prior written consent of Oracle. This document is not part of your license agreement nor can it beincorporated into any contractual agreement with Oracle or its subsidiaries or affiliates.

For information about Oracle's commitment to accessibility, visit the Oracle Accessibility Program websiteat http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc

Oracle customers that have purchased support have access to electronic support through My OracleSupport. For information, visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info or visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs if you are hearing impaired.

Sample Code

Oracle may provide sample code in SuiteAnswers, the Help Center, User Guides, or elsewhere throughhelp links. All such sample code is provided "as is” and “as available”, for use only with an authorizedNetSuite Service account, and is made available as a SuiteCloud Technology subject to the SuiteCloudTerms of Service at www.netsuite.com/tos.

Oracle may modify or remove sample code at any time without notice.

No Excessive Use of the Service

As the Service is a multi-tenant service offering on shared databases, Customer may not use the Servicein excess of limits or thresholds that Oracle considers commercially reasonable for the Service. If Oraclereasonably concludes that a Customer’s use is excessive and/or will cause immediate or ongoingperformance issues for one or more of Oracle’s other customers, Oracle may slow down or throttleCustomer’s excess use until such time that Customer’s use stays within reasonable limits. If Customer’sparticular usage pattern requires a higher limit or threshold, then the Customer should procure asubscription to the Service that accommodates a higher limit and/or threshold that more effectively alignswith the Customer’s actual usage pattern.

Beta Features

Oracle may make available to Customer certain features that are labeled “beta” that are not yet generallyavailable. To use such features, Customer acknowledges and agrees that such beta features are subjectto the terms and conditions accepted by Customer upon activation of the feature, or in the absence ofsuch terms, subject to the limitations for the feature described in the User Guide and as follows: The betafeature is a prototype or beta version only and is not error or bug free and Customer agrees that it willuse the beta feature carefully and will not use it in any way which might result in any loss, corruption orunauthorized access of or to its or any third party’s property or information. Customer must promptlyreport to Oracle any defects, errors or other problems in beta features to [email protected] orother designated contact for the specific beta feature. Oracle cannot guarantee the continued availabilityof such beta features and may substantially modify or cease providing such beta features withoutentitling Customer to any refund, credit, or other compensation. Oracle makes no representations orwarranties regarding functionality or use of beta features and Oracle shall have no liability for any lostdata, incomplete data, re-run time, inaccurate input, work delay, lost profits or adverse effect on theperformance of the Service resulting from the use of beta features. Oracle’s standard service levels,warranties and related commitments regarding the Service shall not apply to beta features and they maynot be fully supported by Oracle’s customer support. These limitations and exclusions shall apply until thedate that Oracle at its sole option makes a beta feature generally available to its customers and partnersas part of the Service without a “beta” label.

Send Us Your FeedbackWe'd like to hear your feedback on this document.

Answering the following questions will help us improve our help content:

■ Did you find the information you needed? If not, what was missing?

■ Did you find any errors?

■ Is the information clear?

■ Are the examples correct?

■ Do you need more examples?

■ What did you like most about this document?

Click here to send us your comments. If possible, please provide a page number or section title to identifythe content you're describing.

To report software issues, contact NetSuite Customer Support.

Table of ContentsWorking with the SuiteSocial API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

SuiteSocial API Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Getting Started with the SuiteSocial API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Assigning a SuiteSocial Integration Role to an Employee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Deploying the SuiteSocial Integration RESTlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Creating the Code for Initializing the RESTlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Calling the RESTlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3Posts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9Colleagues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11Followers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12Channels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Error Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16Appendix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

Sample Application Source Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

Working with the SuiteSocial API 1

Working with the SuiteSocial API

SuiteSocial API OverviewThe SuiteSocial API lets you integrate SuiteSocial data into third-party applications. This API can be used toretrieve data from the SuiteSocial news feed, and view it in another application.

Getting Started with the SuiteSocial APIThe following procedures describe the steps to set up the SuiteSocial API. You must perform theseprocedures in sequence.

■ Assigning a SuiteSocial Integration Role to an Employee■ Deploying the SuiteSocial Integration RESTlet■ Creating the Code for Initializing the RESTlet■ Calling the RESTlet

Assigning a SuiteSocial Integration Role to an EmployeeImportant: Adding the integration role to an existing employee is not recommended. This rolemust be used only for integration purposes.

1. To create a new employee, go to Lists > Employees > Employees > New.2. Enter values for the Name, Email, and Subsidiary field. For more information, see the help topic

Adding an Employee Record.3. Click the Access subtab, and then check the Give Access box.4. Enter a password, and then retype the password in the appropriate field to confirm.5. In the Roles sublist, select the integration role to assign to this employee record:

■ SuiteSocial Integration Read Access – This role includes read-only access to SuiteSocialcustom records.

■ SuiteSocial Integration Full Access – This role includes full access to SuiteSocial customrecords.

Note: Both roles are bundled with the SuiteSocial SuiteApp and have read-only access toEmployee and Subsidiary records.

6. Click Add.7. Click Save.

Deploying the SuiteSocial Integration RESTlet1. Go to Customization > Scripting > Scripts.2. Click the View link next to the SuiteSocial Integration RESTlet script.3. On the Script page, click the Deployments subtab, and then click SuiteSocial Integration RESTlet.4. On the Script Deployment page, click Edit.5. Check the Deployed box, and then click Save.

SuiteSocial API Guide

Getting Started with the SuiteSocial API 2

6. Note the URL for the Integration RESTlet.The external URL is used to call the RESTlet from an externally hosted client. This will be requiredin the next procedure.

Creating the Code for Initializing the RESTletNote: The sample codes used in the following steps are written in C#. These codes may be usedas is, or converted to the preferred programming language.

1. Create a new C# .NET project.2. Paste the following code snippet to the .NET project.

// Initialize the RESTlet URL with the desired parametersstring url = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=123&deploy=1" + "&resource=users&action=get"; // Initialize authentication credentialsstring authHeader = GetAuthenticationHeader();// Send a request to the RESTlet, providing the URL and the authentication headerstring jsonString = RequestRESTlet(url, authHeader);

3. In the code snippet, replace the value of the URL with the External URL from the previousprocedure.

4. Copy and paste the functions, GetAuthenticationHeader and RequestRESTlet to the .NETproject. See UsersForm.cs in the Appendix section.

5. Set the appropriate authentication credentials in the GetAuthenticationHeader function.

private string GetAuthenticationHeader(){ // Initialize authentication credentials var accountId = "1234567"; // Company Account ID var email = "[email protected]"; // SuiteSocial Integration User Email var password = "password123"; // SuiteSocial Integration User Password var role = "1001"; // SuiteSocial Integration Role ID string authHeader = "NLAuth nlauth_account=" + accountId + ", nlauth_email=" + email + ", nlauth_signature=" + password + ", nlauth_role=" + role; // Return the authentication header string return authHeader;}

Note: The SuiteSocial Integration Role ID is available under the Internal ID columnon the Manage Roles page (Setup > Users/Roles > Manage Roles). Use the ID for theSuiteSocial Integration Read Access role.

The Internal ID column is displayed only if you enable the Show Internal IDs preference(Home > Set Preferences > General > Defaults).

Calling the RESTlet1. Run the codes created in the previous procedures.2. Verify the result of jsonString. See the following sample results:

SuiteSocial API Guide

Getting Started with the SuiteSocial API 3

// Sample JSON result of a successful call to the RESTlet[ { "id" : "125", "lastName" : "Smith", "firstName" : "Angela", "email" : "[email protected]", "userType" : "employee", "title" : "Manager", "department" : { "id" : "412", "name" : "Finance" }} ] // Sample JSON result with error{ "error" : { "code" : "MISSING_REQUIRED_PARAMETER", "message" : "A required parameter 'Resource' is missing." }}

ResourcesA resource is a parameter that identifies the data that you can retrieve using the SuiteSocial API. Thefollowing table lists the possible values for this parameter:

Resource Description

Posts Retrieves the posts accessible to a SuiteSocial user or users.

Users Retrieves a list of active SuiteSocial users.

Colleagues Retrieves a list of employees that the specified user is following.

Followers Retrieves a list of the specified user’s followers.

Channels Retrieves a list of all the channels in SuiteSocial.

Example:

https://rest.netsuite.com/app/site/hosting/restlet.nl?script=17&deploy=1&Resource=Posts&Action=Get&viewAsUserId=125

PostsRetrieves the posts accessible to a SuiteSocial user or users. Posts are returned in reverse-chronologicalorder. You can filter or paginate the number and type of posts returned.

Parameters■ action {string} [required]

Specifies the action to perform on a resource.

SuiteSocial API Guide

Resources 4

Note: The current version of the API supports only the action, ‘get’.

■ viewAsUserId {integer or string} [required]

Retrieves the posts that all users or a specific user can view. Set to ‘all’ to get the posts of all users, orset to the numeric NetSuite ID of an employee to get posts that the user can view.

■ lessThanPostId {integer} [optional]

Retrieves posts with a post ID that is less than the number specified. Set to a system-generatedNetSuite internal ID for a post. Together with size, this can be used for paging posts.

■ size {integer} [optional]

Specifies the number of posts to retrieve. The maximum is 1000 posts. If viewAsUserId is set to anemployee ID, the default maximum number of posts retrieved is 25. If the size is not specified, or if thesize specified is more than the maximum value (25 or 1000), the result will be limited to the maximumvalue.

■ searchString {string} [optional]

Retrieves only the posts that contain the specified keyword or phrase.

■ filter {string} [optional]

Retrieves posts based on the type of filter. Set to ‘channel’, ‘author’, or ‘record’.

Note: To use the filter, you must provide the internal ID for the channel, author, or record.Enable the Show Internal IDs preference (from Home > Set Preferences > General > Defaults)to display the internal ID.

□ channelId {string} [optional] — Set to the internal ID of a channel to retrieve posts only from thespecified channel. To use this parameter, you must also set the filter to ‘channel’.

The channel ID is available under the Internal ID column on the SuiteSocial Channel customrecord. Go to Customization > Lists, Records, & Fields > Record Types, and then click the List linkfor the SuiteSocial Channel record.

Example:

SuiteSocial API Guide

Resources 5

https://rest.netsuite.com/app/site/hosting/restlet.nl?script=17&deploy=1&Resource=Posts&Action=Get&viewAsUserId=125&filter=channel&channelId=412

□ recordTypeScriptId {string} [optional] — Set to the record type script ID to retrieve only theposts associated with the specified scripted record. To user this parameter, you must also set avalue for recordId and set the filter to ‘record’.

The record type script ID is available under the Script ID column on the Scripted Records page. Goto Customization > Scripting > Scripted Records. Check Show Undeployed to display all scriptedrecords.

□ recordId {string} — Set to the record internal ID to retrieve only the posts associated with thespecified record. To use this parameter, you must also set a value for recordTypeScriptId andset the filter to ‘record’.

The record ID is available under the Internal ID column on the record list page. For example, tofind the ID of a customer record, go to Lists > Relationships > Customers.

Example:

https://rest.netsuite.com/app/site/hosting/restlet.nl?script=17&deploy=1&Resource=Posts&Action=Get&viewAsUserId=125&filter=record&recordTypeScriptId=customer&recordId=22

Note: The record filter does not check if an employee has access to a record. Whenapplying this filter to posts that can be viewed by a specific user (viewAsUserId is set to anemployee ID), additional security measures must be implemented to ensure that employeescan view only the records that they have access to.

□ authorId {string} [optional] — Set to the numeric NetSuite ID of the employee to retrieve onlythe posts created by the specified user. To use this parameter, you must also set the filter to‘author’.

The employee ID is available under the Internal ID column on the Employees page. Go to Lists >Employees > Employees.

Example:

https://rest.netsuite.com/app/site/hosting/restlet.nl?script=17&deploy=1&Resource=Posts&Action=Get&viewAsUserId=125&filter=author&authorId=121

SuiteSocial API Guide

Resources 6

Note: If viewAsUserId is set to ‘all’, applying the author filter will retrieve all the postscreated by the specified authorId. If viewAsUserId is set to an employee ID, this filter willretrieve all the posts created by the specified authorId, that the employee can view. Thisalso includes private messages that the employee sent to the author.

Returns

Posts returns an array containing details of the posts retrieved:

■ id {string} — System-generated NetSuite internal ID.

■ dateCreated {datetime} — Date and time the post was created, displayed in ISO format.

■ message {string} — Displays the content of the post.

■ sender {object} — Contains details about the SuiteSocial user who created the post.

□ id {string} — System-generated NetSuite internal ID of an employee.

□ name {string} — Full name of the employee, as it appears in NetSuite’s employee record.

□ profilePhotoUrl {string} — URL of the sender’s profile photo.

■ channel {object} — Contains details about the channel where the post was created.

□ id {string} — System-generated NetSuite internal ID. For public channel, the value is zero (0).

□ name {string} — Name of the channel.

■ isPrivate {boolean} — Specifies if the post is a private message or not.

■ recipient {object} — If the value of isPrivate is ‘true’, this will return details about the recipient ofa private message. Otherwise, the returned value is null.

□ id {string} — System-generated NetSuite employee internal ID.

□ name {string} — Full name of the employee, as it appears in NetSuite’s employee record.

■ record {object} — Contains details about the record that the post is related to. This will return a valueif there is a record change or if a post is made under the record page subtab. The returned value maybe null.

□ id {string} — System-generated NetSuite record internal ID.

□ name {string} — Name of the record.

□ recordURL {string} — The URL of the record. This is accessible when you are logged in toNetSuite.

□ recordTypeScriptId {string} — The script ID of the record type. For example, salesorder,employee.

SuiteSocial API Guide

Resources 7

□ recordTypeName {string} — The name of the record type. For example, Sales Order, Employee.

■ file {object} — The file attached to this post. The returned value may be null.

□ id {string} — System-generated NetSuite internal ID.

□ name {string} — Name of the file.

□ url {string} — Full URL of the file.

□ imagePreviewURL {string} — Full URL of the preview image.

Note: If the original image width is less than 600px, the returned value will be null.

■ permissionList {string[]} — List of employee IDs that can view the post. For posts made in auto-subscribed channels, this will return an array with a single element, 'employee’.

Note: If viewAsUserId is set to a specific employee ID, the value returned will be null.

Sample Input

https://rest.netsuite.com/app/site/hosting/restlet.nl?script=17&deploy=1&Resource=Posts&Action=Get&viewAsUserId=122

Sample Output

[{ id : '203', dateCreated : '2015-04-16T01:11:00.000Z', message : 'hello world', sender : { id : '125', name : 'Angela Smith', profilePhotoUrl : 'https://system.netsuite.com/core/media/media.nl?id=72562&c=3553597&h=527cb7833c533fd71b11%27', }, channel : { id : '112', name : 'Company Announcement' }, isPrivate : true, recipient : { id : '382', name : 'Robert Johnson' }, record : { id : '1', name : 'Employee Anne Miller', recordURL : 'https://system.netsuite.com/app/common/entity/employee.nl?id=748%27', recordTypeScriptId : 'employee', recordTypeName : 'Sales Order' }, file : { id : '223', name : 'cust_SO.png', url : 'https://system.netsuite.com/core/media/media.nl?id=72562&c=3553597&h=527cb7833c533fd71b11%27',

SuiteSocial API Guide

Resources 8

imagePreviewUrl : 'https://system.netsuite.com/core/media/media.nl?id=72562&c=3553597&h=527cb7833c533fd71b11%27', }, permissionList : [ '1', '2', '3', '4' ], comments : [ { id : '212', message : 'You can refer to this one too.', sender : { id : '125', name : 'Angela Smith', profilePhotoUrl : 'https://system.netsuite.com/core/media/media.nl?id=72562&c=3553597&h=527cb7833c533fd71b11%27', }, dateCreated : '2015-04-16T01:11:00.000Z', file : { id : '408', name : 'cust_ref.png', url : 'https://system.netsuite.com/app/site/hosting/scriptlet.nl?script=865&deploy=1&custparam_postid=11514%27', imagePreviewUrl : 'https://system.netsuite.com/core/media/media.nl?id=72562&c=3553597&h=527cb7833c533fd71b11%27', }, } ]}];

Sample Usage in .NET

// Initialize parameter valuesstring UserId = "123"; // Employee ID of the user being simulatedstring channelId = "15"; // Internal ID of the channelstring searchString = "hello"; // Keyword to search // Initialize the RESTlet URL with the desired parametersstring url = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=123&deploy=1" + "&resource=posts&action=get&viewAsUserId=" + UserId;// Include the channel filter to retrieve posts only from the specified channelurl += "&channel=" + channelId;// Include a search string to retrieve only the posts that contains the specified stringurl += "&searchString=" + searchString; // Initialize authentication credentialsstring authHeader = GetAuthenticationHeader(); // Send a request to the RESTlet, providing the URL and authentication headerstring jsonString = RequestRESTlet(url, authHeader); // Convert JSON string to the appropriate object// Note: SuiteSocialColleague is a custom class whose structure mimics that of the colleague (following/follower) JSON object. See documentation for details on the object.// List<> is used here because the result of Followers is an array of colleagues.List<SuiteSocialPost> posts = (List<SuiteSocialPost>)ParseJSONString(jsonString, typeof(List<SuiteSocialPost>)); List

/* Begin using the retrieved object into the UI */

SuiteSocial API Guide

Resources 9

// Reset hash to keep the new set of postsm_hashPosts.Clear(); // Load the list of postslistPosts.Items.Clear();for (int i = 0; i < posts.Count; i++){ // Get each post SuiteSocialPost post = posts[i]; // Add item to list ListViewItem lvItem = new ListViewItem(post.dateCreated, 0); lvItem.Tag = post.id; lvItem.SubItems.Add(post.message); lvItem.SubItems.Add(post.sender.name); lvItem.SubItems.Add(post.sender.profilePhotoUrl); lvItem.SubItems.Add(post.channel.name); lvItem.SubItems.Add(post.isPrivate.ToString()); lvItem.SubItems.Add(post.recipient != null ? post.recipient.name : ""); lvItem.SubItems.Add(post.record != null ? post.record.name : ""); lvItem.SubItems.Add(post.record != null ? post.record.typeName : ""); lvItem.SubItems.Add(post.file != null ? post.file.name : ""); lvItem.SubItems.Add(post.file != null ? post.file.url : ""); lvItem.SubItems.Add(post.comments.Count.ToString()); listPosts.Items.Add(lvItem); // Add to hash m_hashPosts.Add(post.id, post);}

UsersRetrieves a list of active SuiteSocial users. The list is returned in chronological order.

Parameter■ action {string} [required]

Specifies the action to perform on a resource.

Note: The current version of the API supports only the action, ‘get’.

ReturnsUsers returns an array containing details about the users retrieved:

■ id {string} — System-generated NetSuite internal ID of the employee.■ lastName {string} — Last name of the employee.■ firstName {string} — First name of the employee.■ email {string} — Email address of the employee.■ userType {string} — Specifies the type of user. Currently, valid value is only ‘employee’.■ title {string} — Specifies the employee’s job title.

SuiteSocial API Guide

Resources 10

■ department {string} — Specifies which department the employee belongs to.

□ id {string} — System-generated NetSuite internal ID of the department.

□ name {string} — Specifies the name of the department.

Sample Input

https://rest.netsuite.com/app/site/hosting/restlet.nl?script=17&deploy=1&Resource=Users&Action=get

Sample Output

var users = [ { id : '125', lastName : 'Smith', firstName : 'Angela', email : '[email protected]', userType : 'employee', title : 'Manager', department : { id : '412', name : 'Finance' }} ];

Sample Usage in .NET

// Initialize the RESTlet URL with the desired parametersstring url = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=123&deploy=1" + "&resource=users&action=get";

// Initialize authentication credentialsstring authHeader = GetAuthenticationHeader();// Send a request to the RESTlet, providing the URL and authentication headerstring jsonString = RequestRESTlet(url, authHeader);

// Convert JSON string to the appropriate object// Note: SuiteSocialUser is a custom class whose structure mimics that of the user JSON object. See documentation for details on the object.// List<> is used here because the result of Users is an array of users.List<SuiteSocialUser> users = (List<SuiteSocialUser>)ParseJSONString(jsonString, typeof(List<SuiteSocialUser>));

/* Begin using the retrieved object into the UI */

// Load userslistUsers.Items.Clear();

// Add ALLListViewItem lvItem = new ListViewItem("ALL", 0);lvItem.Tag = "ALL";lvItem.SubItems.Add("");lvItem.SubItems.Add("");listUsers.Items.Add(lvItem);

SuiteSocial API Guide

Resources 11

for (int i = 0; i < users.Count; i++){ // Get each user SuiteSocialUser user = users[i];

// Add item to the list lvItem = new ListViewItem(user.firstName + " " + user.lastName, 0); lvItem.Tag = user.id; lvItem.SubItems.Add(user.title ?? ""); lvItem.SubItems.Add(user.department != null ? user.department.name : ""); listUsers.Items.Add(lvItem);}

ColleaguesRetrieves a list of employees that the specified user is following. The names are sorted alphabetically.

Parameters■ action {string} [required]

Specifies the action to perform on a resource.

Note: The current version of the API supports only the action, ‘get’.

■ userId {string} [required]System-generated NetSuite internal ID for the employee.

ReturnsColleagues returns an array containing details about the employees that the specified user is following:

■ id {string} — System-generated NetSuite internal ID for the employee.■ name {string} — Name of the employee.■ title {string} — Specifies the employee’s job title.■ department {string} — Specifies the department name where the employee belongs.■ lastStatus {string} — Shows the last status update posted by the employee.

Sample Input

https://rest.netsuite.com/app/site/hosting/restlet.nl?script=17&deploy=1&resource=colleagues&action=get&userId=122

Sample Output

var following = [ { id : '125', name : 'Employee Angela Smith', title : 'Manager', department : 'Finance', lastStatus : 'In a meeting from 1-4 pm'} ];

SuiteSocial API Guide

Resources 12

Sample Usage in .NET

// Initialize parameter valuesstring UserId = "123"; // employee id of user being simulated

// Initialize the RESTlet URL with the desired parametersstring url = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=123&deploy=1" + "&resource=colleagues&action=get&userId=" + UserId;

// Initialize authentication credentialsstring authHeader = GetAuthenticationHeader();// Send a request to the RESTlet, providing the URL and authentication headerstring jsonString = RequestRESTlet(url, authHeader);

// Convert JSON string to the appropriate object// Note: SuiteSocialColleague is a custom class whose structure mimics that of the colleague (following/follower) JSON object. See documentation for details on the object.// List<> is used here because the result of Colleagues is an array of colleagues.List<SuiteSocialColleague> following = (List<SuiteSocialColleague>)ParseJSONString(jsonString, typeof(List<SuiteSocialColleague>));

/* Begin using the retrieved object into the UI */

// Load following listlistColleagues.Items.Clear();for (int i = 0; i < following.Count; i++){ // Get each user SuiteSocialColleague colleague = following[i];

// Add item to list ListViewItem lvItem = new ListViewItem(colleague.name, 0); lvItem.Tag = colleague.id; lvItem.SubItems.Add(colleague.title ?? ""); lvItem.SubItems.Add(colleague.department ?? ""); lvItem.SubItems.Add(colleague.lastStatus ?? ""); listColleagues.Items.Add(lvItem);}

FollowersRetrieves a list of the specified user’s followers. The names are sorted alphabetically.

Parameters

■ action {string} [required]

Specifies the action to perform on a resource.

Note: The current version of the API supports only the action, ‘get’.

■ userId {string} [required]

System-generated NetSuite internal ID of the employee.

SuiteSocial API Guide

Resources 13

ReturnsFollowers returns an array containing details about the specified user’s followers.

■ id {string} — System-generated NetSuite internal ID of the employee■ name {string} — Name of the employee.■ title {string} — Specifies the employee’s job title.■ department {string} — Specifies the department name where the employee belongs.■ lastStatus {string} — Shows the last status update posted by the employee.

Sample Input

https://rest.netsuite.com/app/site/hosting/restlet.nl?script=17&deploy=1&Resource=Followers&Action=Get&userId=123

Sample Output

var following = [ { id : '125', name : 'Employee Angela Smith', title : 'Manager', department : 'Finance', lastStatus : 'In a meeting from 1-4 pm'} ];

Sample Usage in .NET

// Initialize parameter valuesstring UserId = "123"; // Employee ID of user being simulated

// Initialize the RESTlet URL with the desired parametersstring url = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=123&deploy=1" + "&resource=followers&action=get&userId=" + UserId;

// Initialize authentication credentialsstring authHeader = GetAuthenticationHeader();

// Send a request to the RESTlet, providing the URL and authentication headerstring jsonString = RequestRESTlet(url, authHeader);

// Convert JSON string to the appropriate object// Note: SuiteSocialColleague is a custom class whose structure mimics that of the colleague (following/follower) JSON object. See documentation for details on the object.// List<> is used here because the result of Followers is an array of colleagues.List<SuiteSocialColleague> followers = (List<SuiteSocialColleague>)ParseJSONString(jsonString, typeof(List<SuiteSocialColleague>));

/* Begin using the retrieved object into the UI */

// Load the followers listlistColleagues.Items.Clear();for (int i = 0; i < followers.Count; i++){

SuiteSocial API Guide

Resources 14

// Get each user SuiteSocialColleague colleague = followers[i];

// Add item to the list ListViewItem lvItem = new ListViewItem(colleague.name, 0); lvItem.Tag = colleague.id; lvItem.SubItems.Add(colleague.title ?? ""); lvItem.SubItems.Add(colleague.department ?? ""); lvItem.SubItems.Add(colleague.lastStatus ?? ""); listColleagues.Items.Add(lvItem);}

ChannelsRetrieves a list of all the channels in SuiteSocial.

Parameter■ action {string} [required]

Specifies the action to perform on a resource.

Note: The current version of the API supports only the action, ‘get’.

ReturnsChannels returns an array that contains information about the available channels in SuiteSocial.

■ id {string} — System-generated NetSuite internal ID.■ name {string} — Name of the channel.■ subsidiary {object} — Specifies the subsidiary that has access to the channel. If the value is null, no

subsidiary restrictions were set for this channel.You can select only one subsidiary as a channel filter for this version of SuiteSocial.□ id {string} — System-generated NetSuite internal ID.□ name {string} — Name of the subsidiary.

■ departments {object} — Specifies the departments that have access to the channel. If the value isnull, no department restrictions were set for this channel.□ id {string} — System-generated NetSuite internal ID.□ name {string} — Name of the department.

■ locations {object} — Specifies the locations that have access to the channel. If the value is null, nolocation restrictions were set for this channel.□ id {string} — System-generated NetSuite internal ID.□ name {string} — Name of the location.

■ roles {object} — Specifies the roles that have access to the channel. If the value is null, no rolerestrictions were set for this channel.□ id {string} — System-generated NetSuite internal ID.□ name {string} — Name of the role.

■ viewPermissionList {object} — Specifies the employees who can view the channel. If the value isnull, no restrictions were set for this channel.

SuiteSocial API Guide

Resources 15

□ id {string} — System-generated NetSuite internal ID.□ name {string} — Name of the employee.

■ createPermissionList {object} — Specifies the employees who can post to the channel. If thevalue is null, no restrictions were set for this channel.□ id {string} — System-generated NetSuite internal ID.□ name {string} — Name of the employee.

■ isAutoSubscribe {boolean} — Specifies if users are automatically subscribed to this channel.■ isAllowComments {boolean} — Specifies if users can comment on posts from this channel.■ externalId {string} — Unique ID that can be used to link this record to an external system.

Sample Input

https://rest.netsuite.com/app/site/hosting/restlet.nl?script=17&deploy=1&Resource=Channels&Action=Get

Sample Output

var channel = { id : '212', name : 'Company Announcement', subsidiary : { id : '101', name : 'Parent Company' }, departments : [ { id : '412', name : 'Finance' } ], locations : [ { id : '113', name : 'APAC' } ], roles : [ { id : '302', name : 'Manager' } ], viewPermissionList : [ { id : '125', name : 'Angela Smith' } ], createPermissionList : [ { id : '125', name : 'Angela Smith' } ], isAutoSubscribe : true, isAllowComments : true, externalId : 'EXT332'};

Sample Usage in .NET

// Initialize RESTlet URL with the desired parameters

SuiteSocial API Guide

Resources 16

string url = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=123&deploy=1" + "&resource=channels&action=get"; // Initialize authentication credentialsstring authHeader = GetAuthenticationHeader(); // Send a request to the RESTlet, providing the URL and authentication headerstring jsonString = RequestRESTlet(url, authHeader); // Convert JSON string to appropriate object// Note: SuiteSocialChannel is a custom class whose structure mimics that of the channel JSON object. See documentation for details on the object.// List<> is used here because the result of Channels is an array of channels.List<SuiteSocialChannel> channels = (List<SuiteSocialChannel>)ParseJSONString(jsonString, typeof(List<SuiteSocialChannel>));

/* Begin using the retrieved object into the UI */ // Load channelscboChannels.Items.Clear(); // Add public channelComboBoxItem cboItem = new ComboBoxItem();cboItem.Text = "Public";cboItem.Value = "0";cboChannels.Items.Add(cboItem); for (int i = 0; i < channels.Count; i++){ // Get each channel SuiteSocialChannel channel = channels[i]; // Add item to the list cboItem = new ComboBoxItem(); cboItem.Text = channel.name; cboItem.Value = channel.id; cboChannels.Items.Add(cboItem);}

Error CodesThe following table lists the error code types that can be returned in a response when using theSuiteSocial API:

Error Code Description

MISSING_REQUIRED_PARAMETER A required parameter [parameter name] is missing.

INVALID_PARAMETER_VALUE Invalid value for parameter [parameter name].

ReturnsThe error object returns the following:

SuiteSocial API Guide

Error Codes 17

■ error {object} — Contains details of the error.

□ code {string} — Specifies the error code.

□ message {string} — Specifies details of the error.

Sample Output

{ error : { code : 'MISSING_REQUIRED_PARAMETER', message : 'A required parameter 'viewAsUserId' is missing.' }}

RESTlet Error HandlingThe following sample code details how a RESTlet error is handled. The WebException object is used hereto hold the details of the error object.

Note that the following code is in C#, and can be used as is or converted to the preferred programminglanguage. This block of code is the same RequestRESTlet function that is used in the SampleApplication Source Code section.

private string RequestRESTlet(string url, string authHeader){ try { // Initialize request var request = WebRequest.Create(url); request.ContentType = "application/json; charset=utf-8"; request.Headers.Add("Authorization", authHeader); request.Timeout = 600000; // User-defined timeout (ms) // Call the RESTlet and get a response var response = (HttpWebResponse)request.GetResponse(); // Get the JSON string result string jsonString = ""; using (var sr = new StreamReader(response.GetResponseStream())) { jsonString = sr.ReadToEnd(); } // Check for an empty string if (jsonString == "") { throw new Exception("JSON string is empty."); } // Return JSON string return jsonString; } catch (WebException ex) { var stream = ex.Response.GetResponseStream(); using (var reader = new StreamReader(stream)) { var strError = reader.ReadToEnd();

SuiteSocial API Guide

Error Codes 18

// Get the error defined and throw it // Note: SuiteSocialError is a custom class whose structure mimics that of the error JSON object. // error = { "error" : { "code" : "ERROR_CODE", "message" : "This is an error message." } } SuiteSocialError error = (SuiteSocialError)ParseJSONString(strError, typeof(SuiteSocialError)); throw new Exception(error.error.message); } } catch (Exception ex) { throw ex; }}

Appendix

Sample Application Source Code

Program.cs

using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;

namespace SuiteSocialClientApp{ static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false);

// Show the users form to a select user UsersForm frmUser = new UsersForm(); if (frmUser.ShowDialog() == DialogResult.OK) { // Show the main form MainForm frmMain = new MainForm(); frmMain.UserId = frmUser.UserId; // user id taken from users form frmMain.UserName = frmUser.UserName; // name taken from users form Application.Run(frmMain); } } }}

SuiteSocial API Guide

Appendix 19

UsersForm.cs

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Configuration;using System.Net;using System.IO; namespace SuiteSocialClientApp{ public partial class UsersForm : Form { public string UserId { get; set; } public string UserName { get; set; } public UsersForm() { InitializeComponent(); } private void UsersForm_Load(object sender, EventArgs e) { // Initialize the RESTlet URL with the desired parameters string url = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=367&deploy=1" + "&resource=users&action=get"; // Initialize authentication credentials string authHeader = GetAuthenticationHeader(); // Send a request to the RESTlet, providing the URL and the authentication header string jsonString = RequestRESTlet(url, authHeader); // Convert JSON string to the appropriate object // Note: SuiteSocialUser is a custom class whose structure mimics that of the user JSON object. See documentation for details on the object. // List<> is used here because the result of getUsers is an array of users. List<SuiteSocialUser> users = (List<SuiteSocialUser>)ParseJSONString(jsonString, typeof(List<SuiteSocialUser>));

/* Begin using the retrieved object into the UI */ // Load users listUsers.Items.Clear(); // Add ALL ListViewItem lvItem = new ListViewItem("ALL", 0); lvItem.Tag = "ALL"; lvItem.SubItems.Add("");

SuiteSocial API Guide

Appendix 20

lvItem.SubItems.Add(""); listUsers.Items.Add(lvItem); for (int i = 0; i < users.Count; i++) { // Get each user SuiteSocialUser user = users[i]; // Add item to the list lvItem = new ListViewItem(user.firstName + " " + user.lastName, 0); lvItem.Tag = user.id; lvItem.SubItems.Add(user.title ?? ""); lvItem.SubItems.Add(user.department != null ? user.department.name : ""); listUsers.Items.Add(lvItem); } } private void btnOK_Click(object sender, EventArgs e) { // Check if a user is selected if (listUsers.SelectedItems.Count == 0) { MessageBox.Show("Please select a user.", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // Get the selected user ListViewItem lvItem = listUsers.SelectedItems[0]; // Keep the user info UserId = lvItem.Tag.ToString(); UserName = lvItem.SubItems[0].Text; // Close with OK result this.DialogResult = System.Windows.Forms.DialogResult.OK; this.Close(); } private void btnCancel_Click(object sender, EventArgs e) { // Close this window this.Close(); } private string GetAuthenticationHeader() { // Initialize authentication credentials var accountId = "1234567"; // Company Account ID var email = "[email protected]"; // SuiteSocial Integration User Email var password = "password123"; // SuiteSocial Integration User Password var role = "1001"; // SuiteSocial Integration Role ID string authHeader = "NLAuth nlauth_account=" + accountId + ", nlauth_email=" + email + ", nlauth_signature=" + password + ", nlauth_role=" + role;

SuiteSocial API Guide

Appendix 21

// Return the authentication header string return authHeader; } private string RequestRESTlet(string url, string authHeader) { try { // Initialize request var request = WebRequest.Create(url); request.ContentType = "application/json; charset=utf-8"; request.Headers.Add("Authorization", authHeader); request.Timeout = 600000; // User-defined timeout (ms) // Call the RESTlet and get a response var response = (HttpWebResponse)request.GetResponse(); // Get JSON string result string jsonString = ""; using (var sr = new StreamReader(response.GetResponseStream())) { jsonString = sr.ReadToEnd(); } // Check if the string is empty if (jsonString == "") { throw new Exception("JSON string is empty."); } // Return JSON string return jsonString; } catch (WebException ex) { var stream = ex.Response.GetResponseStream(); using (var reader = new StreamReader(stream)) { var strError = reader.ReadToEnd(); // Get the error defined and throw it // Note: SuiteSocialError is a custom class whose structure mimics that of the error JSON object. // error = { "error" : { "code" : "ERROR_CODE", "message" : "This is an error message." } } SuiteSocialError error = (SuiteSocialError)ParseJSONString(strError, typeof(SuiteSocialError)); throw new Exception(error.error.message); } } catch (Exception ex) { throw ex; } }

SuiteSocial API Guide

Appendix 22

private object ParseJSONString(string jsonString, Type type) { // Parses the JSON string and converts into an object // Makes use of Json.NET -- a JSON framework for .NET return Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString, type); } }}

UsersForm.Designer.cs (auto-generated)

namespace SuiteSocialClientApp{ partial class UsersForm { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null;

/// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); }

#region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UsersForm)); this.splitMain = new System.Windows.Forms.SplitContainer(); this.lblSelect = new System.Windows.Forms.Label(); this.btnOK = new System.Windows.Forms.Button(); this.listUsers = new System.Windows.Forms.ListView(); this.colName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colTitle = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colDept = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.imgList = new System.Windows.Forms.ImageList(this.components); this.btnCancel = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.splitMain)).BeginInit(); this.splitMain.Panel1.SuspendLayout();

SuiteSocial API Guide

Appendix 23

this.splitMain.Panel2.SuspendLayout(); this.splitMain.SuspendLayout(); this.SuspendLayout(); // // splitMain // this.splitMain.Dock = System.Windows.Forms.DockStyle.Fill; this.splitMain.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; this.splitMain.IsSplitterFixed = true; this.splitMain.Location = new System.Drawing.Point(0, 0); this.splitMain.Name = "splitMain"; this.splitMain.Orientation = System.Windows.Forms.Orientation.Horizontal; // // splitMain.Panel1 // this.splitMain.Panel1.Controls.Add(this.lblSelect); // // splitMain.Panel2 // this.splitMain.Panel2.Controls.Add(this.btnCancel); this.splitMain.Panel2.Controls.Add(this.btnOK); this.splitMain.Panel2.Controls.Add(this.listUsers); this.splitMain.Size = new System.Drawing.Size(373, 229); this.splitMain.SplitterDistance = 30; this.splitMain.TabIndex = 0; // // lblSelect // this.lblSelect.AutoSize = true; this.lblSelect.Font = new System.Drawing.Font("Microsoft Sans Serif", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblSelect.Location = new System.Drawing.Point(12, 7); this.lblSelect.Name = "lblSelect"; this.lblSelect.Size = new System.Drawing.Size(217, 18); this.lblSelect.TabIndex = 0; this.lblSelect.Text = "Please select a user to simulate"; // // btnOK // this.btnOK.Location = new System.Drawing.Point(127, 168); this.btnOK.Name = "btnOK"; this.btnOK.Size = new System.Drawing.Size(114, 25); this.btnOK.TabIndex = 1; this.btnOK.Text = "Select"; this.btnOK.UseVisualStyleBackColor = true; this.btnOK.Click += new System.EventHandler(this.btnOK_Click); // // listUsers // this.listUsers.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.colName, this.colTitle, this.colDept}); this.listUsers.FullRowSelect = true; this.listUsers.LargeImageList = this.imgList;

SuiteSocial API Guide

Appendix 24

this.listUsers.Location = new System.Drawing.Point(0, 0); this.listUsers.MultiSelect = false; this.listUsers.Name = "listUsers"; this.listUsers.Size = new System.Drawing.Size(373, 165); this.listUsers.TabIndex = 0; this.listUsers.TileSize = new System.Drawing.Size(168, 48); this.listUsers.UseCompatibleStateImageBehavior = false; this.listUsers.View = System.Windows.Forms.View.Tile; // // colName // this.colName.Text = "Name"; this.colName.Width = 120; // // colTitle // this.colTitle.Text = "Title"; this.colTitle.Width = 100; // // colDept // this.colDept.Text = "Department"; this.colDept.Width = 100; // // imgList // this.imgList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imgList.ImageStream"))); this.imgList.TransparentColor = System.Drawing.Color.Transparent; this.imgList.Images.SetKeyName(0, "generic_person.jpg"); // // btnCancel // this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.btnCancel.Location = new System.Drawing.Point(247, 168); this.btnCancel.Name = "btnCancel"; this.btnCancel.Size = new System.Drawing.Size(114, 25); this.btnCancel.TabIndex = 2; this.btnCancel.Text = "Cancel"; this.btnCancel.UseVisualStyleBackColor = true; this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); // // UsersForm // this.AcceptButton = this.btnOK; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.btnCancel; this.ClientSize = new System.Drawing.Size(373, 229); this.Controls.Add(this.splitMain); this.MaximizeBox = false; this.Name = "UsersForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "SuiteSocial Client App"; this.Load += new System.EventHandler(this.UsersForm_Load);

SuiteSocial API Guide

Appendix 25

this.splitMain.Panel1.ResumeLayout(false); this.splitMain.Panel1.PerformLayout(); this.splitMain.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitMain)).EndInit(); this.splitMain.ResumeLayout(false); this.ResumeLayout(false);

}

#endregion

private System.Windows.Forms.SplitContainer splitMain; private System.Windows.Forms.Label lblSelect; private System.Windows.Forms.ListView listUsers; private System.Windows.Forms.ColumnHeader colName; private System.Windows.Forms.ColumnHeader colTitle; private System.Windows.Forms.ColumnHeader colDept; private System.Windows.Forms.ImageList imgList; private System.Windows.Forms.Button btnOK; private System.Windows.Forms.Button btnCancel; }}

UserForm.resx (auto-generated)

<?xml version="1.0" encoding="utf-8"?><root> <!-- Microsoft ResX Schema

Version 2.0

The primary goals of this format is to allow a simple XML format that is mostly human readable. The generation and parsing of the various data types are done through the TypeConverter classes associated with the data types.

Example:

... ado.net/XML headers & schema ... <resheader name="resmimetype">text/microsoft-resx</resheader> <resheader name="version">2.0</resheader> <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> <value>[base64 mime encoded serialized .NET Framework object]</value> </data> <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> <comment>This is a comment</comment> </data>

SuiteSocial API Guide

Appendix 26

There are any number of "resheader" rows that contain simple name/value pairs.

Each data row contains a name, and value. The row also contains a type or mimetype. Type corresponds to a .NET class that support text/value conversion through the TypeConverter architecture. Classes that don't support this are serialized and stored with the mimetype set.

The mimetype is used for serialized objects, and tells the ResXResourceReader how to depersist the object. This is currently not extensible. For a given mimetype the value must be set accordingly:

Note - application/x-microsoft.net.object.binary.base64 is the format that the ResXResourceWriter will generate, however the reader can read any of the formats listed below.

mimetype: application/x-microsoft.net.object.binary.base64 value : The object must be serialized with : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.soap.base64 value : The object must be serialized with : System.Runtime.Serialization.Formatters.Soap.SoapFormatter : and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64 value : The object must be serialized into a byte array : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:element name="root" msdata:IsDataSet="true"> <xsd:complexType> <xsd:choice maxOccurs="unbounded"> <xsd:element name="metadata"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" /> </xsd:sequence> <xsd:attribute name="name" use="required" type="xsd:string" /> <xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="mimetype" type="xsd:string" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="assembly"> <xsd:complexType> <xsd:attribute name="alias" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" /> </xsd:complexType>

SuiteSocial API Guide

Appendix 27

</xsd:element> <xsd:element name="data"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="resheader"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" /> </xsd:complexType> </xsd:element> </xsd:choice> </xsd:complexType> </xsd:element> </xsd:schema> <resheader name="resmimetype"> <value>text/microsoft-resx</value> </resheader> <resheader name="version"> <value>2.0</value> </resheader> <resheader name="reader"> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <resheader name="writer"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <metadata name="imgList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>17, 17</value> </metadata> <data name="imgList.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64"> <value> AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACi CAAAAk1TRnQBSQFMAwEBAAFQAQABUAEAATABAAEwAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA AcADAAEwAwABAQEAAQgGAAEkGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHAAdwBwAEA AfABygGmAQABMwUAATMBAAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANCAQADOQEA AYABfAH/AQACUAH/AQABkwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ATMDAAFm AwABmQMAAcwCAAEzAwACMwIAATMBZgIAATMBmQIAATMBzAIAATMB/wIAAWYDAAFmATMCAAJmAgABZgGZ AgABZgHMAgABZgH/AgABmQMAAZkBMwIAAZkBZgIAApkCAAGZAcwCAAGZAf8CAAHMAwABzAEzAgABzAFm AgABzAGZAgACzAIAAcwB/wIAAf8BZgIAAf8BmQIAAf8BzAEAATMB/wIAAf8BAAEzAQABMwEAAWYBAAEz

SuiteSocial API Guide

Appendix 28

AQABmQEAATMBAAHMAQABMwEAAf8BAAH/ATMCAAMzAQACMwFmAQACMwGZAQACMwHMAQACMwH/AQABMwFm AgABMwFmATMBAAEzAmYBAAEzAWYBmQEAATMBZgHMAQABMwFmAf8BAAEzAZkCAAEzAZkBMwEAATMBmQFm AQABMwKZAQABMwGZAcwBAAEzAZkB/wEAATMBzAIAATMBzAEzAQABMwHMAWYBAAEzAcwBmQEAATMCzAEA ATMBzAH/AQABMwH/ATMBAAEzAf8BZgEAATMB/wGZAQABMwH/AcwBAAEzAv8BAAFmAwABZgEAATMBAAFm AQABZgEAAWYBAAGZAQABZgEAAcwBAAFmAQAB/wEAAWYBMwIAAWYCMwEAAWYBMwFmAQABZgEzAZkBAAFm ATMBzAEAAWYBMwH/AQACZgIAAmYBMwEAA2YBAAJmAZkBAAJmAcwBAAFmAZkCAAFmAZkBMwEAAWYBmQFm AQABZgKZAQABZgGZAcwBAAFmAZkB/wEAAWYBzAIAAWYBzAEzAQABZgHMAZkBAAFmAswBAAFmAcwB/wEA AWYB/wIAAWYB/wEzAQABZgH/AZkBAAFmAf8BzAEAAcwBAAH/AQAB/wEAAcwBAAKZAgABmQEzAZkBAAGZ AQABmQEAAZkBAAHMAQABmQMAAZkCMwEAAZkBAAFmAQABmQEzAcwBAAGZAQAB/wEAAZkBZgIAAZkBZgEz AQABmQEzAWYBAAGZAWYBmQEAAZkBZgHMAQABmQEzAf8BAAKZATMBAAKZAWYBAAOZAQACmQHMAQACmQH/ AQABmQHMAgABmQHMATMBAAFmAcwBZgEAAZkBzAGZAQABmQLMAQABmQHMAf8BAAGZAf8CAAGZAf8BMwEA AZkBzAFmAQABmQH/AZkBAAGZAf8BzAEAAZkC/wEAAcwDAAGZAQABMwEAAcwBAAFmAQABzAEAAZkBAAHM AQABzAEAAZkBMwIAAcwCMwEAAcwBMwFmAQABzAEzAZkBAAHMATMBzAEAAcwBMwH/AQABzAFmAgABzAFm ATMBAAGZAmYBAAHMAWYBmQEAAcwBZgHMAQABmQFmAf8BAAHMAZkCAAHMAZkBMwEAAcwBmQFmAQABzAKZ AQABzAGZAcwBAAHMAZkB/wEAAswCAALMATMBAALMAWYBAALMAZkBAAPMAQACzAH/AQABzAH/AgABzAH/ ATMBAAGZAf8BZgEAAcwB/wGZAQABzAH/AcwBAAHMAv8BAAHMAQABMwEAAf8BAAFmAQAB/wEAAZkBAAHM ATMCAAH/AjMBAAH/ATMBZgEAAf8BMwGZAQAB/wEzAcwBAAH/ATMB/wEAAf8BZgIAAf8BZgEzAQABzAJm AQAB/wFmAZkBAAH/AWYBzAEAAcwBZgH/AQAB/wGZAgAB/wGZATMBAAH/AZkBZgEAAf8CmQEAAf8BmQHM AQAB/wGZAf8BAAH/AcwCAAH/AcwBMwEAAf8BzAFmAQAB/wHMAZkBAAH/AswBAAH/AcwB/wEAAv8BMwEA AcwB/wFmAQAC/wGZAQAC/wHMAQACZgH/AQABZgH/AWYBAAFmAv8BAAH/AmYBAAH/AWYB/wEAAv8BZgEA ASEBAAGlAQADXwEAA3cBAAOGAQADlgEAA8sBAAOyAQAD1wEAA90BAAPjAQAD6gEAA/EBAAP4AQAB8AH7 Af8BAAGkAqABAAOAAwAB/wIAAf8DAAL/AQAB/wMAAf8BAAH/AQAC/wIAA/8BADDzkAAw85AAMPOQADDz kAAB/wH0LPMB9AH/kAAE/wH0J/MB9AP/kAAG/wH0IvMB9Ab/kAAJ/wH0HfMB9Aj/kAAM/xjzAfQL/5AA Dv8V8w3/kAAP/xLzAfQO/5AAEP8R8w//kAAQ/wH0D/MQ/5AAEf8O8wH0EP+QABH/AfQN8xH/kAAR/wH0 DfMR/5AAEf8B9A3zEf+QABH/AfQN8xH/kAAR/wH0DfMR/5AAEf8O8wH0EP+QABD/AfQB8g7zEP+QABD/ EPMQ/5AAD/8B9BHzD/+QAA7/AfQT8w7/kAAO/xXzDf+QAA7/FfMN/5AADf8B9BXzDf+QAA3/FvMB9Az/ kAAN/xbzAfQM/5AADf8B9BXzDf+QAA3/AfQV8w3/kAAN/wH0FfMN/5AADf8B9BXzDf+QAA3/AfQV8w3/ kAAO/xXzDf+QAA7/FfMN/5AADv8S8wHyAvMN/5AADv8B9BPzAfQN/5AAD/8T8w7/kAAP/wH0EfMP/5AA EP8S8w7/kAAQ/wH0EPMP/5AAEf8B9A7zAfQP/5AAE/8B9AvzEf+QABX/AfQF8wL0E/+QADD/kAAw/5AA MP+QAAFCAU0BPgcAAT4DAAEoAwABwAMAATADAAEBAQABAQUAAYABBBYAA///AP8A/wD/AIUACw==</value> </data></root>

MainForm.cs

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.IO;using System.Linq;using System.Net;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;using System.Configuration;using System.Collections; namespace SuiteSocialClientApp{ public partial class MainForm : Form {

SuiteSocial API Guide

Appendix 29

public string UserId { get; set; } public string UserName { get; set; } List<SuiteSocialColleague> m_following = null List<SuiteSocialColleague> m_followers = null bool m_IsColleaguePosts = false; string m_colleagueUserId = ""; Hashtable m_hashPosts = new Hashtable(); public MainForm() { InitializeComponent(); } private void MainForm_Load(object sender, EventArgs e) { // Update the title with user info this.Text += " - " + UserName; // Load channels LoadChannels(); // Load colleagues only if user is specified if (UserId != "ALL") { // Load colleagues LoadFollowing(); LoadFollowers(); // Select following by default cboColleagueTypes.SelectedIndex = 0; } } private void LoadChannels() { try { // Initialize the RESTlet URL with the desired parameters string url = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=367&deploy=1" + "&resource=channels&action=get"; // Initialize authentication credentials string authHeader = GetAuthenticationHeader(); // Send a request to the RESTlet, providing the URL and authentication header string jsonString = RequestRESTlet(url, authHeader); // Convert JSON string to the appropriate object // Note: SuiteSocialChannel is a custom class whose structure mimics that of the channel JSON object. See documentation for details on the object. // List<> is used here because the result of getChannels is an array of channels. List<SuiteSocialChannel> channels = (List<SuiteSocialChannel>)ParseJSONString(jsonString, typeof(List<SuiteSocialChannel>));

/* Begin using the retrieved object into the UI */

SuiteSocial API Guide

Appendix 30

// Load channels cboChannels.Items.Clear(); // Add public channel ComboBoxItem cboItem = new ComboBoxItem(); cboItem.Text = "Public"; cboItem.Value = "0"; cboChannels.Items.Add(cboItem); for (int i = 0; i < channels.Count; i++) { // Get each channel SuiteSocialChannel channel = channels[i]; // Add item to list cboItem = new ComboBoxItem(); cboItem.Text = channel.name; cboItem.Value = channel.id; cboChannels.Items.Add(cboItem); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void LoadFollowing() { try { // Initialize the RESTlet URL with the desired parameters string url = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=367&deploy=1" + "&resource=colleagues&action=get&userId=" + UserId; // Initialize authentication credentials string authHeader = GetAuthenticationHeader(); // Send a request to the restlet, providing the url and authentication header string jsonString = RequestRESTlet(url, authHeader); // Convert JSON string to the appropriate object // Note: SuiteSocialColleague is a custom class whose structure mimics that of the colleague (following/follower) JSON object. See documentation for details on the object. // List<> is used here because the result of getFollowing is an array of colleagues. m_following = (List<SuiteSocialColleague>)ParseJSONString(jsonString, typeof(List<SuiteSocialColleague>));

/* Begin using the retrieved object into the UI */ } catch (Exception ex) { MessageBox.Show(ex.Message);

SuiteSocial API Guide

Appendix 31

} } private void LoadFollowers() { try { // Initialize the RESTlet URL with the desired parameters string url = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=367&deploy=1" + "&resource=followers&get=get&userId=" + UserId; // Initialize authentication credentials string authHeader = GetAuthenticationHeader(); // Send a request to the RESTlet, providing the URL and authentication header string jsonString = RequestRESTlet(url, authHeader); // Convert JSON string to the appropriate object // Note: SuiteSocialColleague is a custom class whose structure mimics that of the colleague (following/follower) JSON object. See documentation for details on the object. // List<> is used here because the result of getFollowers is an array of colleagues. m_followers = (List<SuiteSocialColleague>)ParseJSONString(jsonString, typeof(List<SuiteSocialColleague>));

/* Begin using the retrieved object into the UI */ } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void LoadFollowingList() { try { if (m_following == null) return; // Load following list listColleagues.Items.Clear(); for (int i = 0; i < m_following.Count; i++) { // Get each user SuiteSocialColleague colleague = m_following[i]; // Add item to list ListViewItem lvItem = new ListViewItem(colleague.name, 0); lvItem.Tag = colleague.id; lvItem.SubItems.Add(colleague.title ?? ""); lvItem.SubItems.Add(colleague.department ?? ""); lvItem.SubItems.Add(colleague.lastStatus ?? ""); listColleagues.Items.Add(lvItem); }

SuiteSocial API Guide

Appendix 32

} catch (Exception ex) { MessageBox.Show(ex.Message); } } private void LoadFollowersList() { try { if (m_followers == null) return; // Load followers list listColleagues.Items.Clear(); for (int i = 0; i < m_followers.Count; i++) { // Get each user SuiteSocialColleague colleague = m_followers[i]; // Add item to list ListViewItem lvItem = new ListViewItem(colleague.name, 0); lvItem.Tag = colleague.id; lvItem.SubItems.Add(colleague.title ?? ""); lvItem.SubItems.Add(colleague.department ?? ""); lvItem.SubItems.Add(colleague.lastStatus ?? ""); listColleagues.Items.Add(lvItem); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void LoadPosts(string channelId, string searchString) { try { // Initialize the RESTlet URL with the desired parameters string url = "https://rest.netsuite.com/app/site/hosting/restlet.nl?script=367&deploy=1" + "&resource=posts&action=get&viewAsUserId=" + UserId; // Check if a channel was specified if (channelId != "" && channelId != "0") { // Include channel filter to get only the posts on that channel url += "&channelId=" + channelId; } // Check if a search string was specified if (searchString != "") { // Include a search string to get only the posts containing that string url += "&searchString=" + searchString;

SuiteSocial API Guide

Appendix 33

} // Initialize authentication credentials string authHeader = GetAuthenticationHeader(); // Send a request to the RESTlet, providing the URL and authentication header string jsonString = RequestRESTlet(url, authHeader); // Convert JSON string to the appropriate object // Note: SuiteSocialColleague is a custom class whose structure mimics that of the colleague (following/follower) JSON object. See documentation for details on the object. // List<> is used here because the result of getFollowers is an array of colleagues. List<SuiteSocialPost> posts = (List<SuiteSocialPost>)ParseJSONString(jsonString, typeof(List<SuiteSocialPost>));

/* Begin using the retrieved object into the UI */ // Reset hash to keep the new set of posts m_hashPosts.Clear(); // Load the posts list listPosts.Items.Clear(); for (int i = 0; i < posts.Count; i++) { // Get each post SuiteSocialPost post = posts[i]; // Add item to the list ListViewItem lvItem = new ListViewItem(post.dateCreated, 0); lvItem.Tag = post.id; lvItem.SubItems.Add(post.message); lvItem.SubItems.Add(post.sender.name); lvItem.SubItems.Add(post.sender.profilePhotoUrl); lvItem.SubItems.Add(post.channel.name); lvItem.SubItems.Add(post.isPrivate.ToString()); lvItem.SubItems.Add(post.recipient != null ? post.recipient.name : ""); lvItem.SubItems.Add(post.record != null ? post.record.name : ""); lvItem.SubItems.Add(post.record != null ? post.record.typeName : ""); lvItem.SubItems.Add(post.file != null ? post.file.name : ""); lvItem.SubItems.Add(post.file != null ? post.file.url : ""); lvItem.SubItems.Add(post.comments.Count.ToString()); listPosts.Items.Add(lvItem); // Add to hash m_hashPosts.Add(post.id, post); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void cboColleagueTypes_SelectedIndexChanged(object sender, EventArgs e) {

SuiteSocial API Guide

Appendix 34

// Check which list to show — the following list or the followers list if (cboColleagueTypes.SelectedIndex == 0) { LoadFollowingList(); } else { LoadFollowersList(); } } private void btnRefresh_Click(object sender, EventArgs e) { // Check for a channel, if not viewing colleague posts string channelId = ""; if (!m_IsColleaguePosts) { // Check if a channel is selected if (cboChannels.SelectedIndex == -1) { MessageBox.Show("Please select a channel.", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // Get channel channelId = ((ComboBoxItem)cboChannels.SelectedItem).Value.ToString(); } // Get search string string searchString = txtSearch.Text; // Load posts LoadPosts(channelId, searchString); } private void mnuColleague_Opening(object sender, CancelEventArgs e) { // Do not open if no colleague is selected if (listColleagues.SelectedItems.Count == 0) { e.Cancel = true; return; } //TEMP: View Colleague Posts not yet supported e.Cancel = true; } private void mnuViewPosts_Click(object sender, EventArgs e) { // Get selected colleague ListViewItem lvItem = listColleagues.SelectedItems[0]; m_colleagueUserId = lvItem.Tag.ToString(); // Set flag

SuiteSocial API Guide

Appendix 35

m_IsColleaguePosts = true; // clear channel selection cboChannels.SelectedIndex = -1; // Get search string string searchString = txtSearch.Text; // Load colleague posts //Note: View Colleague Posts not yet supported } private void cboChannels_SelectedIndexChanged(object sender, EventArgs e) { // Reset flag if (cboChannels.SelectedIndex >= 0) { m_IsColleaguePosts = false; m_colleagueUserId = ""; } } private void mnuPost_Opening(object sender, CancelEventArgs e) { // Do not open if no post is selected if (listPosts.SelectedItems.Count == 0) { e.Cancel = true; return; } } private void mnuViewPost_Click(object sender, EventArgs e) { // Get selected post ListViewItem lvItem = listPosts.SelectedItems[0]; string postId = lvItem.Tag.ToString(); // Get the post object from hash SuiteSocialPost post = (SuiteSocialPost)m_hashPosts[postId]; // Show post form PostForm frm = new PostForm(); frm.Post = post; frm.ShowDialog(); } private void mnuExit_Click(object sender, EventArgs e) { // Close this window this.Close(); } private string GetAuthenticationHeader() { // Initialize authentication credentials

SuiteSocial API Guide

Appendix 36

var accountId = "1234567"; // Company Account ID var email = "[email protected]"; // SuiteSocial Integration User Email var password = "password123"; // SuiteSocial Integration User Password var role = "1001"; // SuiteSocial Integration Role ID string authHeader = "NLAuth nlauth_account=" + accountId + ", nlauth_email=" + email + ", nlauth_signature=" + password + ", nlauth_role=" + role; // Return authentication header string return authHeader; } private string RequestRESTlet(string url, string authHeader) { try { // Initialize request var request = WebRequest.Create(url); request.ContentType = "application/json; charset=utf-8"; request.Headers.Add("Authorization", authHeader); request.Timeout = 600000; // User-defined timeout (ms) // Call the RESTlet and get a response var response = (HttpWebResponse)request.GetResponse(); // Get the JSON string result string jsonString = ""; using (var sr = new StreamReader(response.GetResponseStream())) { jsonString = sr.ReadToEnd(); } // Check for an empty string if (jsonString == "") { throw new Exception("JSON string is empty."); } // Return JSON string return jsonString; } catch (WebException ex) { var stream = ex.Response.GetResponseStream(); using (var reader = new StreamReader(stream)) { var strError = reader.ReadToEnd(); // Get the error defined and throw it // Note: SuiteSocialError is a custom class whose structure mimics that of the error JSON object. // error = { "error" : { "code" : "ERROR_CODE", "message" : "This is an error message." } } SuiteSocialError error = (SuiteSocialError)ParseJSONString(strError, typeof(SuiteSocialError)); throw new Exception(error.error.message); } }

SuiteSocial API Guide

Appendix 37

catch (Exception ex) { throw ex; } } private object ParseJSONString(string jsonString, Type type) { // Parses the JSON string and converts it into an object // Makes use of Json.NET -- a JSON framework for .NET return Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString, type); } }}

MainForm.Designer.cs (auto-generated)

namespace SuiteSocialClientApp{ partial class MainForm { /// <summary> /// Required designer variable /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name= "disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.mnuMain = new System.Windows.Forms.MenuStrip(); this.mnuFile = new System.Windows.Forms.ToolStripMenuItem(); this.mnuExit = new System.Windows.Forms.ToolStripMenuItem(); this.splitMain = new System.Windows.Forms.SplitContainer(); this.splitColleagues = new System.Windows.Forms.SplitContainer(); this.cboColleagueTypes = new System.Windows.Forms.ComboBox();

SuiteSocial API Guide

Appendix 38

this.lblColleagues = new System.Windows.Forms.Label(); this.listColleagues = new System.Windows.Forms.ListView(); this.colName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colTitle = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colDept = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colStatus = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.mnuColleague = new System.Windows.Forms.ContextMenuStrip(this.components); this.mnuViewPosts = new System.Windows.Forms.ToolStripMenuItem(); this.splitNewsfeed = new System.Windows.Forms.SplitContainer(); this.btnRefresh = new System.Windows.Forms.Button(); this.txtSearch = new System.Windows.Forms.TextBox(); this.lblSearch = new System.Windows.Forms.Label(); this.cboChannels = new System.Windows.Forms.ComboBox(); this.lblChannel = new System.Windows.Forms.Label(); this.listPosts = new System.Windows.Forms.ListView(); this.colDate = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colMessage = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colSender = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colSenderProfilePhotoUrl = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colChannel = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colIsPrivate = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colRecipient = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colRecord = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colRecordType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colFilename = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colFileUrl = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colComments = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.mnuPost = new System.Windows.Forms.ContextMenuStrip(this.components); this.mnuViewPost = new System.Windows.Forms.ToolStripMenuItem(); this.mnuMain.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitMain)).BeginInit(); this.splitMain.Panel1.SuspendLayout(); this.splitMain.Panel2.SuspendLayout(); this.splitMain.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitColleagues)).BeginInit(); this.splitColleagues.Panel1.SuspendLayout(); this.splitColleagues.Panel2.SuspendLayout(); this.splitColleagues.SuspendLayout(); this.mnuColleague.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitNewsfeed)).BeginInit(); this.splitNewsfeed.Panel1.SuspendLayout(); this.splitNewsfeed.Panel2.SuspendLayout(); this.splitNewsfeed.SuspendLayout(); this.mnuPost.SuspendLayout(); this.SuspendLayout(); // // mnuMain // this.mnuMain.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.mnuFile}); this.mnuMain.Location = new System.Drawing.Point(0, 0); this.mnuMain.Name = "mnuMain"; this.mnuMain.Size = new System.Drawing.Size(784, 24); this.mnuMain.TabIndex = 0;

SuiteSocial API Guide

Appendix 39

this.mnuMain.Text = "mnuMain"; // // mnuFile // this.mnuFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.mnuExit}); this.mnuFile.Name = "mnuFile"; this.mnuFile.Size = new System.Drawing.Size(37, 20); this.mnuFile.Text = "&File"; // // mnuExit // this.mnuExit.Name = "mnuExit"; this.mnuExit.Size = new System.Drawing.Size(152, 22); this.mnuExit.Text = "E&xit"; this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click); // // splitMain // this.splitMain.Dock = System.Windows.Forms.DockStyle.Fill; this.splitMain.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; this.splitMain.Location = new System.Drawing.Point(0, 24); this.splitMain.Name = "splitMain"; // // splitMain.Panel1 // this.splitMain.Panel1.Controls.Add(this.splitColleagues); // // splitMain.Panel2 // this.splitMain.Panel2.Controls.Add(this.splitNewsfeed); this.splitMain.Size = new System.Drawing.Size(784, 438); this.splitMain.SplitterDistance = 200; this.splitMain.TabIndex = 1; // // splitColleagues // this.splitColleagues.Dock = System.Windows.Forms.DockStyle.Fill; this.splitColleagues.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; this.splitColleagues.IsSplitterFixed = true; this.splitColleagues.Location = new System.Drawing.Point(0, 0); this.splitColleagues.Name = "splitColleagues"; this.splitColleagues.Orientation = System.Windows.Forms.Orientation.Horizontal; // // splitColleagues.Panel1 // this.splitColleagues.Panel1.Controls.Add(this.cboColleagueTypes); this.splitColleagues.Panel1.Controls.Add(this.lblColleagues); // // splitColleagues.Panel2 // this.splitColleagues.Panel2.Controls.Add(this.listColleagues); this.splitColleagues.Size = new System.Drawing.Size(200, 438); this.splitColleagues.TabIndex = 0; //

SuiteSocial API Guide

Appendix 40

// cboColleagueTypes // this.cboColleagueTypes.Dock = System.Windows.Forms.DockStyle.Bottom; this.cboColleagueTypes.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cboColleagueTypes.FormattingEnabled = true; this.cboColleagueTypes.Items.AddRange(new object[] { "Following", "Followers"}); this.cboColleagueTypes.Location = new System.Drawing.Point(0, 29); this.cboColleagueTypes.Name = "cboColleagueTypes"; this.cboColleagueTypes.Size = new System.Drawing.Size(200, 21); this.cboColleagueTypes.TabIndex = 1; this.cboColleagueTypes.SelectedIndexChanged += new System.EventHandler(this.cboColleagueTypes_SelectedIndexChanged); // // lblColleagues // this.lblColleagues.AutoSize = true; this.lblColleagues.Font = new System.Drawing.Font("Microsoft Sans Serif", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblColleagues.Location = new System.Drawing.Point(3, 6); this.lblColleagues.Name = "lblColleagues"; this.lblColleagues.Size = new System.Drawing.Size(82, 18); this.lblColleagues.TabIndex = 0; this.lblColleagues.Text = "Colleagues"; // // listColleagues // this.listColleagues.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.colName, this.colTitle, this.colDept, this.colStatus}); this.listColleagues.ContextMenuStrip = this.mnuColleague; this.listColleagues.Dock = System.Windows.Forms.DockStyle.Fill; this.listColleagues.FullRowSelect = true; this.listColleagues.GridLines = true; this.listColleagues.Location = new System.Drawing.Point(0, 0); this.listColleagues.MultiSelect = false; this.listColleagues.Name = "listColleagues"; this.listColleagues.Size = new System.Drawing.Size(200, 384); this.listColleagues.TabIndex = 0; this.listColleagues.UseCompatibleStateImageBehavior = false; this.listColleagues.View = System.Windows.Forms.View.Details; // // colName // this.colName.Text = "Name"; this.colName.Width = 120; // // colTitle // this.colTitle.Text = "Title"; this.colTitle.Width = 100; //

SuiteSocial API Guide

Appendix 41

// colDept // this.colDept.Text = "Department"; this.colDept.Width = 100; // // colStatus // this.colStatus.Text = "Last Status"; this.colStatus.Width = 120; // // mnuColleague // this.mnuColleague.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.mnuViewPosts}); this.mnuColleague.Name = "mnuColleague"; this.mnuColleague.Size = new System.Drawing.Size(131, 26); this.mnuColleague.Opening += new System.ComponentModel.CancelEventHandler(this.mnuColleague_Opening); // // mnuViewPosts // this.mnuViewPosts.Name = "mnuViewPosts"; this.mnuViewPosts.Size = new System.Drawing.Size(130, 22); this.mnuViewPosts.Text = "View &Posts"; this.mnuViewPosts.Click += new System.EventHandler(this.mnuViewPosts_Click); // // splitNewsfeed // this.splitNewsfeed.Dock = System.Windows.Forms.DockStyle.Fill; this.splitNewsfeed.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; this.splitNewsfeed.IsSplitterFixed = true; this.splitNewsfeed.Location = new System.Drawing.Point(0, 0); this.splitNewsfeed.Name = "splitNewsfeed"; this.splitNewsfeed.Orientation = System.Windows.Forms.Orientation.Horizontal; // // splitNewsfeed.Panel1 // this.splitNewsfeed.Panel1.Controls.Add(this.btnRefresh); this.splitNewsfeed.Panel1.Controls.Add(this.txtSearch); this.splitNewsfeed.Panel1.Controls.Add(this.lblSearch); this.splitNewsfeed.Panel1.Controls.Add(this.cboChannels); this.splitNewsfeed.Panel1.Controls.Add(this.lblChannel); // // splitNewsfeed.Panel2 // this.splitNewsfeed.Panel2.Controls.Add(this.listPosts); this.splitNewsfeed.Size = new System.Drawing.Size(580, 438); this.splitNewsfeed.TabIndex = 0; // // btnRefresh // this.btnRefresh.Location = new System.Drawing.Point(414, 27); this.btnRefresh.Name = "btnRefresh"; this.btnRefresh.Size = new System.Drawing.Size(100, 23); this.btnRefresh.TabIndex = 6; this.btnRefresh.Text = "Refresh";

SuiteSocial API Guide

Appendix 42

this.btnRefresh.UseVisualStyleBackColor = true; this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click); // // txtSearch // this.txtSearch.Location = new System.Drawing.Point(208, 29); this.txtSearch.Name = "txtSearch"; this.txtSearch.Size = new System.Drawing.Size(200, 20); this.txtSearch.TabIndex = 5; // // lblSearch // this.lblSearch.AutoSize = true; this.lblSearch.Font = new System.Drawing.Font("Microsoft Sans Serif", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblSearch.Location = new System.Drawing.Point(208, 6); this.lblSearch.Name = "lblSearch"; this.lblSearch.Size = new System.Drawing.Size(126, 18); this.lblSearch.TabIndex = 4; this.lblSearch.Text = "Search news feed"; // // cboChannels // this.cboChannels.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cboChannels.FormattingEnabled = true; this.cboChannels.Location = new System.Drawing.Point(2, 29); this.cboChannels.Name = "cboChannels"; this.cboChannels.Size = new System.Drawing.Size(200, 21); this.cboChannels.TabIndex = 3; this.cboChannels.SelectedIndexChanged += new System.EventHandler(this.cboChannels_SelectedIndexChanged); // // lblChannel // this.lblChannel.AutoSize = true; this.lblChannel.Font = new System.Drawing.Font("Microsoft Sans Serif", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblChannel.Location = new System.Drawing.Point(3, 6); this.lblChannel.Name = "lblChannel"; this.lblChannel.Size = new System.Drawing.Size(62, 18); this.lblChannel.TabIndex = 2; this.lblChannel.Text = "Channel"; // // listPosts // this.listPosts.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.colDate, this.colMessage, this.colSender, this.colSenderProfilePhotoUrl, this.colChannel, this.colIsPrivate, this.colRecipient, this.colRecord, this.colRecordType,

SuiteSocial API Guide

Appendix 43

this.colFilename, this.colFileUrl, this.colComments}); this.listPosts.ContextMenuStrip = this.mnuPost; this.listPosts.Dock = System.Windows.Forms.DockStyle.Fill; this.listPosts.FullRowSelect = true; this.listPosts.GridLines = true; this.listPosts.Location = new System.Drawing.Point(0, 0); this.listPosts.MultiSelect = false; this.listPosts.Name = "listPosts"; this.listPosts.Size = new System.Drawing.Size(580, 384); this.listPosts.TabIndex = 0; this.listPosts.UseCompatibleStateImageBehavior = false; this.listPosts.View = System.Windows.Forms.View.Details; // // colDate // this.colDate.Text = "DateTime UTC"; this.colDate.Width = 100; // // colMessage // this.colMessage.Text = "Message"; this.colMessage.Width = 300; // // colSender // this.colSender.Text = "Sender"; this.colSender.Width = 100; // // colSenderProfilePhotoUrl // this.colSenderProfilePhotoUrl.Text = "Profile Photo URL"; this.colSenderProfilePhotoUrl.Width = 100; // // colChannel // this.colChannel.Text = "Channel"; this.colChannel.Width = 100; // // colIsPrivate // this.colIsPrivate.Text = "Is Private"; // // colRecipient // this.colRecipient.Text = "Recipient"; this.colRecipient.Width = 100; // // colRecord // this.colRecord.Text = "Record Name"; this.colRecord.Width = 100; // // colRecordType

SuiteSocial API Guide

Appendix 44

// this.colRecordType.Text = "Record Type"; this.colRecordType.Width = 100; // // colFilename // this.colFilename.Text = "File Name"; this.colFilename.Width = 100; // // colFileUrl // this.colFileUrl.Text = "File URL"; this.colFileUrl.Width = 120; // // colComments // this.colComments.Text = "Comments Count"; this.colComments.Width = 100; // // mnuPost // this.mnuPost.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.mnuViewPost}); this.mnuPost.Name = "mnuPost"; this.mnuPost.Size = new System.Drawing.Size(126, 26); this.mnuPost.Opening += new System.ComponentModel.CancelEventHandler(this.mnuPost_Opening); // // mnuViewPost // this.mnuViewPost.Name = "mnuViewPost"; this.mnuViewPost.Size = new System.Drawing.Size(125, 22); this.mnuViewPost.Text = "&View Post"; this.mnuViewPost.Click += new System.EventHandler(this.mnuViewPost_Click); // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(784, 462); this.Controls.Add(this.splitMain); this.Controls.Add(this.mnuMain); this.MaximizeBox = false; this.Name = "MainForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "SuiteSocial Client App"; this.Load += new System.EventHandler(this.MainForm_Load); this.mnuMain.ResumeLayout(false); this.mnuMain.PerformLayout(); this.splitMain.Panel1.ResumeLayout(false); this.splitMain.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitMain)).EndInit(); this.splitMain.ResumeLayout(false); this.splitColleagues.Panel1.ResumeLayout(false); this.splitColleagues.Panel1.PerformLayout(); this.splitColleagues.Panel2.ResumeLayout(false);

SuiteSocial API Guide

Appendix 45

((System.ComponentModel.ISupportInitialize)(this.splitColleagues)).EndInit(); this.splitColleagues.ResumeLayout(false); this.mnuColleague.ResumeLayout(false); this.splitNewsfeed.Panel1.ResumeLayout(false); this.splitNewsfeed.Panel1.PerformLayout(); this.splitNewsfeed.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitNewsfeed)).EndInit(); this.splitNewsfeed.ResumeLayout(false); this.mnuPost.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.MenuStrip mnuMain; private System.Windows.Forms.ToolStripMenuItem mnuFile; private System.Windows.Forms.ToolStripMenuItem mnuExit; private System.Windows.Forms.SplitContainer splitMain; private System.Windows.Forms.SplitContainer splitColleagues; private System.Windows.Forms.Label lblColleagues; private System.Windows.Forms.ComboBox cboColleagueTypes; private System.Windows.Forms.ListView listColleagues; private System.Windows.Forms.ColumnHeader colName; private System.Windows.Forms.ColumnHeader colTitle; private System.Windows.Forms.ColumnHeader colDept; private System.Windows.Forms.ColumnHeader colStatus; private System.Windows.Forms.SplitContainer splitNewsfeed; private System.Windows.Forms.Label lblChannel; private System.Windows.Forms.ComboBox cboChannels; private System.Windows.Forms.Label lblSearch; private System.Windows.Forms.TextBox txtSearch; private System.Windows.Forms.Button btnRefresh; private System.Windows.Forms.ListView listPosts; private System.Windows.Forms.ColumnHeader colDate; private System.Windows.Forms.ColumnHeader colMessage; private System.Windows.Forms.ColumnHeader colSender; private System.Windows.Forms.ColumnHeader colSenderProfilePhotoUrl; private System.Windows.Forms.ColumnHeader colChannel; private System.Windows.Forms.ColumnHeader colIsPrivate; private System.Windows.Forms.ColumnHeader colRecipient; private System.Windows.Forms.ColumnHeader colRecord; private System.Windows.Forms.ColumnHeader colRecordType; private System.Windows.Forms.ColumnHeader colFilename; private System.Windows.Forms.ColumnHeader colFileUrl; private System.Windows.Forms.ColumnHeader colComments; private System.Windows.Forms.ContextMenuStrip mnuColleague; private System.Windows.Forms.ToolStripMenuItem mnuViewPosts; private System.Windows.Forms.ContextMenuStrip mnuPost; private System.Windows.Forms.ToolStripMenuItem mnuViewPost; }}

SuiteSocial API Guide

Appendix 46

MainForm.resx (auto-generated)

<?xml version="1.0" encoding="utf-8"?> <root> <!-- Microsoft ResX Schema Version 2.0 The primary goals of this format is to allow a simple XML format that is mostly human readable. The generation and parsing of the various data types are done through the TypeConverter classes associated with the data types. Example: ... ado.net/XML headers & schema ... <resheader name="resmimetype">text/microsoft-resx</resheader> <resheader name="version">2.0</resheader> <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> <value>[base64 mime encoded serialized .NET Framework object]</value> </data> <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> <comment>This is a comment</comment> </data> There are any number of "resheader" rows that contain simple name/value pairs. Each data row contains a name, and value. The row also contains a type or mimetype. Type corresponds to a .NET class that support text/value conversion through the TypeConverter architecture. Classes that don't support this are serialized and stored with the mimetype set. The mimetype is used for serialized objects, and tells the ResXResourceReader how to depersist the object. This is currently not extensible. For a given mimetype the value must be set accordingly: Note - application/x-microsoft.net.object.binary.base64 is the format that the ResXResourceWriter will generate, however the reader can read any of the formats listed below. mimetype: application/x-microsoft.net.object.binary.base64 value : The object must be serialized with : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : and then encoded with base64 encoding. mimetype: application/x-microsoft.net.object.soap.base64

SuiteSocial API Guide

Appendix 47

value : The object must be serialized with : System.Runtime.Serialization.Formatters.Soap.SoapFormatter : and then encoded with base64 encoding. mimetype: application/x-microsoft.net.object.bytearray.base64 value : The object must be serialized into a byte array : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> <xsd:schema id="root" xmlns="" xmlns:xsd=http://www.w3.org/2001/XMLSchema"" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:element name="root" msdata:IsDataSet="true"> <xsd:complexType> <xsd:choice maxOccurs="unbounded"> <xsd:element name="metadata"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" /> </xsd:sequence> <xsd:attribute name="name" use="required" type="xsd:string" /> <xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="mimetype" type="xsd:string" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="assembly"> <xsd:complexType> <xsd:attribute name="alias" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" /> </xsd:complexType> </xsd:element> <xsd:element name="data"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="resheader"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" /> </xsd:complexType> </xsd:element> </xsd:choice> </xsd:complexType> </xsd:element>

SuiteSocial API Guide

Appendix 48

</xsd:schema> <resheader name="resmimetype"> <value>text/microsoft-resx</value> </resheader> <resheader name="version"> <value>2.0</value> </resheader> <resheader name="reader"> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <resheader name="writer"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <metadata name="mnuMain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>17, 17</value> </metadata> <metadata name="mnuColleague.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>121, 17</value> </metadata> <metadata name="mnuPost.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>252, 17</value> </metadata> <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <value>56</value> </metadata></root>

PostForm.cs

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms; namespace SuiteSocialClientApp{ public partial class PostForm : Form { public SuiteSocialPost Post { get; set; } public PostForm() { InitializeComponent(); }

SuiteSocial API Guide

Appendix 49

private void PostForm_Load(object sender, EventArgs e) { // Load details picProfile.ImageLocation = Post.sender.profilePhotoUrl; lblName.Text = Post.sender.name; lblDateTime.Text = Post.dateCreated; txtMessage.Text = Post.message; // Load comments listComments.Items.Clear(); for (int i = 0; i < Post.comments.Count; i++) { // Get each post SuiteSocialComment comment = Post.comments[i]; // Add item to list ListViewItem lvItem = new ListViewItem(comment.dateCreated, 0); lvItem.Tag = comment.id; lvItem.SubItems.Add(comment.message); lvItem.SubItems.Add(comment.sender.name); lvItem.SubItems.Add(comment.sender.profilePhotoUrl); lvItem.SubItems.Add(comment.file != null ? comment.file.name : ""); lvItem.SubItems.Add(comment.file != null ? comment.file.url : ""); listComments.Items.Add(lvItem); } } }}

PostForm.Designer.cs (auto-generated)

namespace SuiteSocialClientApp{ partial class PostForm { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code

SuiteSocial API Guide

Appendix 50

/// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.splitMain = new System.Windows.Forms.SplitContainer(); this.txtMessage = new System.Windows.Forms.TextBox(); this.lblDateTime = new System.Windows.Forms.Label(); this.lblName = new System.Windows.Forms.Label(); this.picProfile = new System.Windows.Forms.PictureBox(); this.listComments = new System.Windows.Forms.ListView(); this.colDateTime = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colMessage = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colSender = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colSenderProfilePhotoUrl = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colFile = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colFileUrl = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); ((System.ComponentModel.ISupportInitialize)(this.splitMain)).BeginInit(); this.splitMain.Panel1.SuspendLayout(); this.splitMain.Panel2.SuspendLayout(); this.splitMain.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.picProfile)).BeginInit(); this.SuspendLayout(); // // splitMain // this.splitMain.Dock = System.Windows.Forms.DockStyle.Fill; this.splitMain.Location = new System.Drawing.Point(0, 0); this.splitMain.Name = "splitMain"; this.splitMain.Orientation = System.Windows.Forms.Orientation.Horizontal; // // splitMain.Panel1 // this.splitMain.Panel1.Controls.Add(this.txtMessage); this.splitMain.Panel1.Controls.Add(this.lblDateTime); this.splitMain.Panel1.Controls.Add(this.lblName); this.splitMain.Panel1.Controls.Add(this.picProfile); // // splitMain.Panel2 // this.splitMain.Panel2.Controls.Add(this.listComments); this.splitMain.Size = new System.Drawing.Size(418, 249); this.splitMain.SplitterDistance = 99; this.splitMain.TabIndex = 0; // // txtMessage // this.txtMessage.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.txtMessage.Location = new System.Drawing.Point(60, 44); this.txtMessage.Multiline = true; this.txtMessage.Name = "txtMessage"; this.txtMessage.ReadOnly = true;

SuiteSocial API Guide

Appendix 51

this.txtMessage.Size = new System.Drawing.Size(355, 52); this.txtMessage.TabIndex = 3; // // lblDateTime // this.lblDateTime.AutoSize = true; this.lblDateTime.Location = new System.Drawing.Point(60, 27); this.lblDateTime.Name = "lblDateTime"; this.lblDateTime.Size = new System.Drawing.Size(122, 13); this.lblDateTime.TabIndex = 2; this.lblDateTime.Text = "Thu 4/30/2015 4:40 pm"; // // lblName // this.lblName.AutoSize = true; this.lblName.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblName.ForeColor = System.Drawing.Color.RoyalBlue; this.lblName.Location = new System.Drawing.Point(60, 3); this.lblName.Name = "lblName"; this.lblName.Size = new System.Drawing.Size(120, 20); this.lblName.TabIndex = 1; this.lblName.Text = "Ems Dev Test"; // // picProfile // this.picProfile.ImageLocation = "https://system.netsuite.com/core/media/media.nl?id=615641&c=3948745&h=f45d0e53be3" + "26acc3d86"; this.picProfile.Location = new System.Drawing.Point(3, 3); this.picProfile.Name = "picProfile"; this.picProfile.Size = new System.Drawing.Size(50, 50); this.picProfile.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; this.picProfile.TabIndex = 0; this.picProfile.TabStop = false; // // listComments // this.listComments.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.colDateTime, this.colMessage, this.colSender, this.colSenderProfilePhotoUrl, this.colFile, this.colFileUrl}); this.listComments.Dock = System.Windows.Forms.DockStyle.Fill; this.listComments.FullRowSelect = true; this.listComments.GridLines = true; this.listComments.Location = new System.Drawing.Point(0, 0); this.listComments.Name = "listComments"; this.listComments.Size = new System.Drawing.Size(418, 146); this.listComments.TabIndex = 0; this.listComments.UseCompatibleStateImageBehavior = false; this.listComments.View = System.Windows.Forms.View.Details; //

SuiteSocial API Guide

Appendix 52

// colDateTime // this.colDateTime.Text = "DateTime UTC"; this.colDateTime.Width = 100; // // colMessage // this.colMessage.Text = "Message"; this.colMessage.Width = 200; // // colSender // this.colSender.Text = "Sender"; this.colSender.Width = 100; // // colSenderProfilePhotoUrl // this.colSenderProfilePhotoUrl.Text = "Profile Photo URL"; this.colSenderProfilePhotoUrl.Width = 100; // // colFile // this.colFile.Text = "File Name"; this.colFile.Width = 100; // // colFileUrl // this.colFileUrl.Text = "File URL"; this.colFileUrl.Width = 100; // // PostForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(418, 249); this.Controls.Add(this.splitMain); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "PostForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "SuiteSocial Client App"; this.Load += new System.EventHandler(this.PostForm_Load); this.splitMain.Panel1.ResumeLayout(false); this.splitMain.Panel1.PerformLayout(); this.splitMain.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitMain)).EndInit(); this.splitMain.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.picProfile)).EndInit(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.SplitContainer splitMain; private System.Windows.Forms.PictureBox picProfile;

SuiteSocial API Guide

Appendix 53

private System.Windows.Forms.Label lblName; private System.Windows.Forms.Label lblDateTime; private System.Windows.Forms.TextBox txtMessage; private System.Windows.Forms.ListView listComments; private System.Windows.Forms.ColumnHeader colDateTime; private System.Windows.Forms.ColumnHeader colMessage; private System.Windows.Forms.ColumnHeader colSender; private System.Windows.Forms.ColumnHeader colSenderProfilePhotoUrl; private System.Windows.Forms.ColumnHeader colFile; private System.Windows.Forms.ColumnHeader colFileUrl; }}

PostForm.resx (auto-generated)

<?xml version="1.0" encoding="utf-8?><root> <!-- Microsoft ResX Schema Version 2.0 The primary goals of this format is to allow a simple XML format that is mostly human readable. The generation and parsing of the various data types are done through the TypeConverter classes associated with the data types. Example: ... ado.net/XML headers & schema ... <resheader name="resmimetype">text/microsoft-resx</resheader> <resheader name="version">2.0</resheader> <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> <value>[base64 mime encoded serialized .NET Framework object]</value> </data> <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> <comment>This is a comment</comment> </data>

There are any number of "resheader" rows that contain simple name/value pairs. Each data row contains a name, and value. The row also contains a type or mimetype. Type corresponds to a .NET class that support text/value conversion through the TypeConverter architecture. Classes that don't support this are serialized and stored with the mimetype set. The mimetype is used for serialized objects, and tells the

SuiteSocial API Guide

Appendix 54

ResXResourceReader how to depersist the object. This is currently not extensible. For a given mimetype the value must be set accordingly: Note - application/x-microsoft.net.object.binary.base64 is the format that the ResXResourceWriter will generate, however the reader can read any of the formats listed below. mimetype: application/x-microsoft.net.object.binary.base64 value : The object must be serialized with : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : and then encoded with base64 encoding. mimetype: application/x-microsoft.net.object.soap.base64 value : The object must be serialized with : System.Runtime.Serialization.Formatters.Soap.SoapFormatter : and then encoded with base64 encoding. mimetype: application/x-microsoft.net.object.bytearray.base64 value : The object must be serialized into a byte array : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:element name="root" msdata:IsDataSet="true"> <xsd:complexType> <xsd:choice maxOccurs="unbounded"> <xsd:element name="metadata"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" /> </xsd:sequence> <xsd:attribute name="name" use="required" type="xsd:string" /> <xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="mimetype" type="xsd:string" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="assembly"> <xsd:complexType> <xsd:attribute name="alias" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" /> </xsd:complexType> </xsd:element> <xsd:element name="data"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> <xsd:attribute ref="xml:space" />

SuiteSocial API Guide

Appendix 55

</xsd:complexType> </xsd:element> <xsd:element name="resheader"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" /> </xsd:complexType> </xsd:element> </xsd:choice> </xsd:complexType> </xsd:element> </xsd:schema> <resheader name="resmimetype"> <value>text/microsoft-resx</value> </resheader> <resheader name="version"> <value>2.0</value> </resheader> <resheader name="reader"> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <resheader name="writer"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader></root>

ComboBoxItem.cs

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; namespace SuiteSocialClientApp{ class ComboBoxItem { public string Text { get; set; } public object Value { get; set; } public override string ToString() { return Text; } }}

SuiteSocial API Guide

Appendix 56

SuiteSocialClasses.cs

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; namespace SuiteSocialClientApp{ /* Error object */ public class SuiteSocialError { public SuiteSocialErrorDetail error { get set; } } /* Error Detail object */ public class SuiteSocialErrorDetail { public string code { get set; } public string message { get set; } }

/* Channel object */ public class SuiteSocialChannel { public string id { get; set; } public string name { get; set; } public SuiteSocialSubsidiary subsidiary { get; set; } public List<SuiteSocialDepartment) departments { get; set; } public List<SuiteSocialLocation> locations { get; set; } public List<SuiteSocialRole> roles { get; set; } public List<SuiteSocialViewPermission> viewPermissionList { get; set; } public List<SuiteSocialCreatePermission> createPermissionList { get; set; } public bool isAutoSubscribe { get; set; } public bool isAllowComments { get; set; } public string externalId { get; set; } } /* Subsidiary object - part of the Channel object */ public class SuiteSocialSubsidiary { public string id { get; set; } public string name { get; set; } } /* Department object - part of the Channel object */ public class SuiteSocialDepartment { public string id { get; set; } public string name { get; set; } } /* Location object - part of the Channel object */ public class SuiteSocialLocation

SuiteSocial API Guide

Appendix 57

{ public string id { get; set; } public string name { get; set; } } /* Role object - part of the Channel object */ public class SuiteSocialRole { public string id { get; set; } public string name { get; set; } } /* View Permission object - part of the Channel object */ public class SuiteSocialViewPermission { public string id { get; set; } public string name { get; set; } } /* Create Permission object - part of the Channel object */ public class SuiteSocialCreatePermission { public string id { get; set; } public string name { get; set; } } /* Colleague object */ public class SuiteSocialColleague { public string id { get; set; } public string name { get; set; } public string title { get; set; } public string department { get; set; } public string lastStatus { get; set; } } /* User object */ public class SuiteSocialUser { public string id { get; set; } public string lastName { get; set; } public string firstName { get; set; } public string email { get; set; } public string userType { get; set; } public string title { get; set; } public SuiteSocialDepartment department { get; set; } } /* Post object */ public class SuiteSocialPost { public string id { get; set; } public string dateCreated { get; set; } public string externalId { get; set; } public string message { get; set; }

SuiteSocial API Guide

Appendix 58

public SuiteSocialSender sender { get; set; } public SuiteSocialChannelMin channel { get; set; } public bool isPrivate { get; set; } public SuiteSocialRecipient recipient { get; set; } public SuiteSocialRecord record { get; set; } public SuiteSocialFile file { get; set; } public List<string> permissionList { get; set; } public List<SuiteSocialComment> comments { get; set; }}

/* Sender object - part of the Post object */ public class SuiteSocialSender { public string id { get; set; } public string name { get; set; } public string profilePhotoUrl { get; set; } } /* Channel (minimal) object - part of the Post object */ public class SuiteSocialChannelMin { public string id { get; set; } public string name { get; set; } } /* Recipient object - part of the Post object */ public class SuiteSocialRecipient { public string id { get; set; } public string name { get; set; } } /* Record object - part of the Post object */ public class SuiteSocialRecord { public string id { get; set; } public string name { get; set; } public string recordURL { get; set; } public string recordTypeScriptId { get; set; } public string recordTypeName { get; set; } } /* File object - part of the Post object */ public class SuiteSocialFile { public string id { get; set; } public string name { get; set; } public string url { get; set; } public string imagePreviewUrl { get; set; } } /* Comment object - part of the Post object */ public class SuiteSocialComment { public string id { get; set; }

SuiteSocial API Guide

Appendix 59

public string message { get; set; } public SuiteSocialSender sender { get; set; } public string dateCreated { get; set; } public SuiteSocialFile file { get; set; } }}

SuiteSocial API Guide