238
Services API Guide Version 8.1 | October 11, 2013 For the most recent version of this document, visit our Relativity 8.1 Developers website .

Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Services API GuideVersion 8.1 | October 11, 2013

For the most recent version of this document, visit our Relativity 8.1 Developers website.

Page 2: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 2

Table of Contents

1 Relativity Services API 9

2 Configuring the Services API 9

2.1 Configuration prerequisites 9

2.2 SSL certificate for HTTPS 10

2.3 SSL certificate for HTTP or Net.TCP 10

2.4 Creating a self-signed certificate 12

2.5 Configuring HTTP or HTTPS connectivity to IIS 13

2.5.1 Verifying HTTP and HTTPS site bindings 14

2.6 Configuring Net.Pipe or Net.TCP connectivity 16

2.6.1 Enabling non-HTTP activation for WCF 16

2.6.2 Configuring the Net.Pipe or Net.TCP protocols 17

2.6.3 Verifying Net.Pipe and Net.TCP site bindings 18

2.6.4 Starting the Net.Pipe or Net.TCP listener adapter service 18

2.7Manually configuring the Services API for the Relativity platform 18

2.8 Configuration overrides 19

2.8.1 Setting client configuration overrides 19

2.8.2 Setting server configuration overrides 20

2.8.3 Server-side override values 22

2.8.4 Override configuration references 24

2.9 Testing the Services API configuration 25

2.9.1 Relativity Services API Diagnostic Tool 25

2.9.2 Viewing errors in the Services API Diagnostic Tool 28

2.10 Troubleshooting the Services API Configuration 30

2.10.1 Logging and debugging settings in the web.config 31

2.10.2 Production environment trace settings 31

2.10.3 Test environment trace settings 32

2.10.4 FailureAuditing Configuration Override Setting 33

2.10.5 Attempting to access .svc file causes keyset error 33

2.10.6 Catching EndpointType exceptions 34

2.10.7 Connection errors in load-balanced systems 34

2.10.8 Could not load type 'System.ServiceModel.Activation.HttpModule' 34

2.10.9 Erroneous calls to internal web server in load-balanced systems 35

2.10.10 HTTP error 404.17 or 404.3 35

2.10.11 Incorrect version of .NET enabled for application pools 36

Page 3: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 3

2.10.12Missing handler mappings 36

2.10.13 Pipe endpoint could not be found 38

2.10.14 System.ServiceModel.ExceptionDetail Error 38

2.10.15 Unable to access .svc file path in browser 38

2.10.16 Unable to access website 39

2.10.17 Updating the HTTP host header 39

3 Upgrading the Services API 39

3.1 Upgrading from Relativity 8 39

3.1.1 Upgrade guidelines for the Relativity 8.1 39

3.1.2 Upgrade guidelines from the Relativity 8.0.291.1 patch release 40

3.2 Upgrading from Relativity 7.5 41

3.3 Upgrading from Relativity 7.4 and earlier 42

4 Getting started with the Services API 42

4.1 Prerequisites for a development environment 42

4.2 Services API materials available in the SDK Installer 42

4.3 Setting up a project in Visual Studio 43

4.4 Creating a simple program with the Services API 45

4.4.1 Before you begin 45

4.4.2 Adding directives for required namespaces 46

4.4.3 Adding theMain method 46

4.4.4 Creating the RSAPIClient proxy 47

4.4.5 Querying for a Workspace 48

4.4.6 Creating a Relativity Dynamic Object DTO 49

4.4.7 Creating a Field on a RDO 50

4.4.8 Updating Fields on an RDO 51

4.4.9 Reading an RDO 52

4.4.10 Querying for RDOs 53

4.4.11 Deleting a Field on an RDO 54

4.4.12 Deleting an RDO 54

4.4.13 Exiting the program 55

4.4.14Writing success and failuremessages 55

4.4.15 Building and running the program 56

5 Basic Services API concepts 57

5.1 Services API features 57

5.2 Services API and the Relativity Platform 58

Page 4: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 4

5.3 Client Proxy 59

5.3.1 Backwards Compatibility 59

5.4 Deploying the Services API 60

5.4.1 Deploying the Services API 60

5.4.2 Transport protocols 60

5.4.3 AuthenticationType classes supported by the RSAPIClient 60

5.4.4 Summary of authentication methods and endpoint types 61

5.5 Creating the RSAPIClient proxy 61

5.5.1 RSAPIClient class overview 61

5.5.2 APIOptions class 62

5.5.3 RSAPIClientSettings class 62

5.5.4 RSAPIClientServiceOperationFailed event 62

5.5.5 Best practices for proxy creation 62

5.5.6 Creating the proxy in an agent, custom page, or event handler 63

5.5.7 Code samples for proxy creation in a console application 63

5.6 Token login 65

5.6.1 Creating the proxy using a token 65

5.6.2 Generating an authorization token for Relativity 66

5.7 Data Transfer Objects (DTOs) 67

5.7.1 DTO Features 67

5.7.2 Supported DTOs 68

5.8 Untyped base Artifacts 69

5.8.1 RSAPIClient support for ArtifactTypes 69

5.8.2 Limited support for Create() on Fields 70

5.8.3 Field (untyped) 70

5.9 StrictMode property and Field directives 73

5.9.1 StrictMode property for DTOs 73

5.9.2 Field directives for DTOs 73

5.9.3 StrictMode and the TextIdentifer property (untyped layer) 74

5.9.4 Field directives (untyped layer) 74

5.10 Best practices for the Services API 75

5.10.1 Use DTOs whenever possible 75

5.10.2 Bring back only Fields that you need for optimum performance 75

5.10.3 Don’t use the Services API to bulk-load data 75

5.10.4Work in batches 75

Page 5: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 5

5.10.5 Use GUIDs to reference Fields and object types 75

5.10.6 Install and uninstall applications through the ADS 76

5.10.7 Use of the APIOptions token property 76

5.10.8 Avoid specific version assembly references 76

5.10.9 Use constant Field names for Read() and Query()methods 77

5.10.10 Use Services API enumerations or constants 77

5.11 GUIDs in application development 78

5.11.1 Using GUIDs as best practice 78

5.11.2 Using GUIDs in read, update, and delete operations 78

5.11.3 Viewing GUIDs for your application components 78

5.12 Asynchronous framework 78

5.13 Terminology 79

6 DTO reference and code samples 81

6.1 Batch 82

6.1.1 Updating and reading a Batch 82

6.1.2 Querying for a Batch 84

6.2 BatchSet 85

6.2.1 Creating, updating, and querying BatchSet objects 85

6.2.2 Creating and deleting a BatchSet 88

6.2.3 Creating Batches for a BatchSet 90

6.2.4 Querying for a Batch Set 91

6.2.5 Canceling the creation of a BatchSet 91

6.2.6 Purging Batches for a BatchSet 93

6.2.7 Event handlers used in code samples 94

6.3 Choice 95

6.3.1 Reading a Choice 95

6.3.2 Querying on a Choice 96

6.4 Client 97

6.4.1 Creating a Client 97

6.4.2 Reading a Client 98

6.4.3 Updating a Client 100

6.4.4 Deleting a Client 101

6.4.5 Querying for a Client 102

6.5 Document 103

6.5.1 Fields on a Document DTO 103

Page 6: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 6

6.5.2 Creating a Document 103

6.5.3 Reading a Document 105

6.5.4 Updating a Document 106

6.5.5 Deleting a Document 108

6.5.6 Querying for a Document 109

6.5.7 Downloading a native file 111

6.6 Error 112

6.6.1Writing to the error log 112

6.7 Field 113

6.7.1 System type fields 113

6.7.2 Field types 114

6.7.3 Supported operations for Field types 128

6.7.4 Field code samples 128

6.7.5 File field 135

6.7.6 Fields used by Field type, User, and Group 141

6.7.7 Constant Field names 146

6.8 Folder 153

6.8.1 Creating a Folder 153

6.8.2 Reading a Folder 154

6.8.3 Deleting a Folder 155

6.8.4 Querying for a Folder 157

6.9 Group 158

6.9.1 Creating a Group 158

6.9.2 Reading a Group 159

6.9.3 Updating a Group 160

6.9.4 Deleting a Group 161

6.9.5 Querying for a Group 162

6.10 Layout 163

6.10.1 Reading a Layout 164

6.10.2 Querying for a Layout 165

6.11MarkupSet 166

6.11.1 Creating a MarkupSet 166

6.11.2 Reading a MarkupSet 167

6.11.3 Updating a MarkupSet 168

6.11.4 Deleting a MarkupSet 169

Page 7: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 7

6.11.5 Querying for a MarkupSet 170

6.12 ObjectType 172

6.12.1 Creating an ObjectType 172

6.12.2 Reading an ObjectType 173

6.12.3 Updating an ObjectType 174

6.12.4 Deleting an ObjectType 175

6.12.5 Querying for an ObjectType 176

6.13 RDO 177

6.13.1 Creating an RDO 177

6.13.2 Creating an RDO as a child object 179

6.13.3 Reading an RDO 180

6.13.4 Updating an RDO 182

6.13.5 Deleting an RDO 183

6.13.6 Querying for an RDO 184

6.14 RelativityApplication 186

6.14.1 Reading a RelativityApplication 186

6.14.2 Deleting a Relativity Application 187

6.14.3 Querying for a RelativityApplication 188

6.15 RelativityScript 189

6.15.1 Reading a RelativityScript 190

6.15.2 Querying for a RelativityScript 191

6.15.3 Executing a RelativityScript 192

6.15.4 Retrieving Input for a RelativityScript 195

6.16 Tab 196

6.16.1 Reading a Tab 196

6.16.2 Querying for a Tab 197

6.17 User 198

6.17.1 Creating a User 198

6.17.2 Utility methods used in User DTO creation 201

6.17.3 Reading a User 203

6.17.4 Updating a User 204

6.17.5 Deleting a User 206

6.17.6 Querying for a User 206

6.18 View 207

6.18.1 Reading a View 208

Page 8: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 8

6.18.2 Querying for a View 209

6.19Workspace 210

6.19.1 Reading aWorkspace 210

6.19.2 Querying for a Workspace 211

7 Additional Services API functionality 212

7.1 File transfers 212

7.1.1 Supported file transfer operations 212

7.1.2 File transfer error messages 213

7.1.3 Error classes 213

7.1.4 Sample error handling code 214

7.2Mass processes 215

7.2.1Mass delete operations 223

7.3 Querying 227

7.3.1 Using Query objects 227

7.3.2 Available Conditions for Querying 227

7.3.3 System Types supported by the Query() method 228

7.3.4 Paging 228

7.3.5 Constraints on the Query() method 229

7.3.6 SavedSearchCondition 229

7.3.7 Specialized queries with Conditions 231

7.3.8 ViewCondition 233

8 Troubleshooting the Services API 236

8.1 Common causes of Services API errors 236

8.2 Error occurs when machines in a workgroup attempt to log in 237

Page 9: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 9

1 Relativity Services APIThe Services API supports the development of customized end-user applications that interact with Relativity.It simplifies the development process by providing object classes and other data structures that are thebuilding blocks for custom applications.

2 Configuring the Services APIThe Services API is installed on the Relativity web server as an additional IIS application calledRelativity.Services. When you install Relativity on your web server, the installer automatically configures theServices API to use Net.Pipe.

Note: You don’t need to complete any additional configuration steps for the Services API unless you wantto use HTTP, HTTPS, or TCP as the scheme, or customize the client and server configuration settings. Youmay also need to configure Net.Pipe on the IIS if you ran the Relativity installer before rebooting yourmachine after Windows updates were installed.

Most of the configuration of Relativity.Services is determined by the settings in the web.config file of theRelativity.Services virtual directory. A few of the configuration options are controlled in IIS. The configurationprocess includes configuring settings in IIS, testing the connectivity to the Services API, and troubleshootingthe configuration settings.

2.1 Configuration prerequisitesBefore you begin configuring the Services API, you will need to complete the following tasks:

n Confirm that Relativity has been installed in your environment, and that the Services API has beeninstalled as part of the web server component of Relativity.

n Determine the scheme that you want to use, such as HTTP, HTTPS, or TCP. You will also need to selectan authentication method, such as username/password orWindows credentials. The Services API canuse a different authentication scheme than other Relativity components installed on the samewebserver.

Note: You don't need to complete any configuration steps if you use Net.Pipe as installed on the IIS when yourun the Relativity installer.

n Obtain a valid SSL certificate based on these requirements:o HTTPS - If you're using this scheme, you must have a certificate.o Username/password over HTTP or username/password over Net.TCP - If you're defining the

CertificateFindValue in the web.config file on the server, you need a certificate for theseschemes. Otherwise, you don't need a certificate.

Note: Make sure that the Subject Name on the certificate is unique.

Page 10: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 10

2.2 SSL certificate for HTTPSYou need to obtain a SSL certificate if you are going to use HTTPS.

1. Obtain a digital certificate that meets the following requirements:n Make sure that you have a trusted certificate. You can use a certificate issued from a valid cer-

tificate authority or a self-signed certificate.n Matches the domain where Relativity Services is installedn Must be current (You can’t use an expired certificate.)

2. Ensure there is a properly configured HTTPS binding. See Configuring HTTP or HTTPS connectivity to IISon page 13.

2.3 SSL certificate for HTTP or Net.TCPIf you're defining the CertificateFindValue in the web.config file on the server, you need a certificate for theseauthentication schemes:

n Username/password over HTTPn Username/password over Net.TCP

Note: If you aren't setting CertificateFindValue in the web.config file, you don't need to complete thefollowing steps.

Complete the following steps to configure an SSL certificate for username/password over HTTP.

1. Create or import a certificate. Use the instructions available on theMicrosoft website for one of the fol-lowing methods:

n Import a certificate from another source into IIS 7 (http://technet.microsoft.com/en-us/lib-rary/cc732785(v=ws.10).aspx)

n Create a self-signed certificate in IIS 7 (http://technet.microsoft.com/en-us/library/cc753127(v=ws.10).aspx)

Note: If you use another method to install the certificate, add it to the Personal store for the localmachine but not the Personal store for the current user. (.NET refers to this location as My store.) Youwill need the Subject Name value on the certificate when you configure IIS.

2. Complete the following steps to configure the server to use the certificate:a. Locate theweb.config file for the Services API. The default directory is listed below:

<YourInstallationDirectory>\kCura Corporation\Relativity\Relativity.Services

b. In this file, set the value for the CertificateFindValue key to the Subject value on the certificate.See the following example:

<kCura.CommonServiceValues.Config>

Page 11: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 11

<add key="CertificateFindValue" value="myServer.kcura.com"/>

</kCura.CommonServiceValues.Config>

As displayed in IIS, the valuemyServer.kcura.commatches the value for the Subject in thecertificate:

Note: Make sure that the Subject value (or name) is unique in your environment. When multiplecertificates with the same name exist, the Services API can’t determine the correct one to use. You canview certificates in IIS, which displays the Subject in the Issued To column on Server Certificates pane.

c. (Optional) Override specific configuration settings in the web.config file as required for your envir-onment. See Configuration overrides on page 19.

3. Complete the following steps to configure the client to use the certificate:a. Ensure that the CertificateFindValue corresponds to the value for the CertificateFindValue key

specified in the web.config file on the server. (A CertificateFindValueInvalidException is thrownwhen a mismatch occurs between the CertificateFindValue defined on the server and the cli-ent.)

b. Determine if you need to set the CertificateFindValue. If this value is set on either the client orthe server, then you must configure it on the other entity. (You can't configure only one of theseentities. If the CertificateFindValue on the client is set, then you must configure it on the server,and vice versa.) See Configuration overrides on page 19.

Page 12: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 12

Note: The client won't validate the certificate by default. However, you can control this behavior byupdating the CertificateValidation setting.

4. Configure IIS to require SSL on the Relativity.Services virtual directory. See Configuring HTTP or HTTPSconnectivity to IIS on the next page.

5. Confirm endpoint connections. See Testing the Services API configuration on page 25.

2.4 Creating a self-signed certificateFor development purposes, you can create self-signed certificates with a utility included in the . The SelfSigned Certificate Creator is available Tools folder of your Relativity SDK installation.

Note: Don't use the certificates created with this utility in your production environment. These certificatesare for development purposes only.

1. Locate Tools folder of your Relativity SDK installation. The following path is default location:

...\Program Files\kCura Corporation\Relativity SDK\RSAPI\Tools

2. Click CertificateCreatorForm.exe to open the application.

3. Enter the following information required to create a certificate:n Friendly Name - Enter a name for the certificate that you want to use for identification purposes.

The Friendly Name is used for your convenience to make it easier to distinguish between dif-ferent certificates.

n Machine Name - Enter the name of themachine that will be used as the Subject field on the cer-tificate. Use a value that is appropriate for a self-signed certificate. You can update this value, ifnecessary. This value will also be displayed in the Issued To column.

Page 13: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 13

Note: If you are unsure about how to set the Machine Name, don't use this tool to create a certificate.

n # Years Valid - Enter the number of years from the creation date that you want the certificate tobe valid.

4. Click Create Certificate. You will see your new certificate listed in the Current Certificates box. This listincludes the same set of certificates available on IIS. It is populated from information in the LocalMachine\Personal certificate store in Windows.

2.5 Configuring HTTP or HTTPS connectivity to IISYou must configure IIS hosting Relativity.Services to use anonymous authentication, since the authenticationoccurs within Relativity rather than on the web server itself.

1. On the web server, log on as a member of the Administers group.2. Open IIS Manager.3. Under the Sites node, select the Relativity.Services virtual directory.

4. Double-click on Authentication.5. Verify that only Anonymous Authentication is enabled. The Services API requires that only Anonym-

ous Authentication is enabled, and that all other authentication methods are disabled. However, youcan use the other authentication methods for other Relativity components.

Page 14: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 14

6. If you are using HTTPS with username/password or HTTPS with Windows authentication, verify thatHTTPS binding is configured on the Relativity.Services virtual directory. See Verifying HTTP and HTTPSsite bindings below.

Note: You must have an SSL certificate installed and configured for the website that is trusted by calling clients.It must be installed at the website level.

7. If you are using HTTP with username/password authentication, complete the following steps to dis-able SSL on the Relativity.Services virtual directory:

a. Click the SSL Settings option for the Relativity.Services virtual directory.b. Double-click on SSL Settings.c. Verify that Require SSL is cleared.

8. Complete the steps in Testing the Services API configuration on page 25.

2.5.1 Verifying HTTP and HTTPS site bindingsUse these steps to verify the site bindings for the HTTP or HTTPS protocols that you have configured on yourserver.

Page 15: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 15

1. On the web server, open IIS Manager.2. In IIS Manager Connections pane, expand Sites.3. Right - click on Default Web Site.

4. In the right-click menu, click Edit Bindings to display the Site Bindings dialog.

5. Verify the information for the HTTP or HTTPS protocol that you are using. For HTTPS, you will need toensure that the SSL certificate is valid. Click Edit to view the SSL certificate assigned to the site binding.

Page 16: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 16

6. Click Close.

2.6 Configuring Net.Pipe or Net.TCP connectivityYou can configure the following types of connections to IIS:

n Net.Pipe with Windows authenticationn Net.TCP with username/password authentication(If you are using Net.TCP with username/password

authentication and defining the CertificateFindValue in the web.config file, you must install an SSL cer-tificate. See SSL certificate for HTTP or Net.TCP on page 10.)

n Net.TCP with Windows Authentication

Note: When you install Relativity on your web server, the installer automatically configures the Services APIto use Net.Pipe. However, you may need to configure Net.Pipe on the IIS if you ran the Relativity installerbefore rebooting your machine after Windows updates were installed.

2.6.1 Enabling non-HTTP activation for WCFUse these steps to set the Non-HTTP Activation option in theWindows Server Manager:

1. On the web server, log on as a member of the Administers group.2. In the Control Panel, openWindows Server Manager.3. Open the Add Features Wizard.4. UnderWCF Activation, select Non-HTTP Activation.

Page 17: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 17

5. Complete the steps in Configuring the Net.Pipe or Net.TCP protocols below.

2.6.2 Configuring the Net.Pipe or Net.TCP protocolsYou can configure Net.Pipe or Net.TCP protocols by using a binding configuration. For more information, seeNamedPipe Activation (http://msdn.microsoft.com/en-us/library/ms752253.aspx).

1. On the web server, log on as a member of the Administers group.2. Open IIS Manager.3. Under the Sites node, expand theDefault Web Site.4. Right-click on the Relativity.Services virtual directory.5. Point toManage Application and click Advanced Settings.

6. Add the Net.Pipe or Net.TCP protocol to the Enabled Protocols box, if necessary.

Page 18: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 18

7. Click OK.8. Complete the steps in Verifying HTTP and HTTPS site bindings on page 14.

2.6.3 Verifying Net.Pipe and Net.TCP site bindingsUse these steps to verify the site bindings for the Net.Pipe or Net.TCP protocols that you have configured onyour server.

1. On the web server, open IIS Manager.2. In IIS Manager Connections pane, expand Sites.3. Click Default Web Site.4. In the Actions pane, click Bindings to display the Site Bindings dialog.

5. Verify the information for the protocol that you are using:n Net.Pipe Protocol - Only one net.pipe entry exists in the list of binding types.n Net.TCP Protocol - Only one net.tcp entry exists in the list of binding types.

6. Click Close.7. Complete the steps in Starting the Net.Pipe or Net.TCP listener adapter service below.

2.6.4 Starting the Net.Pipe or Net.TCP listener adapter serviceUse these steps to start the service:

1. On the web server, open Services from Administrative Tools.2. Verify that theNet.Pipe Listener Adapter or theNet.Tcp Listener Adapter service is running. If not,

right-click on the service and click Start.3. Complete the steps in Testing the Services API configuration on page 25.

2.7 Manually configuring the Services API for the Relativity plat-formIf you need to configure the Services API manually, use these guidelines to set up components available withthe Relativity 8.1 platform.Agents

n Services API Hosting - Self-hosted or on IIS (if available on your server)n Relativity.Services URL - Usemethod on Relativity API Helpers to return URL.

Page 19: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 19

n Transport Protocol - Net.Pipen Authentication method -We recommend Windows authentication over token authentication, which

has increased overhead.Custom pages or event handlers (except Pre and Post Install)

n Services API Hosting - Locally through IIS. The Relativity installer automatically adds the Services API tothe web server. (Pre and Post Install event handlers don’t require a connection to the Services API.)

n Relativity.Services URL - Usemethod on Relativity API Helpers to return URL.n Transport Protocol - Net.Pipen Authentication method – UseWindows authentication for full access as the service account or use

token authentication for an audited, secure, and user-aware context.Pre and Post Install event handlers

n Services API Hosting - Self-hosted or on IIS (Themethod for hosting the Services API depends onwhether an agent or Procuro runs the Pre and Post event handlers, or whether they are run from theweb server.)

n Relativity.Services URL - Usemethod on Relativity API Helpers to return URL.n Transport Protocol - Net.Pipen Authentication method – UseWindows authentication for full access as the service account.

ApplicationsServices API Hosting - Host remotely.

Note: Due to certificate issues, the Services API shouldn't be hosted remotely for agents, custom pages,and event handlers. If you must use this configuration, use HTTPS as the transport protocol. In addition,useWindows authentication for full access as a service, or use Active Directory authentication by calling theLoginWithCredentials() method, and passing a username and password.

2.8 Configuration overridesYou can use configuration overrides to enter custom values for endpoint configurations. In general, you willprobably not need to override the default configuration values.

2.8.1 Setting client configuration overridesClient configuration settings override single values. However, they don’t override all configuration values as acustom service and endpoint configuration would. You can programmatically apply configuration overrides ina client-side application by using the RSAPIClientSettings class.The available client configuration overrides share the same name as server-side configuration overrides. Eventhough the names are the same, these values apply only to either the server or the client. Configurationissues may occur if a value configured on the client-side conflicts with that configured on the server-side, orvice versa. Ensure that the configuration override values on the client and server match.To modify configuration settings programmatically, override the properties available on theRSAPIClientSettings class. The following code sample illustrates how to set a CertificateFindValue value:

RSAPIClientSettings settings = new RSAPIClientSettings();

Page 20: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 20

settings.CertificateFindValue = "myServer.myCompany.com";

The following list includes the available override settings for the client:

CertificateFindValue

n Datatype - Stringn Description - Specifies the Subject Name value used to identify the server-side certificate. This client-

side valuemust match the server-side value exactly. The value is case-sensitive. The default value isString.Empty.

Note: This setting applies only to username/password over HTTP and username/password over Net.TCPendpoint types.

CertificateValidation

n Datatype - Booleann Description - Determines whether the client validates the server certificate that the CertificateFindValue

specifies.

Note: This setting applies only to username/password over HTTP and username/password over Net.TCPendpoint types.

2.8.2 Setting server configuration overridesYou can configure single value or service-wide overrides on the server hosting the Services API. You can usesingle override values for all 4 of the services: Authentication, DataManipulation, FileTransfer, andSetExecutor. These override values are configured in the kCura.Authentication.Config,kCura.DataManipulation.Config, kCura.FileTransfer.Config, and kCura.SetExecutor.Config sections,respectively. An additional configuration section called kCura.CommonServiceValues.Config containsconfiguration values that apply equally to all services.

1. Navigate to the Services API web.config in the following directory on the server:

<YourInstallationDirectory>\kCura Corporation\Relativity\Relativity.Services

2. Open the web.config in a text or other editor.3. Locate the <configSections>…</configSections> tags in the file.4. Define the configuration override settings for each of the configuration sections between these tags.

See the following example:

<configSections>

<section name="kCura.Config" type="System.Configuration.DictionarySectionHandler,

System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

<section name="kCura.Authentication.Config"

type="System.Configuration.DictionarySectionHandler, System, Version=1.0.3300.0,

Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

Page 21: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 21

<section name="kCura.DataManipulation.Config"

type="System.Configuration.DictionarySectionHandler, System, Version=1.0.3300.0,

Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

<section name="kCura.FileTransfer.Config"

type="System.Configuration.DictionarySectionHandler, System, Version=1.0.3300.0,

Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

<section name="kCura.SetExecutor.Config"

type="System.Configuration.DictionarySectionHandler, System, Version=1.0.3300.0,

Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

<section name="kCura.CommonServiceValues.Config"

type="System.Configuration.DictionarySectionHandler, System, Version=1.0.3300.0,

Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

<section name="customBasicAuthentication"

type="Thinktecture.CustomBasicAuthentication.CustomBasicAuthenticationSection,

Thinktecture.CustomBasicAuthenticationModule"/>

</configSections>

<kCura.Config>

<add key="encryptedConnectionString" value="…"/>

</kCura.Config>

<kCura.CommonServiceValues.Config>

<add key="ExceptionDetailsInFaults" value="true"/>

</kCura.CommonServiceValues.Config>

<kCura.Authentication.Config>

</kCura.Authentication.Config>

<kCura.DataManipulation.Config>

</kCura.DataManipulation.Config>

<kCura.FileTransfer.Config>

</kCura.FileTransfer.Config>

<kCura.SetExecutor.Config>

</kCura.SetExecutor.Config>

5. Add override settings under configuration sections as necessary:

<add key=”OverrideName” value=”OverrideValue”/>

Replace OverrideName and OverrideValue with the appropriate override key and value as illustratedbelow:

<add key=”ExceptionDetailsInFaults” value=”false”/>

Page 22: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 22

Note: An error will be thrown if a key exists in a section of the configuration file where it doesn't belong. Forexample, ExceptionDetailsInFaults is only valid in kCura.CommonServiceValues.Config, so an error will bethrown if it is incorrectly placed in kCura.Authentication.Config. Verify that you don't have any typographicalerrors in the key. Keys are case sensitive.

2.8.3 Server-side override valuesThe following list includes the available override settings for each service.

CertificateFindValue

n Datatype - Stringn Description - Username/password over HTTP or username/password over Net.TCP endpoint con-

figurations requires a certificate to secure the contents of themessage. The location of this certificate isspecified as the local machine, while it is the store titledMy that is searched. The CertificateFindValuespecifies the value to look for in the Subject Name of the certificate. For example, if you used IIS to cre-ate a self-signed certificate on a machine residing at myMachine.domain.corp, then specifymyMachine.domain.corp as the CertificateFindValue. This value is case-insensitive. The default value isString.Empty for both services.

n Sections - kCura.CommonServiceValues.Config

Note: This setting applies only to username/password over HTTP and username/password over Net.TCPendpoint types.

ExceptionDetailsInFaults

n Datatype - booln Description - Determines how to report exceptions to the client. When set to false (default), detailed

exception information isn't reported to the client. When set to true (enabled), the server sends detailedinformation. The recommendation is to enable this flag only for debugging during development. Thedefault value is False.

n Sections - kCura.CommonServiceValues.Config

FailureAuditing

n Datatype - booln Description - Set this value to True if you want to audit failed security events fromWCF. Audited secur-

ity events include transport, message, or negotiate authentication and authorization events. You canview these events in theWindows Event Viewer, since they are written to Windows event log. Thedefault value is True.

n Sections - kCura.CommonServiceValues.Config

MaxArrayLength

n Datatype - Integern Description - Determines themaximum array length created and returned at various stages ofmessage

processing. The default value for FileTransfer is Int.MaxValue, and for all other services, it is 1000000.n Sections - kCura.Authentication.Config, kCura.DataManipulation.Config, kCura.FileTransfer.Config,

kCura.SetExecutor.Config

MaxBufferSize

n Datatype - Integer

Page 23: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 23

n Description - Specifies themaximum buffer size (in bytes) used to storemessages in memory. If moredata is received than can fit in the buffer, it remains on the underlying socket until there is enoughspace. This value should match theMaxReceivedMessageSize. The default value for FileTransfer isInt.MaxValue, and for all other services, it is 104857600.

n Sections - kCura.Authentication.Config, kCura.DataManipulation.Config, kCura.FileTransfer.Config,kCura.SetExecutor.Config

MaxBufferPoolSize

n Datatype - Longn Description - Specifies themaximum buffer pool size (in bytes) used by the BufferManager. As mes-

sages are received, buffers are required to process them as they come out of the channel. If the Buffer-Manager has insufficient memory, additional memory must be allocated. The default value forFileTransfer is Int.MaxValue, and for all other services, it is 104857600.

n Sections - kCura.Authentication.Config, kCura.DataManipulation.Config, kCura.FileTransfer.Config,kCura.SetExecutor.Config

MaxChunkSize

n Datatype - Longn Description - Specifies themaximum size of each chunk (in bytes) used during a file transfer operation.

Since the client requests a chunk size when starting an upload or download, MaxChunkSize sets anupper limit. This value used as the chunk size if the client doesn't specify a size. Larger chunk sizesrequire fewer messages to transfer a file. If a messagemust be sent again, it will take longer amount oftime as compared to a smaller message. If this value is smaller than MinChunkSize, MinChunkSize istreated as themaximum and this value becomes theminimum. The default value is 262144.

n Section - kCura.FileTransfer.Config

MinChunkSize

n Datatype - Longn Description - Specifies theminimum size of each chunk (in bytes) used during a file transfer operation.

Since the client requests a chunk size when starting either an upload or download, MinChunkSize sets alower limit. Smaller chunk sizes take less time to re-send in the case of a temporary failure, and also res-ult in the need to send moremessages. If this value is larger than MaxChunkSize, MaxChunkSizebecomes the newminimum and this value becomes themaximum. The default value is 8192.

n Section - kCura.FileTransfer.Config

MaxConcurrentCalls

n Datatype - Integern Description - Specifies themaximum number ofmessages allowed to be processed at any given time by

a particular ServiceHost instance. The default value is 100.n Sections - kCura.Authentication.Config, kCura.DataManipulation.Config, kCura.FileTransfer.Config,

kCura.SetExecutor.Config

MaxConcurrentInstances

n Datatype - Integern Description - Specifies themaximum number of instances of the service. If messages arrive while this

limit is reached, themessages are held until resources are available. The default value is 200 for all ser-vices.

n Sections - kCura.Authentication.Config, kCura.DataManipulation.Config, kCura.FileTransfer.Config,kCura.SetExecutor.Config

Page 24: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 24

MaxConcurrentSessions

n Datatype - Integern Description - Specifies themaximum number of service sessions. This value should match MaxCon-

currentInstances, and should be set to approximately 100 * # of processors on the server. The defaultvalue is 200 for all services.

n Sections - kCura.Authentication.Config, kCura.DataManipulation.Config, kCura.FileTransfer.Config,kCura.SetExecutor.Config

MaxDepth

n Datatype - Integern Description - Specifies themaximum node depth. The default value is 200.n Sections - kCura.Authentication.Config, kCura.DataManipulation.Config, kCura.FileTransfer.Config,

kCura.SetExecutor.Config

MaxReceivedMessageSize

n Datatype - Longn Description - Specifies themaximum size of a message (in bytes) that will be processed by the service.

This value helps limit DoS attacks, and should be large enough to accommodate larger message pay-loads. The default value for FileTransfer is Int.MaxValue, and for all other services, it is 104857600.

n Sections - kCura.Authentication.Config, kCura.DataManipulation.Config, kCura.FileTransfer.Config,kCura.SetExecutor.Config

MaxStringContentLength

n Datatype - Integern Description - Specifies themaximum string length returned by the XML reader. The default value for

FileTransfer is Int.MaxValue, and for all other services, it is 104857600.n Sections - kCura.Authentication.Config, kCura.DataManipulation.Config, kCura.FileTransfer.Config,

kCura.SetExecutor.Config

ReceiveTimeout

n Datatype - Timespann Description - Specifies the length of time a connection can be inactive before it is dropped.

ReceiveTimeout specifies how long a service waits from the beginning of a receiving a request until themessage is finished being processed. The default value is 10minutes for all services.

n Sections - kCura.Authentication.Config, kCura.DataManipulation.Config, kCura.FileTransfer.Config,kCura.SetExecutor.Config

2.8.4 Override configuration referencesFor more information about override configuration options, review the following references:

n IncludeExceptionDetailInFaults Property:http://msdn.microsoft.com/en-us/library/system.servicemodel.servicebehaviorattribute.includeexceptiondetailinfaults.aspx

n MaxArrayLength Property:http://msdn.microsoft.com/en-us/library/system.xml.xmldictionaryreaderquotas.maxarraylength(v=vs.100).aspx

n MaxBufferSize Property:http://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpbinding.maxbuffersize.aspx

Page 25: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 25

n MaxBufferPoolSize Property:http://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpbinding.maxbufferpoolsize.aspx

n MaxConcurrentCalls Property:http://msdn.microsoft.com/en-us/library/system.servicemodel.description.servicethrottlingbehavior.maxconcurrentcalls.aspx

n MaxConcurrentInstances Property:http://msdn.microsoft.com/en-us/library/system.servicemodel.description.servicethrottlingbehavior.maxconcurrentinstances.aspx

n MaxConcurrentSessions Property:http://msdn.microsoft.com/en-us/library/system.servicemodel.description.servicethrottlingbehavior.maxconcurrentsessions.aspx

n MaxDepth Property:http://msdn.microsoft.com/en-us/library/system.xml.xmldictionaryreaderquotas.maxdepth.aspx

n MaxReceivedMessageSize Property:http://msdn.microsoft.com/en-us/library/system.servicemodel.wshttpbindingbase.maxreceivedmessagesize.aspx

n MaxStringContentLength Property:http://msdn.microsoft.com/en-us/library/system.xml.xmldictionaryreaderquotas.maxstringcontentlength.aspx

n ReceiveTimeout Property:http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.binding.receivetimeout.aspx

n SendTimeout Property:http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.binding.sendtimeout.aspx

2.9 Testing the Services API configurationThe Relativity Services API Diagnostic Tool provides you with the ability to test the configuration of theServices API in your environment. It displays error messages with troubleshooting information when itdetects incorrect settings for certificate values, and other endpoint configuration errors.

2.9.1 Relativity Services API Diagnostic ToolYou can use the Relativity Services API Diagnostic Tool to verify that the Services API is configured properly inyour environment. This tool tests theWSDL endpoint configuration for the RSAPIClient proxy, and tests allservices that it runs in the background. The tool displays error messages when it detects a problem. SeeViewing errors in the Services API Diagnostic Tool on page 28.

1. Navigate to the following DiagnosticTool folder in your installation directory, and click ProxyDia-gnostic.exe. For example, you would use the following path if the SDK was installed on drive C:

C:\Program Files\kCura Corporation\Relativity SDK\RSAPI\Tools\DiagnosticTool\

ProxyDiagnostic.exe

2. To launch the Services API Diagnostic Tool, click the executable.

Page 26: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 26

3. Enter Username and Password that you are using for authentication. Leave these fields blank if youaren't using this type of authentication.

4. Enter the name of Serverwhere the Services API is running. (The Services API Diagnostic Tool onlyrequires themachine name, but you can enter the URI for the server, and it will parse the name fromthis string.)

5. In the Authentication tree, select the authentication methods that you want to test. You can right-clickon this list to select or clear all the check boxes.By default, all of the authentication methods are selected. You may initially want to test all methods toidentify, which endpoint types are available in your environment. You can then disable any endpointtypes that you don't want exposed.

6. (Optional) If a CertificateFindValue is defined in the web.config for your server, select the Auto-DetectCertificateFindValue box. The Services API Diagnostic Tool will automatically populate the Cer-tificateFindValue box with the current server setting. See Server-side override values on page 22.

Note: Leave the Auto-Detect CertificateFindValue box blank if you aren't setting the CertificateFindValue inthe web.config file.

7. Click Run Diagnostics. The Current EndPointType box is updated with status messages as the test pro-ceeds. The Services API Diagnostic Tool automatically detects the CertificateFindValue for the server.

Page 27: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 27

8. Review the results of the endpoint tests in the Authentication tree:n Green Status - indicates the endpoint type is available and the connection succeeded.n Red Status - indicates that the attempt to connect with this endpoint failed. To obtain more

information about a failure, complete step 9.9. (Optional) Complete the following tasks if you want to view the exception thrown when the endpoint

test failed:a. Select only the failed endpoint in the Authentication tree.b. Select theDisplay ServiceOperationFailed Events option.c. Click Run Diagnostics to display exception details including the exception thrown and the stack

trace as in the following illustration.

Page 28: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 28

Note: You can also perform additional troubleshooting to resolve these errors. See Viewing errors inthe Services API Diagnostic Tool below and Troubleshooting the Services API Configuration on page 30.

d. (Optional) Click Copy to Clipboard if you want copy the error messages generated in the CurrentEndpointType box.

2.9.2 Viewing errors in the Services API Diagnostic ToolThe RelativityServices API Diagnostic Tool displays error messages when it detects that the Services API isn'tconfigured properly. You can review the details for these error messages and then use the suggestedresolution to update the endpoint configuration for the RSAPIClient proxy. See Configuring the Services APIon page 9.

2.9.2.1 Ambiguous CertificateFindValue definedYou will receive the following error message when the CertificateFindValue needs to bemore specific:

The value '<VALUE>' was specified as the server-side CertificateFindValue, butthere is more than one matching certificate. Remove certificates withduplicate SubjectName values from the Certificate Store, or provide a morespecific SubjectName.

This error occurs when the supplied CertificateFindValue in the server-side web.config file needs to bemorespecific. (See '<VALUE>' in themessage.) If the name supplied for the CertificateFindValuematches multiplecertificates in IIS, you must update the CertificateFindValue to identify a unique certificate name, or removethe duplicate certificates. See Configuration overrides on page 19.

Page 29: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 29

2.9.2.2 No CertificateFindValue definedYou will receive the following error message when no value was supplied as the server-sideCertificateFindValue:

Nothing was specified as the server-side CertificateFindValue. Provide theSubjectName value of a valid certificate in the Certificate Store.

This error occurs when no value was defined for the CertificateFindValue, or an empty string ("") was used.Add an entry similar to the following example to the kCura.CommonServiceValues.config section of theRelativity.Services web.config file:

<add key=”CertificateFindValue” value=”myCert.subjectName.com” />

2.9.2.3 Invalid CertificateFindValue definedYou will receive the following error message when an invalid value was supplied as the server-sideCertificateFindValue:

The value '<VALUE>' was specified as the server-side CertificateFindValue, buta matching certificate couldn't be found. Double check the name and spellingand ensure the certificate is in the correct Certificate Store.

This error occurs when the value supplied as the CertificateFindValue doesn't match any existing certificate.Ensure the certificate is in the appropriate store, and that the spelling is correct.

2.9.2.4 Invalid server formatYou will receive the following error message when the server address supplied was in an invalid format:

The supplied server is in an invalid format. Check for any typing mistakes.

Verify that there aren't any spelling or typographical errors.

2.9.2.5 Invalid configuration keys presentYou will receive the following error message when invalid keys are present in a specific section of the server-side web.config file:

The '<SECTION>' section of the web.config contains invalid keys: <KEYS>.Ensure no typographical errors were made and that each key is in theappropriate section.

In this message, <SECTION> represents the part of the web.config file that contains invalid keys. <KEYS> is acomma-separated list of the offending keys. Ensure that each key is in the correct section, and that no spellingor typographical errors exist. Also, the keys are case-sensitive.

2.9.2.6 Insufficient permissions in IISYou will receive the following error message when the account that the Relativity.Services application poolruns under has insufficient permissions to access a certificate:

The account that IIS is running under does not have sufficient permissions tothe private key of the certificate referred to by the server-sideCertificateFindValue. Via the 'Certificates' snap-in of the MicrosoftManagement Console, give the appropriate account permissions to the privatekey.

Page 30: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 30

Follow the instructions provided in the error message. SeeMSDN (http://msdn.microsoft.com/en-us/default.aspx) for more information about how to modify private key permissions.

2.9.2.7 Protocol not configured properlyYou will receive the following error message when a protocol hasn't been properly configured:

The protocol '<VALUE>' has not been configured correctly. Ensure that allnecessary Windows features are installed, that '<VALUE>' has been added to thelist of Enabled Protocols for the IIS application, and the site has a bindingfor '<VALUE>'.

In the error message, <VALUE> indicates the protocol that requires further configuration before it is usable.See Configuring the Services API on page 9.

2.9.2.8 Remote name unreachableYou will receive the following error message when the server address supplied can't be reached:

The supplied server '<SERVER>' could not be reached.

Verify that no spelling or typographical errors exist, and that Windows can resolve the supplied host name.

2.9.2.9 HTTP requested, but SSL is requiredYou will receive the following error message when the server requires SSL, but an attempt was made tocommunicate using HTTP:

A connection attempt was made with HTTP, but the server requires SSL.

HTTP must be allowed in IIS if you want to use any of the endpoint configurations that involve HTTP, such asIntegratedHTTP, or UserNamePasswordHTTP. See Configuring the Services API on page 9.

2.9.2.10 SSL trust failureYou will receive the following error message when there is an issue establishing an SSL connection:

The Certificate Authority of the server's certificate is not trusted by theclient. If the server is using a self-signed certificate, install thatcertificate on the client in the Trusted Root Certification Authorities of theLocal Machine if you trust it. The specified server name does not match theSubjectName value of the certificate of the HTTPS binding in IIS. Either use adifferent certificate on the server, or use a client-side server name thatmatches against the SubjectName.

To resolve this error, ensure the server’s certificate is trusted and that the client is using an appropriateaddress to reach the server. The address must match the SubjectName of the certificate attached to theHTTPS binding in IIS. See Configuring the Services API on page 9.

2.10 Troubleshooting the Services API ConfigurationYou can use the information in the following sections to troubleshoot the configuration of the Services API. Inaddition to reviewing error messages, you can also use the Proxy Diagnostic Tool to troubleshoot connectionsto the Services API. See Testing the Services API configuration on page 25.

Page 31: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 31

2.10.1 Logging and debugging settings in the web.configTo assist with Services API troubleshooting, enable logging and debugging in the web.config file. (They aredisabled by default.) Modify the configuration settings as necessary.

2.10.2 Production environment trace settingsTo troubleshoot application activity, you can collect trace data fromWCF or user-defined trace sources. Tracelevels includeWarning, Information, and Verbose.

Note: Logging may result in application performance degradation. Information and Verbose levels producegreater logging output resulting in a greater performance impact, so they may be best suited for non-production environments.

This table includes logging configurations recommended for production environments. You will need toupdate the web.config file with these values. (If you don't anticipate performance degradation, you can setthe switchValue attribute to Information to generate additional trace data.)

Trace Source Source Name switchValue Attribute Additional AttributeWCF System.ServiceModel Warning propagateActivity="true"User-defined User-defined source name Warning,

ActivityTracing

Using the recommended production environment configurations, the following sample code defines tracesettings for the System.ServiceModelWCF trace source and a user-defined trace source namedmyUserTraceSource:

<system.diagnostics><sources>

<source name="System.ServiceModel"switchValue="Warning"propagateActivity="true" >

<listeners><add name="xml"/>

</listeners></source><source name="myUserTraceSource"

switchValue="Warning, ActivityTracing"><listeners>

<add name="xml"/></listeners>

</source></sources><shareListeners>

<add name="xml"type="System.Diagnostics.XmlWriterTraceListener"

Page 32: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 32

initializeData="C:\logs\Traces.svclog" /></sharedListeners>

</system.diagnostics>

2.10.3 Test environment trace settingsIn your test environment, make the following updates to the web.config file:

n In the initializeData attribute, set the file name and directory location to the folder where you want tosave the log output.

n Add the following node to the system.servicemodel section:

<diagnostics wmiProviderEnabled="true">

<messageLogging

logEntireMessage="true"

logMalformedMessages="true"

logMessagesAtServiceLevel="true"

logMessagesAtTransportLevel="true"

maxMessagesToLog="3000"

/>

</diagnostics>

Use the recommended configuration settings for the test environment listed in the following table. Forenhanced logging, add System.ServiceModel.MessageLogging as an additional trace source. (The switchValueattribute doesn’t affect this trace source.)

Trace Source Source Name Source Name Additional AttributeWCF System.ServiceModel Information, ActivityTracing or

Verbose, ActivityTracingpropagateActivity="true"

User-defined User-defined sourcename

Information, ActivityTracing orVerbose, ActivityTracing

The following sample code defines trace settings for the System.ServiceModelWCF, and theSystem.ServiceModel.MessageLogging trace sources, as well as a user-defined trace source namedmyUserTraceSource. The switchValue attribute uses this Information, and ActivityTracing settings.

<system.diagnostics><sources>

<source name="System.ServiceModel"switchValue="Information, ActivityTracing"propagateActivity="true" >

<listeners><add name="xml"/>

</listeners></source><source name="System.ServiceModel.MessageLogging">

Page 33: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 33

<listeners><add name="xml"/>

</listeners></source><source name="myUserTraceSource"

switchValue="Information, ActivityTracing"><listeners>

<add name="xml"/></listeners>

</source></sources><sharedListeners>

<add name="xml"type="System.Diagnostics.XmlWriterTraceListener"initializeData="C:\logs\Traces.svclog" />

</sharedListeners></system.diagnostics>

2.10.4 FailureAuditing Configuration Override SettingYou can also configure a FailureAuditing override setting on the server hosting the Services API. You can setthis value to True if you want to audit failed security events fromWCF. Audited security events includetransport, message, or negotiate authentication and authorization events. You can view these events in theWindows Event Viewer, since they are written to Windows event log. See Configuration overrides on page 19.

2.10.5 Attempting to access .svc file causes keyset errorYou receive the following error message when accessing a .svc files that expose an EndpointType configurationrequiring a certificate, such as username and password authentication forfor HTTP, HTTPS, or Net.TCP:

Keyset does not exist.

This error occurs because the permissions on the private key of the certificate are incorrect. It occurs onlywhen the Services API attempts to access a certificate already added to a directory, even though it is in thecorrect location. You don’t need to relocate the certificate.To resolve this issue, you need to ensure the account running the Relativity.Services application in IIS hasaccess to the private key of the certificate. Complete these steps to set the permissions:

1. Log on to the server running the Services API.2. Click Start.3. In the Search programs and files box, typemmc.4. Press Enter to open theMicrosoft Management Console.5. On the File menu, click Add/Remove Snap-in.6. In the Available snap-ins column, double-click Certificates to open the Certificates snap-in dialog.7. Select Computer account, and click Next.8. Select Local computer option for managing snap-ins.9. Open the Certificates (Local Computer) snap-in.10. Browse to Personal, and then Certificates.11. Locate the certificate that you have set for CertificateFindValue property in the web.config file.

Page 34: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 34

12. Right-click on the certificate, point to All Tasks, and clickManage Private Keys.13. To modify the private key permissions, select Add.14. Grant full permissions to the account running the Relativity.Services IIS application.

2.10.6 Catching EndpointType exceptionsYou can obtain additional information about EndpointType errors by catching theEndpointTypeCollectionInvalidException exception. This error message is returned when you catch thisexception:

Error constructing a proxy.Log Info:EndpointType UserNamePasswordNetTCPHTTP Failed:-->Metadata contains a reference that cannot be resolved:'http://someserver.name.domain/Relativity.Services/SetExecutorNetHTTP.svc?wsdl'.-->The remote name could not be resolved: 'someserver.name.domain'EndpointType UserNamePasswordHTTP Failed:-->Metadata contains a reference that cannot be resolved:'http://someserver.name.domain/Relativity.Services/SetExecutorHTTP.svc?wsdl'.-->The remote name could not be resolved: 'someserver.name.domain'EndpointType UserNamePasswordNetTCPHTTPS Failed:-->Metadata contains a reference that cannot be resolved:'https://someserver.name.domain/Relativity.Services/SetExecutorNetHTTPS.svc?wsdl'.-->The remote name could not be resolved: 'someserver.name.domain'EndpointType UserNamePasswordHTTPS Failed:-->Metadata contains a reference that cannot be resolved:'https://someserver.name.domain/Relativity.Services/SetExecutor.svc?wsdl'.-->The remote name could not be resolved: 'someserver.name.domain'

2.10.7 Connection errors in load-balanced systemsIf you have configured your environment for load balancing and HTTPS, you may receive errors if the APIconnects to a different URL than theWSDL. To resolve these errors, set the binding in IIS to a certificate froman internal CA authority or to a wildcard certificate.

2.10.8 Could not load type 'System.ServiceModel.Activation.HttpModule'This error is displayed if you have installed .NET 4.0 features after installing .NET 4.5:

Server Error in '/Relativity.Services' Application.Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly'System.ServiceModel, Version=3.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089'.

Open a Visual Studio 64-bit console. In Admin mode, execute this command:

aspnet_regiis.exe /iru

Page 35: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 35

The program, aspnet_regiis.exe, is located in one of the following directories by default. Theminor versionnumber in the directory path may vary, such as .30319 in this example.

%windir%\Microsoft.NET\Framework64\v4.0.30319%windir%\Microsoft.NET\Framework\v4.0.30319

If the previous command didn't resolve the issue, execute this command:

servicemodelreg -r

For more information, see The DCS ServiceModelReg Utility on theMicrosoft Developer Network site.

2.10.9 Erroneous calls to internal web server in load-balanced systemsWhen you use the client proxy to access the Services API, a second erroneous call is made to an internal webserver. The URIs in theWSDL document points to inaccessible internal websites. Microsoft has identified thisbehavior as a known issue exhibited by theWCF service in load-balanced environments. The followingenvironmental configurations are associated with this issue:

n Windows Communication Foundation (WCF) service in a load-balanced environmentn Microsoft .NET 3.0 and 3.5n Windows Server 2003, Windows XP, Windows Vista, and Windows 2008

To resolve this issue, specify the following service behavior by adding these settings to the web.config file.Replace <name>with the behavior name of theWCF service.

<serviceBehaviors><behavior name="<name>">

<useRequestHeadersForMetadataAddress><defaultPorts>

<add scheme="http" port="81" /><add scheme="https" port="444" />

</defaultPorts></useRequestHeadersForMetadataAddress>

</behavior></serviceBehaviors>

For more information, see this Microsoft article (http://support.microsoft.com/kb/971842).

2.10.10 HTTP error 404.17 or 404.3When you attempt to reach one of the service endpoints from a server hosting the Relativity.Services, youreceive an HTTP 404.17 or 404.3 errors.

Page 36: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 36

Use the following steps to install WCF on machines hosting the Relativity.Services:

1. Open a command prompt on a machine hosting the Relativity.Services.2. Change to one of the following directories depending on your machine:

n 64-bit:cd C:\Windows\Microsoft.NET\Framework64\v4.0.30319

n 32-bit:cd C:\Windows\Microsoft.NET\Framework\v4.0.30319

3. Press Enter.4. Type ServiceModelReg -I. Press Enter.5. Repeat steps 1 - 4 on each machine that hosts the Relativity.Services in your environment.

Note: For more information, see http://iweb.adefwebserver.com/Default.aspx?tabid=57&EntryID=34.

2.10.11 Incorrect version of .NET enabled for application poolsSince Relativity 7.0 or above only supports .NET Framework v 4.0, you may need to register the .NET versionfor your environment. Complete these steps:

1. Use the following commands to register the appropriate version of .NET (in Framework64):

aspnet_regiis -iru -enable

2. Change the application pool to the appropriate version of .NET and recycle the application pool.

Note: If the application pool fails to restart, restart IIS and then start the application pool again.

2.10.12 Missing handler mappingsError messages don't provide detailed information for troubleshooting this issue. You will need to comparethe handler mappings on the Services API server to those of a known working server. For reference, the

Page 37: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 37

following path is used for the handler mapping:

%SystemRoot%\Microsoft.NET\<framework>\v2.0.50727\aspnet_isapi.dll

The <framework> represents Framework or Framework64 directory.

Note: The API on Relativity 7 includes handler mappings for .NET 4.0 as well as those for 2.0, using thev4.0.30319 directory.

As illustrated below, these handler mappings may bemissing:

n svc-ISAPI-2.0

Page 38: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 38

n svc-ISAPI-2.0-64

2.10.13 Pipe endpoint could not be foundYou will receive the following error message when Net.Pipe is not configured:

System.IO.PipeException: The pipe endpoint 'net.pipe://my-server.kcura.corp/Relativity.Services/AuthenticationNetHTTP.svc' could not befound on your local machine.

This error indicates that no endpoint was listening at Net.Pipe, which can be caused by an incorrect address orSOAP action. You may see this error in the Relativity error log depending on where the call to the Services APIwas made. To resolve this error, see Configuring Net.Pipe or Net.TCP connectivity on page 16.

2.10.14 System.ServiceModel.ExceptionDetail ErrorYou receive the following error message when using the Services API:

Type 'System.ServiceModel.ExceptionDetail' in Assembly 'System.ServiceModel,Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is notmarked as serializable.

For example, you may see this error message when communicating across application domains. If theexception thrown from one domain to another isn't serializable, this error occurs.

2.10.15 Unable to access .svc file path in browserAfter you install theWindows Non-HTTP Activation feature, you receive the following error when attemptingto access a .svc file path in the web browser:

Could not load type ‘System.ServiceModel.Activation.HttpModule’ from assembly‘System.ServiceModel, Version=3.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089’

To resolve this issue, execute the following command line statement:

Page 39: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 39

aspnet_regiis.exe /iru

2.10.16 Unable to access websiteYou will be unable to access your website if the HTTP or HTTPS host header references your local machinename. You can update the HTTP or HTTPS host header and reset the ISS to resolve this issue.

Note: Reset IIS during off-hours.

2.10.17 Updating the HTTP host headerIf your scheme is HTTP, use the following steps to update the host header:

1. On the web server, log on as a member of the Administers group.2. Open IIS Manager.3. Under the Sites node, select your website.4. In the Actions pane, click Bindings to display the Site Bindings.5. Select HTTP, and click Edit.6. Update the Host Header on the dialog.7. Reset IIS.8. Try to connect.9. Repeat step 1 -9 on all servers that host Relativity.Services.

3 Upgrading the Services APIUpgrading the Services API may require specific changes to your source code as well as updates to your serverand client-side configurations. As part of the upgrade process, you may want to perform endpointconfiguration tests in order to ensure clients are successfully communicating with the Services API. See Testingthe Services API configuration on page 25.

3.1 Upgrading from Relativity 8kCura initially introduced the newRSAPIClient proxy and related function in the Relativity 8.0.291.1 patchrelease - September 13, 2013. The following upgrade guidelines included information from this patch releasedue to the impact of these enhancements on development with the Services API.

3.1.1 Upgrade guidelines for the Relativity 8.1To upgrade to Relativity 8.1, use these guidelines if your environment runs Relativity 8.0.291.1 or above.

3.1.1.1 Update .dll references in your projectsTo upgrade your code, run the Relativity SDK installer to obtain the new kCura.Relativity.Client.dll,Relativity.API.dll, and other .dll files. Add references to the new .dlls to your projects. On the Relativity8.1Developers site, obtain a copy of the Relativity SDK Installer from the Development environment guidelinespage.

Page 40: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 40

3.1.1.2 Upgrade your development environment to .NET 4.5UseMicrosoft .NET 4.5 framework for new development. When you update any of your current applications,you should also target the .NET 4.5 framework.

Note: We recommend testing your existing applications for compatibility with .NET 4.5. Depending on theresults of your testing, you may need to recompile your applications for optimum performance.

3.1.2 Upgrade guidelines from the Relativity 8.0.291.1 patch releaseTo upgrade to Relativity 8.1, use these guidelines if your environment runs Relativity 8.0.275.3 or below. Inaddition, see Upgrade guidelines for the Relativity 8.1 on the previous page.

3.1.2.1 (Optional) Update references to WCF Web Service File (.svc) filesTheWCF Web Service files (.svc) have been renamed to coincide with changes made for the retrieval ofmetadata over the same protocol as that used for the service connection. If you aren't using thekCura.Relativity.Client.dll for your client development, you may need to update your code to accommodatethese changes.

Changes to .svc file names for the Authentication service

The following table lists changes to the file names for the Authentication service by EndpointType enum. Ablank entry indicates that the EndpointType enum didn't exist in previous versions.

EndpointType enums Authentication service (.svc) inRelativity 8

Authentication service (.svc) priorto Relativity 8

IntegratedHTTP Authentic-ationWinAuthHTTP.svc

No change

IntegratedHTTPS AuthenticationWinAuth.svc No changeIntegratedNetNamedPipe AuthenticationNetWinAuth.svcIntegratedNetNamedPipeViaHTTP AuthenticationNetWinAuth.svc AuthenticationNetHTTP.svcIntegratedNetNamedPipeViaHTTPS AuthenticationNetWinAuth.svc AuthenticationNetHTTPS.svcIntegratedNetTCP Authentic-

ationNetTCPWinAuth.svcIntegratedNetTCPViaHTTP Authentic-

ationNetTCPWinAuth.svcAuthenticationNetHTTP.svc

IntegratedNetTCPViaHTTPS Authentic-ationNetTCPWinAuth.svc

AuthenticationNetHTTPS.svc

UserNamePasswordHTTP AuthenticationForms.svc AuthenticationHTTP.svcUserNamePasswordHTTPS Authentication.svc No changeUserNamePasswordNetNamedPipe AuthenticationNetForms.svcUserNamePasswordNetTCP Authentic-

ationNetTCPForms.svcUserNamePasswordNetTCPViaHTTP Authentic-

ationNetTCPForms.svc iAuthenticationHTTP.svc

UserNamePasswordNetTCPViaHTTPS Authentic-ationNetTCPForms.svc

AuthenticationNetHTTPSForms.svc

Page 41: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 41

3.1.2.2 Use of State property on ServiceInformation classThe RSAPIClient class doesn't include a State property that was previously available on theArtifactManagerProxy class. In Relativity 8.1, the ArtifactManagerProxy returns only Open for the Stateproperty on ServiceInformation object.

3.1.2.3 Use updated EndpointType enumsThe UserNamePasswordNetNamedPipe endpoint type replaces deprecated endpoint types listed in thefollowing table. This table also includes mappings between other endpoint types deprecated during theRelativity 8 release and their new replacements. For more information, see Upgrading the Services API in theRelativity 8 Developers site.

Note: As a best practice, use the new endpoint types in all future applications that you develop. kCuracurrently supports the deprecated endpoint types only for backwards compatibility.

Deprecated EndpointType enums New EndpointType enumsIntegratedNetNamedPipeViaHTTPIntegratedNetNamedPipeViaHTTPS

IntegratedNetNamedPipe

IntegratedNetTCPViaHTTPIntegratedNetTCPViaHTTPS

IntegratedNetTCP

UserNamePasswordNetTCPViaHTTPUserNamePasswordNetTCPViaHTTPS

UserNamePasswordNetTCP

(Deprecated in Relativity 8.0.291.1)UserNamePasswordNetNamedPipeViaHTTPUserNamePasswordNetNamedPipeViaHTTPS

UserNamePasswordNetNamedPipe

3.1.2.4 Client-side configuration overrides automatically setWith the introduction of the newRSAPIClient proxy, Relativity automatically sets most client-sideconfiguration override values available on the ProxySettings class. It copies these settings from your server toyour client-side configuration file.These deprecated properties on the ProxySettings class are now copied from the server configuration:

n MaxArrayLengthn MaxBufferSizen MaxBufferPoolSizen MaxDepthn MaxReceivedMessageSizen MaxStringContentLengthn SendTimeoutn MaxConnectionRetries

You can optionally set the CertificateFindValue and CertificateValidation properties on the client-side as inprevious Relativity releases. See Setting client configuration overrides on page 19.

3.2 Upgrading from Relativity 7.5Your upgrade path for Relativity 8.1 depends on the patch version currently installed in your environment:

Page 42: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 42

n Relativity Patch 7.5.632.83 or above - review the information provided under Upgrading from Relativ-ity 8 on page 39. You may have already completed some of these tasks as you upgraded to the latestpatches.

n Relativity 7.5.632.72 or below - review Relativity Patch 7.5.632.83 Guidelines on the Relativity 7.5Developers site and the information provided under Upgrading from Relativity 8 on page 39.

3.3 Upgrading from Relativity 7.4 and earlierTo upgrade to Relativity 8.1, make any required updates to your existing code and configuration settings.Review the following information that describes feature changes and enhancements:

n Upgrading the Services API and Relativity Patch 7.5.632.83 Guidelines on the Relativity 7.5 Developerssite

n Upgrading from Relativity 8 on page 39

4 Getting started with the Services APIThe Services API provides you with a set of web services for programmatically manipulating many of theobject types available in Relativity. Depending on the object type, you have the option to create, read,update, delete, and query on it. You can use the functionality provided by the Services API to perform manyof the same tasks that you can complete through a Relativity web UI.

4.1 Prerequisites for a development environmentComplete the following tasks before you set up your development environment:

n (Optional) Complete the configuration steps for the Services API only if you want to use HTTP, HTTPS,or TCP as the scheme, or customize the client and server configuration settings. See Configuring theServices API on page 9

Note: You don't need to complete any configuration steps if you use Net.Pipe as installed on the IIS when yourun the Relativity installer.

n Confirm that you have .NET version 4.5 installed on your development machine.n On the Relativity 8.1 Developers site, obtain a copy of the Relativity SDK Installer, and see the Devel-

opment environment guidelines.

4.2 Services API materials available in the SDK InstallerWhen you run the 32 or 64-bit version of the Relativity SDK Installer, its add a folder containing Services APImaterials in one of the following default location:

n 64-bit version - installs in ...\Program Files\kCura Corporation\Relativity SDK\RSAPI\n 32-bit version - installs in ...\Program Files (x86)\kCura Corporation\Relativity SDK\RSAPI

The RSAPI folder has the following subfolders with their related contents:

Page 43: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 43

n Client - contains the kCura.Relativity.Client.dll, which must be reference by a Visual Studio project usedfor development with the Services API.

n Documentation - contains the Relativity - Services API.chm file with the Services API class library.n Samples - includes various subfolders with sample code. In the kCura.Relativity.Client.APISamples

folder, you will find a project containing sample class files in both VB.NET and C#.n Tools - includes the Relativity Services API Diagnostic Tool and the self-signed certificate utility. See

Relativity Services API Diagnostic Tool on page 25 and Creating a self-signed certificate on page 12.

4.3 Setting up a project in Visual Studio1. To run the installer, double-click the kCura.Relativity.SDK.Setup.msi, and follow the instructions in the

installation wizard.2. Create a new project in Visual Studio. (The following steps use Visual Studio 2012 as an example.)3. Open the Solution Explorer.

4. Confirm that the Target framework is .NET Framework 4.5. (In the Solution Explorer, expand your pro-ject and right-click Properties. Click Open to display the Application tab in the left pane. Select .NETFramework 4.5 in the Target framework box.)

Page 44: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 44

5. Add a reference to the kCura.Relativity.Client.dll. (In the Solution Explorer, right-click References, andthen click Add References to display the ReferenceManager dialog. Click the Browse button and selectthe kCura.Relativity.Client.dll.)You can find this .dll in a Relativity web server installation, or in the RSAPI folder of the SDK installationdirectory. The folder is installed at one of these locations by default:

n 64-bit version - installs in ...\Program Files\kCura Corporation\Relativity SDK\RSAPI\Clientn 32-bit version - installs in ...\Program Files (x86)\kCura Corporation\Relativity SDK\RSAPI\Client

6. Add references to the following .NET framework assemblies: System.Runtime.Serialization, and Sys-tem.ServiceModel. (In the ReferenceManager dialog, expand Assemblies and click Framework.)

Page 45: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 45

7. (Optional) Point the RelativityServices API Diagnostic Tool at your server to determine the endpoint con-figurations that are exposed. See Testing the Services API configuration on page 25.

4.4 Creating a simple program with the Services APIThis tutorial helps you to create a simple program that uses the Services API to perform CRUD and queryoperations. It illustrates how to extend the functionality provide by a sample application developed using theApplication Deployment System.The tutorial uses a Custodian object to demonstrate how to create Relativity Dynamic Objects (RDOs) using atyped class in the kCura.Relativity.Client.DTOs namespace. The Custodian class represents a person and itsFields store data such as a phone number and first and last name.

4.4.1 Before you beginTo run this sample program, complete the following tasks to set up your development environment:

n Confirm that you have the required software. See Prerequisites for a development environment onpage 42.

n Create a workspace in your target Relativity instance. You don't need to add documents to the work-space.

n Confirm that you have these permissions:o Relativity Administrator rights to log in to Relativity through Services APIo Relativity Script Administrator rights to install an application

n Download RSAPIGettingStartedTutorial.zip file on the Relativity 8.1 Developers site. This file containsthe application and source code for this sample program.

n Unzip the Services API Tutorial Application, and install the RA_Tutorial_20130711213312.xml file to yourworkspace. For more information, see Installing an application on the Relativity 8.1 Developers site.

n Create a C# console application in Visual Studio. See Setting up a project in Visual Studio on page 43.

Page 46: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 46

Note: The code for this program references several constants that represent GUID and string values. TheTutorialConstants class provides a complete list of these constants. To view this class, open the Program.csfile included in the RSAPIGettingStartedTutorial.zip file.

4.4.2 Adding directives for required namespacesTo your applications, add using directives referencing the namespaces that contain the classes used to createa proxy and work with DTOs. If these Services API namespaces aren't available in your application, see Gettingstarted with the Services API on page 42.

using System;using System.Collections.Generic;using System.Linq;using kCura.Relativity.Client;using DTOs = kCura.Relativity.Client.DTOs;

4.4.3 Adding the Main methodThe sample program has a Main() method that includes code for calls to subsequent methods for creating theproxy, querying for Workspaces, creating an RDO, and performing other tasks.

public static void Main(string[] args){

// Create a client which uses Windows Authentication// to log in to the Relativity Services on the local machine.// Set up the current Windows user as a Relativity System// Administrator for the purposes of this tutorial.

using (IRSAPIClient client = CreateClient()){

// Query for a workspace and access it.// Change the following string to the name of a workspace in your copy ofRelativity.FindAndEnterWorkspace(client, TutorialConstants.TARGET_WORKSPACE_NAME);

// Create a Custodian RDO in the context of the workspace.Int32 rdoID = CreateRdo(client);

// Create an Address Field on the Custodian.Int32 fieldID = CreateField(client);

// Update the RDO with new data.UpdateRdo(client, rdoID, fieldID);

// Read the updated RDO.

Page 47: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 47

ReadRdo(client, rdoID);

// Query for the ArtifactIDs of all Custodians.QueryRdo(client);

// Delete the newly added Field from the Custodian RDO.DeleteField(client, fieldID);

// Delete the newly created RDO.DeleteRdo(client, rdoID);// Log out is handled by the RSAPIClient object.

} // Exiting the using block calls the Dispose() method on the RSAPIClient,which ensures the client is cleaned up.

PauseBeforeExit();}

4.4.4 Creating the RSAPIClient proxyYou must be authenticated before you can manipulate objects in Relativity through the Services API. Youneed to create an instance of the RSAPIClient class to hold the session data. The overloaded constructor forthe class provides you with the ability to choose the combination of endpoint type, authentication method,and optional configuration settings appropriate for your application development goals. The proxyautomatically logs in to Relativity using the specified AuthenticationType so you don't need to call a loginmethod. See Creating the RSAPIClient proxy on page 61.This code sample illustrates how to instantiate the proxy with a constructor that uses integrated Windowsauthentication.

public static IRSAPIClient CreateClient(){

// Create a new instance of RSAPIClient. The first parameter indicates theendpoint Uri,// which indicates the scheme to use. The second parameter indicates the// authentication type. The RSAPIClient members page in the Services APIclass library// documents other possible constructors. The constructor also ensures alogged in session.

string localHostFQDN = System.Net.Dns.GetHostEntry("localhost").HostName;Uri endpointUri = new Uri(string.Format("https://{0}/relativity.services",localHostFQDN));IRSAPIClient rsapiClient = new RSAPIClient(endpointUri, newIntegratedAuthCredentials());

Console.WriteLine("\tClient created and logged in.");

Page 48: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 48

return rsapiClient;}

4.4.5 Querying for a WorkspaceEach instance of the RSAPIClient class has an APIOptions property. Before you can use a workspace, you mustset theWorkspaceID property on APIOptions to its ArtifactID. You can perform a query on the name of theworkspace to return its ArtifactID.The following code sample illustrates how to use the Query DTO with a TextCondition to search for aWorkspace by name and then sets its ArtifactID on the APIOptions. This code uses a Like text condition, butyou could also an EqualTo condition. Both are available in the TextConditionEnum enumeration. SinceWorkspace names aren't required to be unique, the code sample calls the Any() method on the Resultsobject.This Workspace provides the context for other operations.

private static void FindAndEnterWorkspace(IRSAPIClient client, stringworkspaceName){

Console.WriteLine("\n\tFinding and entering Workspace...");

// Use the TextCondition to match workspaces with names similar to thespecified string.var workspaceCondition = new TextCondition(DTOs.ArtifactFieldNames.TextIdentifier,TextConditionEnum.Like, workspaceName);

// Build a query with the workspaceCondition.var query = new DTOs.Query<DTOs.Workspace> { Condition = workspaceCondition};query.Fields = DTOs.FieldValue.NoFields;

// Send the query and receive results.DTOs.QueryResultSet<DTOs.Workspace> results =client.Repositories.Workspace.Query(query);

if (!results.Success){

WriteFailedResultAndExit(results, client);}

if (!results.Results.Any()){

// No Workspace with the specified name exists.

Page 49: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 49

WriteErrorAndExit("No Workspace matching condition found.", client);}

// To begin using this workspace, set the WorkspaceID of your instance ofAPIOptions to the// ArtifactID of the Workspace.client.APIOptions.WorkspaceID = results.Results.First().Artifact.ArtifactID;

}

4.4.6 Creating a Relativity Dynamic Object DTOTo develop a custom application, you can create RDOs and other objects using the typed classes in thekCura.Relativity.Client.DTOs namespace. The classes in this namespace are called DTOs. See Data TransferObjects (DTOs) on page 67.This sample code shows you how to create Custodian RDO by completing the following steps that are alsocommon to other DTOs:

n Set all required properties for a newDTO.n Call the Create() method.n Confirm that the object was created successfully.n Save or return the ArtifactID for future use.

private static Int32 CreateRdo(IRSAPIClient client){

Console.WriteLine("\n\tCreating RDO... ");

var rdo = new DTOs.RDO();rdo.TextIdentifier = DateTime.Now.Ticks.ToString();rdo.Fields.Add(new DTOs.FieldValue(TutorialConstants.FIRST_NAME_FIELD_GUID,TutorialConstants.CUSTODIAN_FIRST_NAME_VALUE));rdo.Fields.Add(new DTOs.FieldValue(TutorialConstants.LAST_NAME_FIELD_GUID,TutorialConstants.CUSTODIAN_LAST_NAME_VALUE));rdo.Fields.Add(new DTOs.FieldValue(TutorialConstants.PHONE_NUMBER_FIELD_GUID,TutorialConstants.CUSTODIAN_PHONE_NUMBER_VALUE));

// Set the ArtifactTypeName, ArtifactTypeID, or ArtifactTypeGuids for anynew RDO.rdo.ArtifactTypeGuids = new List<Guid>() { TutorialConstants.CUSTODIAN_TABLE_GUID };

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(rdo);

// Check for success of Create() method.if (!results.Success){

Page 50: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 50

WriteFailedResultAndExit(results, client);}if (!results.Results.Any()){

WriteErrorAndExit("FAILURE: RDO creation succeeded but returned noArtifacts.", client);

}

// Get the ArtifactID of the new Custodian.Int32 rdoID = results.Results.Single().Artifact.ArtifactID;Console.WriteLine("\tArtifactID of new RDO: {0}", rdoID);

return rdoID;}

4.4.7 Creating a Field on a RDOYou can create Fields on DTOs to storemetadata and other information about them. To the Custodian RDO,you add a Field with a name, which includes the word Address followed by the count of CPU ticks since12:00:00midnight on Jan 1, 2001. This process ensures that Field name is unique, such as Address635133920940413625. For more information, see Field on page 113.

private static Int32 CreateField(IRSAPIClient client){

Console.WriteLine("\n\tCreating Field... ");

DTOs.Field field = new DTOs.Field();field.ObjectType = new DTOs.ObjectType(TutorialConstants.CUSTODIAN_TABLE_GUID);field.Name = string.Format("Address {0}", DateTime.Now.Ticks);field.FieldTypeID = FieldType.FixedLengthText;field.Length = 255;field.IsRequired = false;field.IncludeInTextIndex = false;field.Unicode = true;field.AllowHTML = false;field.OpenToAssociations = false;field.Linked = false;field.AllowSortTally = true;field.Wrapping = true;field.AllowGroupBy = false;field.AllowPivot = false;field.IgnoreWarnings = true;field.Width = "10";

Page 51: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 51

DTOs.WriteResultSet<DTOs.Field> results = client.Repositories.Field.Create(field);if (!results.Success){

WriteFailedResultAndExit(results, client);}if (!results.Results.Any()){

WriteErrorAndExit("FAILURE: Field creation succeeded but returned noArtifacts.", client);

}

Int32 fieldID = results.Results.Single().Artifact.ArtifactID;Console.WriteLine("\tArtifactID of new Field: {0}", fieldID);

return fieldID;}

4.4.8 Updating Fields on an RDOYou can update specific Fields on a DTO. This code sample creates a newDTO with the same ArtifactID as theone that you want to update. It illustrates how to update value of the Last Name and Text Identifier fields, andsets the value for the newly created Address field, which is currently blank.The ArtifactTypeGuids property indicates the object type of the RDO, which is Custodian. You can useArtifactGuid instead of ArtifactID, and ArtifactTypeID or ArtifactTypeName instead of ArtifactTypeGuids. Werecommend using GUIDs since they are unique across Relativity and they can't bemodified. See GUIDs inapplication development on page 78.This code sample updates the Last Name and Text Identifier fields on the Custodian RDO. It also sets theAddress, which is blank.

private static void UpdateRdo(IRSAPIClient client, Int32 rdoID, Int32 fieldID){

Console.WriteLine("\n\tUpdating RDO... ");

// rdoID is the ArtifactID of the RDO that you want to update.// The ArtifactTypeGuids indicates object type of the RDO, which isCustodian.// You can use an ArtifactGuid instead of the ArtifactID.var updatedRdo = new DTOs.RDO(rdoID);

// You can replace the ArtifactTypeGuids with either ArtifactTypeID orArtifactTypeName.// Use GUIDs because they are unique across all of Relativity and can't bemodified.

Page 52: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 52

updatedRdo.ArtifactTypeGuids = new List<Guid>() { TutorialConstants.CUSTODIAN_TABLE_GUID };

// List all Fields to be updated and their new values.// Any Fields not listed remain unchanged.updatedRdo.Fields = new List<DTOs.FieldValue>();updatedRdo.Fields.Add(new DTOs.FieldValue(TutorialConstants.LAST_NAME_FIELD_GUID,

TutorialConstants.UPDATED_CUSTODIAN_LAST_NAME_VALUE));updatedRdo.Fields.Add(new DTOs.FieldValue(TutorialConstants.TEXT_IDENTIFIER_FIELD_GUID,

TutorialConstants.UPDATED_CUSTODIAN_TEXT_IDENTIFIER_VALUE));updatedRdo.Fields.Add(new DTOs.FieldValue(fieldID,TutorialConstants.UPDATED_CUSTODIAN_ADDRESS_VALUE, true));

// Send updated RDO and receive results.DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(updatedRdo);

if (!results.Success){

WriteFailedResultAndExit(results, client);}Console.WriteLine("\tLast Name, Text Identifier, and Address [...] valuesupdated.");

}

4.4.9 Reading an RDOTo read, call the Read() method which takes a DTO of type RDO as an argument. The following code samplereads the ArtifactTypeName of the Custodian RDO.

private static void ReadRdo(IRSAPIClient client, Int32 rdoID){

Console.WriteLine("\n\tReading RDO... ");DTOs.ResultSet<DTOs.RDO> results =

client.Repositories.RDO.Read(new DTOs.RDO(TutorialConstants.CUSTODIAN_TABLE_GUID, rdoID));

if (!results.Success){

WriteFailedResultAndExit(results, client);}if (!results.Results.Any()){

Page 53: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 53

WriteErrorAndExit("FAILURE: RDO read succeeded but returned noArtifacts.", client);

}

// The following line prints "ArtifactTypeName of RDO is 'Custodian'."Console.WriteLine("\tArtifactTypeName of RDO is '{0}'.",results.Results.Single().Artifact.ArtifactTypeName);

}

4.4.10 Querying for RDOsYou can perform searches for RDOs by using the Query DTO. In addition, you can return specific Field valueson an Artifact by adding them to the query:

query.Fields.Add(new DTOs.FieldValue("Phone Number"));

You can use this sample code to query for all Custodians and then print their ArtifactIDs. If your workspacecontains only the newly added Custodian, then this code prints just its ArtifactID. For information aboutavailable fields, see Constant Field names on page 146.

private static void QueryRdo(IRSAPIClient client){

Console.WriteLine("\n\tQuerying RDO... ");

var rdoQuery = new DTOs.Query<DTOs.RDO>();rdoQuery.ArtifactTypeGuid = TutorialConstants.CUSTODIAN_TABLE_GUID;rdoQuery.Fields = DTOs.FieldValue.NoFields;

// To obtain more details about an Artifact, add Fields to the query.// For example, you might add: query.Fields.Add(new DTOs.FieldValue("PhoneNumber"));

// Send the Query to Relativity.DTOs.QueryResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(rdoQuery);

if (!results.Success){

WriteFailedResultAndExit(results, client);}if (!results.Results.Any()){

WriteErrorAndExit("FAILURE: RDO query succeeded but returned noArtifacts.", client);

Page 54: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 54

}Console.WriteLine("\tArtifactID of each Custodian:");

foreach (var res in results.Results){

Console.WriteLine("\t {0}", res.Artifact.ArtifactID);}

}

4.4.11 Deleting a Field on an RDOYou can remove a Field from an RDO by calling the Delete() method and passing the ArtifactID of the Field to it.To confirm the deletion, this code sample attempts to read the Field.

private static void DeleteField(IRSAPIClient client, Int32 fieldID){

Console.WriteLine("\n\tDeleting Field... ");

// Delete the Custodian RDO's newly added Field.DTOs.WriteResultSet<DTOs.Field> deleteResult =client.Repositories.Field.Delete(new DTOs.Field(fieldID));

// Try to read the same Field.DTOs.ResultSet<DTOs.Field> readResult = client.Repositories.Field.Read(newDTOs.Field(fieldID));if (!deleteResult.Success){

WriteFailedResultAndExit(deleteResult, client);}else if (readResult.Success){

WriteErrorAndExit("FAILURE: Reading back the deleted Field should nothave succeeded.", client);

}}

4.4.12 Deleting an RDOYou remove a DTO from Relativity by calling the Delete() method and passing the ArtifactID of the object to it.This code sample deletes the Custodian RDO and then attempts to perform a Read operation to confirm thatthis object no longer exists.

private static void DeleteRdo(IRSAPIClient client, Int32 rdoID){

Page 55: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 55

Console.WriteLine("\n\tDeleting RDO... ");

// Delete the Custodian with ArtifactID of rdoID.DTOs.WriteResultSet<DTOs.RDO> deleteResult =

client.Repositories.RDO.Delete(new DTOs.RDO(TutorialConstants.CUSTODIAN_TABLE_GUID, rdoID));

// Try to read the same Custodian.DTOs.ResultSet<DTOs.RDO> readResult =

client.Repositories.RDO.Read(new DTOs.RDO(TutorialConstants.CUSTODIAN_TABLE_GUID, rdoID));

if (!deleteResult.Success){

WriteFailedResultAndExit(deleteResult, client);}else if (readResult.Success){

WriteErrorAndExit("FAILURE: Reading back the deleted Custodian should nothave succeeded.", client);

}}

4.4.13 Exiting the programWhen you finish a session, you don't need to complete any additional steps to log out or close the proxy. TheRSAPIClient automatically completes these tasks. This sample code requests a response from the user beforethe program closes.

public static void PauseBeforeExit(){

Console.WriteLine("\nPlease press enter to end the program.");Console.ReadLine();

}

4.4.14 Writing success and failure messagesThe following sample code illustrates how to write out messages that indicate the success or failure of theprogram, as well as how to log out if an error occurs.

4.4.14.1 Obtaining a result messageThis sample code attempts to find the first Result in ResultSets with a non-empty, non-whitespacemessage.The individual Results usually contain a message indicating when a failure occurs. However, this code showsthe overall message for the ResultSet when a more specific failuremessage isn’t available. This code can beused to read themost specific messaging from any ResultSet. However, this program only attempts to read

Page 56: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 56

messaging from failed operations, because successful operations rarely contain messaging. See Obtaining anerror message below.

private static string GetResultMostSpecificResultSetMessage<T>(DTOs.ResultSet<T> results) where T : DTOs.Artifact{

string resultMessage = results.Results.Any(result =>!string.IsNullOrWhiteSpace(result.Message))

? results.Results.First().Message: results.Message;

return resultMessage;}

4.4.14.2 Stopping the program due to an errorThis sample code writes out a message and then logs out of the proxy when an error occurs.

private static void WriteErrorAndExit(String message, IRSAPIClient client){

Console.WriteLine(message);

PauseBeforeExit();

Environment.Exit(1);}

4.4.14.3 Obtaining an error messageThis sample code illustrates how to obtain an error message from a ResultSet object, and how to write out themessage before terminating the program. For more information about this code, see Obtaining a resultmessage on the previous page.

private static void WriteFailedResultAndExit<T>(DTOs.ResultSet<T> results,IRSAPIClient client) where T : DTOs.Artifact

{string failureMessage = GetResultMostSpecificResultSetMessage(results);

WriteErrorAndExit(string.Format("FAILURE: {0}", failureMessage), client);}

4.4.15 Building and running the programYou can download the complete source code for building and running the client in Visual Studio.

Page 57: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 57

Note: You need to install the application as well as update the username and password so the sampleprogram can run in your Relativity environment. See Before you begin on page 45.

After running your program, you should see results similar to that displayed here, but with differentArtifactIDs:

Proxy created.

Logged in.

Finding and entering Workspace.

Creating RDO...ArtifactID of new RDO: 1042640

Creating Field...ArtifactID of new Field: 1042641

Updating RDO...Last Name, Text Identifier, and Address […] values updated.

Reading RDO...ArtifactTypeName of RDO is 'Custodian'

Querying RD...ArtifactID of each Custodian: 1042640

Deleting Field…

Deleting RDO…

Please press enter to end the program.

5 Basic Services API conceptsLearn about the Services API features, architecture, deployment process, classes and methods by reviewingthese key concepts.

5.1 Services API featuresThe Services API enables you to write highly customized solutions on top of Relativity by providingfunctionality to perform these development tasks:

n Create Dynamic Objects for use in Relativity.n Create custom web pages with unique layouts that dynamically display information stored in a Relativ-

ity database.n Develop event handlers that run on pre-save, post-save, console, and other events within Relativity.n Integrate Relativity with external applications to extract, update, or add data.

Page 58: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 58

n Perform mass operations such as editing, creating, or deleting a group of Relativity objects in a singlecall.

n Create Relativity objects using DTOs, which ensure type safety and minimize casting errors.n Create custom agents to perform background processing and long-running operations.

5.2 Services API and the Relativity PlatformThe Services API is a major component of the Relativity platform, which also includes event handlers, custompages, and agents. It facilitates communication between each of these components and the Relativity engine(or business layer) by providing the proxy class necessary to interact with it. When a user performs a task, arequest is sent to the Services API, which passes these calls to the Relativity engine. The code in this layercontains the logic that controls processing of data and access to the database. The following diagramillustrates how the Service API is used by these components of the Relativity platform.

You can leverage the functionality provide by the Services API when you develop custom code for each ofthese key components:

n Custom pages - You can use custom pages to create a unique user interface for interactions with Relativ-ity through the Services API or direct database connections. With the Services API, you can perform val-idation and exception handling to control the interactions between your custom pages and theRelativity engine. These programming options aren’t available through direct database connections.When you create a custom page, reference the kCura.Relativity.Client.dll, which is the assembly usedto obtain a proxy by instantiating the RSAPIClient class.

n Event Handlers - You can develop new event handlers or modify existing ones to provide custom func-tionality. They are called only in the Relativity web UI and they perform operations based on useractions. Event handlers communicate with Relativity through the Services API, the ActiveArtifact class,or direct database connections. To use the Services API, you can reference the kCur-a.Relativity.Client.dll in your event handler code, and use API Helpers to create an instance of the

Page 59: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 59

RSAPIClient class, which provides methods on the proxy and exception handling. For more informationsee Getting Started with the Relativity API Helpers on the Relativity 8.1 Developers site.

n Agents - You can also use agents to communicate with the Relativity engine through an instance of theServices API. Agents are background processes that run jobs performing processing, indexing, or othercustom tasks. Many Relativity environments usemultiple agent servers to run these background jobs.On each server, theWindows Service is used to deploy a copy of the Services API rather than using IIS.Since the agent server is self-hosting an instance of the Services API, the address of the proxy is alwayslocalhost. An advantage of this configuration is reduced network traffic since the agents can use theproxy on their local machine rather than send requests to a web server hosting it. It also eliminates theneed to install the IIS on agent servers.

5.3 Client ProxyIn the Services API, the client-side proxy enables applications to send and receivemessages over a variety oftransport protocols. This proxy is created by instantiating the RSAPIClient class that lives in thekCura.Relativity.client.dll. To use the Services API for custom development, you need to write .NET code andreference this assembly in your project. You also have to configure endpoints that this proxy uses tocommunicate with the Services API. When you call an operation on the RSAPIClient, your request is sent tothe Services API.

5.3.1 Backwards CompatibilitykCura strives to maintain backwards compatibility with each release of the Services API. Compatibility isguaranteed at the .NET client level, which means that the public methods and classes of the client usuallydon’t change in a breaking way. In contrast, the web methods exposed at the server do change betweenreleases. By using the RSAPIClient proxy, you are shielded from back-end changes made to the Services API. Ifbreaking changes are introduced to the client library, the Services API release notes clearly documents them.Because the web methods used by the RSAPIClient can change between releases, the Services API doesn'tsupport the development of custom proxies that directly communicate with theWSDL definitions provided byRelativity.Services. You shouldn't attempt to create your own .NET proxy based on theWSDLs provided bythose services.

Page 60: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 60

5.4 Deploying the Services APIYou deploy the Services API as a web-based service hosted hosted in Internet Information Services (IIS).Youcan configure your environment with all available endpoints, including HTTPS, HTTP, Net.TCP, and Net.Pipe.The Services API supports username/password and Windows authentication methods.

5.4.1 Deploying the Services APIThe Relativity Services API is a web service based on Windows Communication Foundation (WCF), and it ishosted on IIS. The Services API has its own virtual directory and runs in its own application pool. In addition, itcan be installed with theWebAPI as part of the Relativity web server component.The Services API is installed on the Relativity web server as an additional IIS application, calledRelativity.Services. Most of the configuration of Relativity.Services is determined by the settings in theweb.config file of the Relativity.Services virtual directory. Some configuration options are also controlledthrough the Configuration table of the EDDS database.In addition, a local version of the Services API runs on every agent server in your environment. This serviceuses the same code and database connection as your other Services API servers. However, the Services API onthe agent server is self-hosted inside the agent Windows service, so you don't need to install any IISinfrastructure on the servers. Since only the agents on these servers use the Services API, the service onlylistens on the loopback interface using a named pipe and TCP port 6867. No firewall changes or otherconfiguration should be required in most cases.

Note: If your environment already uses the TCP port 6867 for other software, you can update value for theport number in the ServicesAPIMetadataPortOnAgentServers setting in the Configuration table on theEDDS database. For more information about settings used for hosting the Services API on the agentservers, see the Configuration Table guide on the Relativity 8.1 Documentation site.

5.4.2 Transport protocolsThe Services API supports the following data transport protocols:

n HTTPS - All data transmissions are encrypted using Internet standard SSL technology. They are trans-mitted over TCP port 443 by default. HTTPS is the default transport configuration.

n HTTP -While the transport isn't encrypted, themessages are encrypted. Data is transmitted over TCPport 80 by default.

n Net.TCP - Data has a binary format rather than the XML used for HTTP/HTTPS configurations, and per-forms better than HTTP/HTTPS configurations. Since this transport protocol uses binary formattingthat is proprietary to Microsoft and not interoperable with other SOAP stacks, it suitable only for cli-ents written in .NET. Data is transmitted over TCP port 808 by default.

n Net.Pipe - Uses a shared-memory pipe between the client and server. It is the fastest of the transportprotocol options used by the Services API, but is restricted to clients written in .NET, and to envir-onments with clients and servers running on the samemachine.

5.4.3 AuthenticationType classes supported by the RSAPIClientWhen you instantiate the RSAPIClient, the constructor takes an object of AuthenticationType as an argument.The Services API includes the following subclasses of the AuthenticationType class that you can use to specify

Page 61: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 61

the type of authentication used for the connection to the RSAPIClient:

n IntegratedAuthCredentials - indicates the use of integrated Windows authentication.n TokenCredentials - indicates the use of token authentication. This authentication type requires you to

supply a token.n UsernamePasswordCredentials - indicates the use of username and password authentication. This

authentication type requires you to supply a username and password.For code samples illustrating how to use these authentication types

5.4.4 Summary of authentication methods and endpoint typesThe following table lists the combinations of transport and authentication types supported by the ServicesAPI.

Endpoint Type Authentication TypeUsername and Password Windows Authentication

HTTPS Supported SupportedHTTP Supported SupportedNet.TCP Supported SupportedNet.Pipe Supported Supported

5.5 Creating the RSAPIClient proxyWith the RelativityServices API, you can creating a proxy that uses transport protocols, such HTTPS, HTTP,Net.TCP, or Net.Pipe (.NET named pipes). The RSAPIClient class simplifies this process by providing anoverloaded constructor that takes Uri and AthenticationType objects, as well as client-side override settingsspecified in an RSAPIClientSettings object.

Note: For more information about the deprecated ArtifactManagerProxy class, see the Relativity 8Developers site.

5.5.1 RSAPIClient class overviewThe RSAPIClient class exposes all of the available Services API functionality by connecting to theAuthentication, DataManipulation, SetExecutor, and FileTransfer services. You can instantiate this class tocreate a proxy that includes methods used to interact with DTOs and other artifacts.

5.5.1.1 Properties and methods on the RSAPIClient classThe RSAPIClient class has the following properties:

n APIOptions - provides instance of APIOptions class associated with this proxy instance. See APIOptionsclass on the next page.

n AuthType - retrieves information about the authentication type used by the proxy to connect to theServices API. It is an AuthenticationType object. See AuthenticationType classes supported by theRSAPIClient on the previous page.

n EndpointUri - indicates the URI for the Services API URI of Relativity.Services running on the IIS. For

Page 62: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 62

example, it uses the format "http://localhost/Relativity.Services".n Repositories - provides access the group of repositories that support typed data transfer objects.

This class includes a comprehensive set ofmethods, which you can use to log in, create Artifact requests,query for Artifacts, and perform other tasks.

5.5.2 APIOptions classThe APIOptions class controls who makes a call for any given method, where this user is making the call to,and how that call behaves. Themembers of this class include the following properties:

n Token – represents an authenticated user. This property is automatically populated with a token valuewhen the user is authenticated so you don’t need to explicitly call a login method. However, if you wantto switch to another user, you can call the Login(), LoginWithCredentials(), or TokenLogin() to authen-ticated the new user. For sample code, see Token login on page 65.

n WorkspaceID – represents the unique identifier for a workspace in Relativity. A value of -1 indicates themaster EDDS database.

n StrictMode – determines the convention used when returning or supplying fields to the Create(), Read(), Update(), Delete(), and Query() methods. When this field is True, a subset of fields (using consistentnames and datatypes) are available across the various methods. This property is False by default. Formore information, see StrictMode property and Field directives on page 73.

Note: Some Fields available in Relativity 7.4 may have different names or may be unavailable when thisbehavior is enabled by setting the property to True.

5.5.3 RSAPIClientSettings classYou can programmatically set client-side configuration by passing an RSAPIClientSettings object to theoverloaded constructor for the RSAPIClient class. This RSAPIClientSettings class can be used to define theCertificateFindValue and the CertificateValidation settings. See Setting client configuration overrides on page19.

5.5.4 RSAPIClientServiceOperationFailed eventRSAPIClientServiceOperationFailed event is raised when the RSAPIClient throws an exception due to a failureor operation error. See RSAPIClientServiceOperationFailed event in the Services API class libraries.

5.5.5 Best practices for proxy creationUse these guidelines when you create the proxy:

n Create your proxy within a using statement in your code.n Use an appropriate AuthenticationType object to specify the login type.

Note: If you use an AuthenticationType object, the proxy automatically logs in to the Services API so you don'tneed to call a login method. See AuthenticationType classes supported by the RSAPIClient on page 60 andToken login on page 65.

Page 63: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 63

n Omit additional code for logging out or closing the session, since the RSAPIClient proxy automaticallycompletes these tasks.

n Use themethods in the Relativity API Helpers to create the proxy in agents, custom pages, and eventhandlers. See Creating the proxy in an agent, custom page, or event handler below.

n To configure the Services API manually for agents, custom pages, and event handlers, use theguidelines provided in Manually configuring the Services API for the Relativity platform on page 18.These guidelines highlight the use of Relativity API Helpers for obtaining the Relativity.Services URL.

5.5.6 Creating the proxy in an agent, custom page, or event handlerYou can use themethods available in the Relativity API Helpers to create the proxy in agents, custom pages,or event handlers. The CreateProxy() method is available on the IServicesMgr interface in the Relativity APInamespace. In your code, you call this method on the object returned by the GetServiceManager() method,which is available on the agent, custom page, and event handler helper classes also provided in the RelativityAPI Helpers. For more information, see Getting Started with the Relativity API Helpers in the Relativity 8.1Developers site.On the Relativity 8.1 Developers site, see these pages for code samples that illustrate how to create the proxyin the agents, custom pages, or event handlers that you develop:

n Creating custom agentsn Creating custom pagesn Getting started with event handlers includes links to code samples for specific event handler types,

such as Pre Delete event handlers and others

5.5.7 Code samples for proxy creation in a console applicationThese code samples illustrate how to create the proxy using each of the supported protocols. You specify theprotocol in the string used to create the Uri object. For convenience, the code samples useIntegratedAuthCredentials, which is integrated Windows authentication.

n Basic proxy creation

try

{

using (IRSAPIClient proxy =

new RSAPIClient(new Uri("http://localhost/Relativity.Services"), new

IntegratedAuthCredentials()))

{

// Add your custom code.

}

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

Page 64: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 64

n Basic proxy creation with HTTPS endpoint

try

{

using (IRSAPIClient proxy =

new RSAPIClient(new Uri("https://localhost/Relativity.Services"), new

IntegratedAuthCredentials()))

{

// Add your custom code.

}

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

n Basic proxy creation with HTTP endpoint

try

{

using (IRSAPIClient proxy =

new RSAPIClient(new Uri("http://localhost/Relativity.Services"), new

IntegratedAuthCredentials()))

{

// Add your custom code.

}

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

n Basic proxy creation with Net.TCP endpoint

try

{

using (IRSAPIClient proxy =

new RSAPIClient(new Uri("net.tcp://localhost/Relativity.Services"), new

IntegratedAuthCredentials()))

{

// Add your custom code.

}

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

Page 65: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 65

}

n Basic proxy creation with a Net.Pipe endpoint

try

{

using (IRSAPIClient proxy =

new RSAPIClient(new Uri("net.pipe://localhost/Relativity.Services"), new

IntegratedAuthCredentials()))

{

// Add your custom code.

}

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

5.6 Token loginWithin the Relativity platform, you can use tokens for establishing connections in the following ways:

n Services API – To log in to the Services API, you create the proxy using the TokenCredential authen-tication type. You can also create a proxy and log in to the Services API by using the Relativity API Help-ers. The helper classes facilitate creating the proxy and retrieving this session token from an agent,custom page, or event handler. They use this one-time session token as a parameter in the TokenLogin() method on the RSAPIClient class. As a best practice, use the helper classes to facilitating creating aproxy and authenticating to the Services API. For more information, see Getting Started with theRelativity API Helpers.

n Relativity – You can use a token to log in to the Relativity interface. The RSAPIClient class has the Gen-erateRelativityAuthenticationToken() method that you can use to obtain an authorization token forthis purpose.

5.6.1 Creating the proxy using a tokenYou can perform a token login by creating the proxy with the TokenCredential authentication type. When youspecify the AuthenticationType, the proxy automatically logs in to the Services API so you don't need to call alogin method. For information about creating the proxy in an agent, custom page, or event handler, seeGetting Started with the Relativity API Helpers.The following code sample illustrates how to use this authentication type when creating the proxy.

try{

using (IRSAPIClient proxy =

Page 66: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 66

new RSAPIClient(new Uri("http://localhost/Relativity.Services"), newTokenCredential(token)))

{// Add your custom code.

}}catch (Exception ex){

Console.WriteLine(ex.Message);}

5.6.2 Generating an authorization token for RelativityYou can use the GenerateRelativityAuthenticationToken() method on the RSAPIClient class to obtain a tokenfor logging in to the Relativity interface. This authorization token is generated from a session token obtainedfrom proxy. For more information, see APIOptions class on page 62.

Note: You can also appended this authorization token to an HTTP query string as authToken=<value>. Formore information, see REST API authentication.

public void GenerateRelativityAuthenticationToken(){

try{

// Step 1: Create a proxy, using either UsernamePasswordCredentials,IntegratedAuthCredentials,// or TokenCredentials.using (IRSAPIClient proxy =

new RSAPIClient(new Uri("net.pipe://localhost/Relativity.Services"),new IntegratedAuthCredentials()))

{// STEP 2: Generate Relativity authorization token from session tokenand return it in ReadResult object.ReadResult readResult = proxy.GenerateRelativityAuthenticationToken(proxy.APIOptions);

// STEP 3: Pull token out of ReadResult object for use as needed.if (readResult.Success){

string authToken = readResult.Artifact.getFieldByName("AuthenticationToken").ToString();Console.WriteLine(String.Format("Successfully generated Relativityauthorization token {0}", authToken));

}

Page 67: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 67

else{

Console.WriteLine(String.Format("An error occurred generatingRelativity authorization token: {0}", readResult.Message));

}}

}catch (Exception ex){

Console.WriteLine(String.Format("An error occurred generating Relativityauthorization token: {0}", ex.Message));

}}

5.7 Data Transfer Objects (DTOs)The Services API now includes Data Transfer Objects (DTOs) that simplify coding and minimize errors byproviding typed wrappers for system Artifacts and Fields.

Note: While the Services API continues to provide support for the untyped layer, the use of DTOs isrecommended for any new development.

5.7.1 DTO FeaturesDTOs provide the following features as well as offering typed wrappers for system Artifacts and Fields:

n Client methods organized into typed Repositories, such as DocumentRepository, BatchRepository, andothers

n Consistent field values based on the type of the Field. In conjunction with DTOs, you can set theStrictMode property on the APIOptions class, which causes the Services API to return consistent Fieldsfor the Read() and Query() methods across all ArtifactTypes.

Note: Some Fields available in Relativity 7.4 may have different names or may be unavailable when thisbehavior is enabled by setting the property to True. By default, StrictMode is set to False so the Services APIcontinues to return the same Fields as in Relativity 7.4. See StrictMode property and Field directives on page73.

n ParamArray versions ofmany List parametersn Automatic use of the APIOptions instance held in the RSAPIClient class, so no manual coding is

required. See Creating the RSAPIClient proxy on page 61.n Constants for system Artifact and Field namesn Deep field retrieval on explicit requestn Casting methods for dynamic Fieldsn Eliminates use of byte array for string values

This functionality is available in the kCura.Relativity.Client.DTOs and other namespaces.

Page 68: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 68

5.7.2 Supported DTOsYou can use the following table to locate code samples for DTOs. The table lists the Relativity version when thesupport for a specific operation was first introduced. Click the version number under an operation to display acode sample for it.

DTO Supported Operations(listed by earliest supported version)

Create Read Update Delete Query OtherBatch on page 82 7.5 7.5 7.5BatchSet on page85

7.5 7.5 7.5 7.5 7.5 Cancel - 7.5Purge - 7.5

Choice on page 95 7.5 7.5Client on page 97 7.5 7.5 7.5 7.5 7.5Document onpage 103

7.5 7.5 7.5 7.5 7.5 Download native file - 7.5

Error on page 112 7.5Field on page 113 7.5 7.5 7.5 7.5Folder on page153

7.5 7.5 7.5 7.5

Group on page158

7.5 7.5 7.5 7.5 7.5

Layout on page163

7.5 7.5

MarkupSet onpage 166

7.5 7.5 7.5 7.5 7.5

ObjectType onpage 172

7.5 7.5 7.5 7.5 7.5

RDO on page 177 7.5 7.5 7.5 7.5 7.5Relativ-ityApplication onpage 186

7.5 7.5

RelativityScript onpage 189

7.5 7.5 Execute - 7.5Retrieve input -7.5

Tab on page 196 7.5 7.5User on page 198 7.5 7.5 7.5 7.5 7.5View on page 207 7.5 7.5Workspace onpage 210

7.5 7.5

The operations listed in the previous table are supported at the following levels for DTOs:

n Master database -Workspace, Client, User, and Groupn Master database and Workspace - RelativityScript and Choicen Workspace - all other ArtifactTypes

Page 69: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 69

Note: For Error, the Create() method is supported at the master database and Workspace levels. However,all Errors are written to the master database, and theWorkspace where the Error occurred is inferred fromtheWorkspaceID value set in the APIOptions instance.

5.8 Untyped base ArtifactsThe RSAPIClient supports a limited set of operations on untyped base Artifacts, and Fields. The use of untypedArtifacts and Fields was required by Services API in Relativity 7.4 or below.

Note: While the Services API continues to support the untyped layer, use DTOs to simplify development byeliminate the need for casting. Implement any new development with DTOs. See Data Transfer Objects(DTOs) on page 67.

5.8.1 RSAPIClient support for ArtifactTypesThe following table lists the ArtifactTypes and operations supported in the untyped layer.

ArtifactTypes Supported OperationsCreate Read Update Delete Query

Batch on page 79 Yes Yes YesBatchSet on page 79 Yes Yes Yes Yes YesChoice on page 79 Yes YesClient on page 79 Yes Yes Yes Yes YesDocument on page 80 Yes Yes Yes Yes YesError on page 80 YesField on page 80 Limited sup-

port forCreate() onFields on thenext page

Yes Yes Yes

Folder on page 80 Yes Yes Yes YesGroup on page 80 Yes Yes Yes Yes YesLayout on page 80 Yes YesMarkupSet on page 80 Yes Yes Yes Yes YesObjectType on page 80 Yes Yes Yes Yes YesRelativityApplication on page80

Yes Yes

Relativity Dynamic Object(RDO) on page 80

Yes Yes Yes Yes Yes

RelativityScript on page 80 Yes YesTab on page 80 Yes YesUser on page 80 Yes Yes Yes Yes YesView on page 80 Yes YesWorkspace on page 81 Yes Yes

Page 70: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 70

5.8.2 Limited support for Create() on FieldsThe Services API supports the Query() method and a limited version of the Create() method on the Fieldsystem type. The Create() method doesn't currently support the creation of the Decimal and Currency fieldsthrough the API.

Properties Supported for Create() on FieldAllowGroup By Identifier Open to AssociationsAllowHTML Import Behavior OrderAllow Pivot Include in Text Index Pane IconAllow Sort/Tally Keywords RelationalAssociative Object Type Length RequiredAvailable In Field Tree Linked UnicodeAvailable In Viewer Name WidthField Type Notes WrappingFriendly Name Object Type Artifact Type ID Yes/No Field Display Values

When a Field is created through the Services API, the unsupported properties are set to their default values.

Properties Set to Default ValuesField Tree View Popup Picker ViewFilter Type Propagate toFormatting Relativity ApplicationsKeyboard Shortcut

5.8.3 Field (untyped)Relativity uses fields to store document and other metadata, as well as coding selections made by a reviewer.It provides multiple Field types to support this functionality, which are also available through the Services API.

5.8.3.1 System type fieldsSystem type fields are properties on the base Artifact class. In the untyped layer, the base Artifact has thefollowing properties:

Base Artifact Properties in the Untyped LayerArtifactID ArtifactTypeNameArtifactGuids ArtifactTypeGuidsArtifactTypeID ParentArtifactID

Since system type Fields don't have IDs, you must request them by name. Certain Fields have both a displayname used in the Relativity web UI, and an SQL column name used to reference the Field in the database. Forexample, Field has a property with the display name Created By that contains a username as a String, and anSQL column name of CreatedByName. Another property has no display name, but an SQL column name ofCreatedBy, which returns the user’s ID.You can use either namewhen requesting Fields during a read or query operation. The Services API returnsthe Field using the name referenced in your request. If you don't specify any Fields in a request, the API will

Page 71: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 71

return all Fields using the display names when they exist and the SQL names when no display names areavailable.

You can also set the StrictMode to maintain consistency on the Fields returned by the Services API, and fielddirectives to indicate when you want all or no Fields returned.

5.8.3.2 Using Field types in the untyped layerField types are handled differently depending on whether you work with them through the DTO or untypedlayer. While the Services API continues to support the untyped layer, the use of DTOs is recommended for anynew development.

FixedLengthText and LongText Fields

In Relativity, a long text field is larger than 4,999 characters, while a fixed length fields is less than or equal tothis number of characters. In the untyped layer, all strings are encoded as byte arrays. The .NET client isprovided with the GetString() method, which converts a byte array into a String.

These FixedLengthText and LongText fields are handled in this way because the Services API is exposed as a setof SOAP Web Services. The content of all fields is serialized as XML while being transported from the server tothe client. XML enforces restrictions on the characters that may be used in strings. Consequently, the ServicesAPI doesn't use the XML string data type since fields within Relativity may contain text extracted fromdocuments, containing characters prohibited by XML.

SingleChoice Fields

In Relativity, a single choice field has a predetermined set of values called choices. A user can only select one ofthese choices for coding or other purposes. Use these guidelines for SingleChoice fields:

n Create or update SingleChoice fields on documents or RDOs. You can set the values on these Fields toan ArtifactID or GUID, but not to a text representation of a Choice. For example, you can set the valueof the Field Single Choice Field on a Document or Dynamic Object to a Choice using its ArtifactID (suchas 100456) or its GUID. The following sample code illustrates how to set a SingleChoice in the untypedlayer:

artifactRequest.Fields.Add(new Field("Single Choice Field", 100456));

n Retrieve a list of valid Choices for a SingleChoice field as follows:o Perform a read operation using the ArtifactID for Single Choice Field and the ArtifactTypeName

of Field (or ArtifactTypeID = 14).o Request that the Choices field is returned. A List of kCura.Relativity.Client.Choice objects is

returned.n Read operations on a SingleChoice field return the following data:

o Type of the Value property is kCura.Relativity.Client.Choiceo Text value of the Choice set on the Field is the Name property of the Choice objecto ArtifactID property of the Choice object is the ArtifactID of the Choice definition within theWork-

spaceo ArtifactGuids property will be a List of GUIDs assigned to Choice definition

Page 72: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 72

MultiChoice Fields

In Relativity, a multiple choice field has a predetermined set of values called choices. A user can select severalchoices for coding or other purposes. Use these guidelines for MultiChoice fields:

n Set the values of a MultiChoice Field by defining a MultiChoiceUpdateValue that includes in its Valueproperty a List of Integers, which are the ArtifactIDs of the individual Choices in theMultiChoice Field.Alternatively, provide the ValueAsGuid property, which is a List containing a List of GUIDs that rep-resent the ArtifactIDs of the individual Choices. The value is updated based upon theMultiChoiceUp-dateValue.Method property. It is replaced with new values or merged with existing ones. SeeMultiChoiceUpdateValue in the Services API Class Library.

n Read operations for a MultiChoice Field on a Document or Dynamic Object return the selected valuesas a .NET generic list (that is List<Choice>).

SingleObject Fields

Relativity uses a SingleObject field to define a one-to-many relationship between two objects. Use theseguidelines for SingleObject fields:

n Set a a SingleObject field in the untyped layer by passing the Integer value of the ArtifactID as the fieldvalue.

n Read or query operation return a SingleObject field as an Int32. The value of this field is the ArtifactID ofthe Object.

MultipleObject Fields

Relativity uses a multiple object field to define a many-to-many relationship between two objects. Use theseguidelines for MultiObject fields:

n Set a MultipleObject field by passing a List of Int32 values for the Artifact IDs.n Read or query operations return a MultipleObject field as an Int32. The values for this field are the Arti-

factIDs of the objects.

User Fields

In Relativity, a user field contains Relativity users with rights to the current workspace. Use these guidelinesfor User fields:

n Create and update operations require you to set the User field to an ArtifactID.n On read and query operations, the Value property of the field has the type kCura.Relativity.Client.User,

which provides both the Name and the ArtifactID of the user.

5.8.3.3 Querying for Fields associated with an ArtifactTypeYou can use the Query() method to retrieve ArtifactIDs and the Names of all Fields associated with a specificArtifactType. The search returns only Fields that the logged in user has permissions to view. The Field Typefield supports only TextCondition.

//STEP 1: Create a Query to describe the search you want to run.Query q = new Query();

Page 73: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 73

//STEP 2: Use an ArtifactType enum to set the ArtifactTypeID based on the typeof item that you want to query on. Set the ArtifactTypeName to the name of theitem type.

q.ArtifactTypeID = (int) ArtifactType.Field;q.ArtifactTypeName = "Field";

//STEP 3: Create a Fields list to indicate which fields you want returned.q.Fields.Add(new Field("Name"));q.Fields.Add(new Field("Artifact ID"));q.Condition = null;q.RelationalField = null;q.Condition = new TextCondition("Object Type", TextConditionEnum.EqualTo,"Document");

5.9 StrictMode property and Field directivesIn the Services API, you can use the StrictMode property and Field directives to control how the Fieldscollection on an Artifact is handled when it is returned.

5.9.1 StrictMode property for DTOsThe StrictMode property is used to provide consistency in the Fields returned across all ArtifactTypes. Whenyou enable StrictMode, Fields have the following behavior through the Services API:

n Consistent population and naming of system type fields, including System Created By, System CreatedOn, System Last Modified By, System Last Modified On, and Relativity Text Identifier.

n Text fields returned as Strings.n ArtifactID is available on the base Artifact.n Read() and Query() methods return the same Fields collection.n Create() and Update() methods use the same Field names as those returned by Read and Query.n User fields are always returned as a User object with an ArtifactID and Full Name.n Choice fields are always returned as a Choice object with an ArtifactID and Name.

StrictMode is a Boolean property on the APIOptions object:

proxy.APIOptions.StrictMode = True

5.9.2 Field directives for DTOsThe Services API provides the AllFields and NoFields directives to ensure that the Fields collection on anArtifact is handled consistently when returned across supported operations:

n AllFields – Use this directive to return all of the Fields on an Artifact.n NoFields – Use this directive when you don't want to return any of the Fields on an Artifact. Only the

base Artifact is populated.You can use the AllFields and NoFields directives on the read and query operations for DTOs.Read operation using AllFields:

Page 74: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 74

DTOs.RDO dto = new DTOs.RDO(1036225);dto.Fields = FieldValue.AllFields;

Query operation using NoFields:

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();query.Fields = FieldValue.NoFields;

The SelectedFields directive is available for use with a SavedSearchCondition or ViewCondition on a query. Formore information, see SavedSearchCondition on page 229 or ViewCondition on page 233.

5.9.3 StrictMode and the TextIdentifer property (untyped layer)The Services API provides a TextIdentifier property that displays the Identifier field of an object. For example,TextIdentifier equals the Name field on instances of Dynamic Objects. You can use it in place of the Nameproperty on Dynamic Objects. If you set both the TextIdentifier and Name properties during object creation,their values must be equal or you will receive an error message.In the untyped layer, when StrictMode is set to True, the ArtifactRequest and query operations return a fieldcalled Relativity Text Identifier. These operations don't consistently return the TextIdentifier property whenStrictMode is False.Use the constant kCura.Relativity.Client.Constants.RELATIVITY_TEXT_IDENTIFIER to reference the RelativityText Identifier field.

5.9.4 Field directives (untyped layer)The Services API provides the AllFields and NoFields directives to ensure that the Fields collection on anArtifact is handled consistently when returned across supported operations:

n AllFields – Use this directive to return all of the Fields on an Artifact.n NoFields – Use this directive when you don't want to return any of the Fields on an Artifact. Only the

base Artifact is populated.

Note: The SelectedFields directive is available for use with a SavedSearchCondition or ViewCondition on aquery.

You can use the AllFields and NoFields directives on the read and query operations for the untyped layer.Read operation with AllFields:

ArtifactRequest artifactRequest = new ArtifactRequest();artifactRequest.Fields = Field.AllFields;

Query operation with NoFields:

Page 75: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 75

Query query = new Query();query.Fields = Field.NoFields;

5.10 Best practices for the Services APIUse these guidelines to optimize your application development with the Services API.

5.10.1 Use DTOs whenever possibleUse of strongly typed DTOs as the preferred programming model for the Services API. DTOs provide type-safeaccess to common Relativity object types. In addition, they offer the benefit of consistent Field names andresult datatypes. See Data Transfer Objects (DTOs) on page 67.

Note: While the Services API continues to support the use of the ArtifactManagerProxy as an accessmethod, the DTOs provide similar functionality as well as these additional benefits.

5.10.2 Bring back only Fields that you need for optimum performanceWhen you make request for all Fields on an Artifact, it increases the overhead on your application. To ensureoptimum performance, don’t use the AllFields directive unless your client side-code requires every Field on anArtifact. Avoid returning Fields that your code never uses. See Field directives for DTOs on page 73.

5.10.3 Don’t use the Services API to bulk-load dataAvoid or minimize the use of the Services API when loading large amounts of data into Relativity. In general,the Services API is designed for end-user application access patterns. Although it does have the ability to bulk-load data, the Services API isn’t optimized for that use case. Consider using the Import API when you havelarge amounts of data to load. Loading data through the Services API and Import API is complementary andcan be used within the same application. Try benchmarking both approaches in your environment so thatyou can determine which API offers the optimum performance. See the Import API on the Relativity 8.1Developers site.

5.10.4 Work in batchesUse batches to send medium-to-large data sets to the Services API. Break your create operations into batchsizes appropriate for your data and environment. Batches of 1,000 objects are far better than batches of 1million. For example, single request to create 10,000Dynamic Objects is hard on memory and bloats yourmessage payload. You may even reach the configured limits for maximum message size, which you want toavoid doing even though this setting can be overridden through server configuration values.

5.10.5 Use GUIDs to reference Fields and object typesMake your custom applications resilient by using unique identifiers (GUIDs) when referring to Fields, objecttypes, and Choices. This approach offers significant advantages over programming against the name of anArtifact when using the Application Deployment System (ADS) to develop custom applications. It avoids nameconflicts that can occur when Artifacts from a custom application are imported into a Relativity workspace,

Page 76: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 76

containing objects with similar names. The ADS provides the ability to rename Fields during import, since itassigns a GUID to each Artifact. While a powerful technique for working with custom applications, it alsorequires correct handling. The use of GUIDs simplifies development since changes in the names of Fields andobject types can occur at any time.You can find the GUIDs in the custom application XML that you export from Relativity. On your developmentmachine, you can also search the ArtifactGuid table for a workspace to find a GUID for a specific Artifact. Werecommend that you add GUIDs to a constants class in your code base and use those constants in your code.See GUIDs in application development on page 78.

5.10.6 Install and uninstall applications through the ADSWhen building your application, take advantage of the ADS provided by Relativity. The ADS is designed forpackaging your schema into an application and deploying it to the workspace you are developing against.While you can create object types and Fields using the Services API, this system provides powerful tools forsetting up your schema in a workspace. See Application Deployment System guide.

5.10.7 Use of the APIOptions token propertyWith the inclusion of the APIOptions as a property on the RSAPIClient class, you don't need to explicitly trackthe token returned from the Login(), LoginWithCredentials(), or TokenLogin() method. A successful call toeither of thesemethods automatically populates the Token property of the APIOptions property.

Note: The Token property is automatically populated with a token value when the user is authenticated soyou don’t need to explicitly call a login method. However, if you want to switch to another user, you cancall one of the login methods to authenticated the new user.

See the following code sample:

try {proxy.Login();

} catch (Exception ex) {throw new Exception(String.Format("An error occurred logging in: {0}",ex.Message), ex);

}Console.WriteLine("APIOptions.Token is {0}", proxy.APIOptions.Token);

The result of the call to Login() method isn't explicitly stored, and it is automatically available via the Tokenproperty of APIOptions.

5.10.8 Avoid specific version assembly referencesWhen you are developing with a reference to the kCura.Relativity.Client assembly, avoid using the SpecificVersion reference on the Reference Properties window in Visual Studio.

Page 77: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 77

When a custom assembly is loaded for an event handler, agent, or custom page, common .dll files (such askCura.Relativity.Client.dll) are automatically copied into the domain from the lib folder. If you set the SpecificVersion option in Visual Studio, it may not match the version of the .dll files installed on the environment.This mismatch may prevent your application from executing properly, if at all.

Note: Don't package the kCura.Relativity.Client.dll with your application. If you package this .dll file withyour application, it may be overwritten or ignored when you deploy the application in Relativity.

5.10.9 Use constant Field names for Read() and Query()methodsWhen calling the Read() and Query() methods on DTOs, you can reference the constant strings assigned toField names. See Constant Field names on page 146You can also use the AllFields directive while in the development phase to discover available Fields:FieldValue.AllFields.

5.10.10 Use Services API enumerations or constantsThe Services API provides enumerations and constants that you can use instead of strings or integers in yourcode. For example, this code illustrates how to use the constant DescriptorArtifactTypeID on theObjectTypeFieldNames class instead of the string "Descriptor Artifact Type ID":

objectTypeQuery.Condition =new WholeNumberCondition(ObjectTypeFieldNames.DescriptorArtifactTypeID,NumericConditionEnum.EqualTo, 1000035);

For more information, see ArtifactType under the kCura.Relativity.Client namespace, orObjectTypeFieldNames under the kCura.Relativity.Client.DTOs namespace in the Services API class library.

Page 78: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 78

5.11 GUIDs in application developmentYou can use a Globally Unique Identifiers (GUIDs) to provide a unique reference numbers for Artifacts. Forexample, you can use GUIDs to identify the Relativity Dynamic Objects (RDOs) that you create for your customapplications. When you add RDOs to an application, Relativity automatically generates and assigns GUIDs andArtifactIDs to them.

5.11.1 Using GUIDs as best practiceAs a best practice, you should use GUIDs in your application development. They offer the followingadvantages:

n Consistency - They provide consistent references across Relativity workspaces and environments. Theyavoid the confusion that may occur when Field names or ArtifactIDs may change across workspaces.

n Enhanced portability - Since you can install custom applications in multiple workspaces, GUIDs ensurethat the RDOs retain the same unique identifier across workspaces, while ArtifactIDs vary by work-space.

n Easier application management - Field names can bemodified after an application is installed in a work-space. By referencing GUIDs, you have the ability to manipulate these fields even though their namesmay vary across workspaces.

5.11.2 Using GUIDs in read, update, and delete operationsAfter you install a custom application, you can use GUIDs to perform read, update, and delete operations onChoice, Field, ObjectType and RDOs as follows:

n ArtifactGuid can be substituted for ArtifactID.n ArtifactTypeGuid can be substituted for ArtifactTypeID.

You can also use GUIDs for operations on instances of RDOs:

n Create -ArtifactTypeGuid can be substituted for ArtifactTypeID or ArtifactTypeName.n Read, update, and delete -ArtifactGuid can be substituted for ArtifactID.

For code samples, see RDO on page 177.

5.11.3 Viewing GUIDs for your application componentsWhen you enable Developer mode for Relativity, you can view the GUIDs for the components in yourapplications. You can click the Show Component GUIDs link available on the Relativity Applications tab toview a list of GUIDs. For more information, see Development environment guidelines on the Relativity 8.1Developers site.

5.12 Asynchronous frameworkThe asynchronous framework is used to monitor long-running operations by returning status updates asevents. Not only does the asynchronous framework provide you with ability to monitor these operations, butyou can also use it to cancel them. The asynchronous framework supports the following processes:

n Creating BatchSets using the CreateBatchesforBatchSet() methodn Purging BatchSets using the PurgeBatchesOfBatchSet() method

Page 79: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 79

After the asynchronous version of these operations starts a process and succeeds, it returns a uniqueidentifier for that operation. The property is empty when the operation fails. Each of these operations(CreateBatchesforBatchSet() and PurgeBatchesOfBatchSet() methods) has two versions: one that registers bydefault and one that takes a flag. Depending on the version of the operation, the proxy is registered tomonitor the state of the process, and to raise events as its status changes. You can call theMonitorProcessState() method to explicitly register the proxy to monitor and raise status events for a runningprocess. For code samples, see BatchSet on page 85.The asynchronous framework will raise events for status updates automatically. However, you can alsoretrieve the process status explicitly by calling the GetProcessState() method on the proxy. This methodreturns a ProcessInformation object that contains data about the internal state of the process.You can cancel an asynchronous process or allow it to run until it completes or fails. To perform this action,call the FlagForCancellation() method, which flags the process for cancellation when the current batchcompletes.

5.13 TerminologyThe following table lists terms that are frequently used to refer to features and functionality available in theServices API and the Relativity web UI.

Term DescriptionAPIOptions An object containing a login token representing a session as well as the cur-

rent WorkspaceID. Used as a parameter for most methods on the proxy.ArtifactID A 32-bit integer that uniquely identifies items in a workspace.ArtifactManagerProxy (Deprecated - See RSAPIClient class overview on page 61.)

The client-side proxy that lives in the kCura.Realtivity.client.dll. Used to com-municate with the Services API by calling methods on it.

ArtifactRequest A request for an operation to be performed on an Artifact in a workspace. Itcan hold information about documents or Dynamic Objects. Used in CRUDoperations.

Artifact Objects representing a content item in Relativity, such as a document. It hasa unique identifier called an ArtifactID.

ArtifactType An enumeration that assigns a value to various Artifacts in Relativity.ArtifactTypeID An integer used to identify the type of an Artifact in a workspace. For

example, Documents have an ArtifactTypeID of 10.Batch A collection of documents assigned to a single user for review.BatchSet A collection ofmultiple batches originating from the same data source.Choice A predetermined value assigned to a single or multiple-choice field.Client An organization associated with users, matters, and workspaces.CRUD Represents the following database operations: create, read, update, and

delete.

Page 80: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 80

Term DescriptionDescriptorArtifactTypeID The name of the property on the ObjectType DTO, which represents the

effective ArtifactTypeID. If an ArtifactTypeID is required in the code, that IDcan simultaneously be thought of as the DescriptorArtifactTypeID of someObjectType.

Document An object in Relativity with properties such as native files, extracted text,images, and other metadata.

Error Provides information about an error that occurred in Relativity.Field An object used to storemetadata about another object. Similar to columns

in a database.Folder A parent container for documents displayed in the Folder browser on Docu-

ments tab.Group A collection of one or more users, often assigned a specific set of permissions.Layout Aweb-based coding form that allows a user to edit the data stored in the

fields of an object.MarkupSet A set of annotations and redactions used during a review.ObjectRules Provides a list of rules that control the specific behavior of a Dynamic Object.ObjectType ADynamic Object type added to a workspace. Synonymous with ArtifactType

(as in ArtifactTypeID).ParentArtifactID A unique identifier for a parent of an Artifact.Query A query or search of a Workspace. It is passed to the Query() method.QueryResult Data returned by the Query() or SubQuery() methods.RelativityApplication A collection of object types, fields, choices, views, layouts, tabs, event hand-

lers, object rules, Relativity scripts, and custom pages designed to providecustom functionality when deployed in a workspace.

Relativity Dynamic Object(RDO)

An object created by a Relativity administrator. Each type of Dynamic Objecthas a unique ArtifactTypeID in the workspace where it was created.

RelativityScript A script defined through the Scripts tab in Relativity that allows the executionof custom SQL scripts.

RSAPIClient Refers to the RelativityServices API Client (RSAPIClient) for .NET. The client-side proxy that lives in the kCura.Realtivity.client.dll. Used to communicatewith the Services API by calling methods on it. See RSAPIClient class overviewon page 61.

SavedSearch A search that is defined and stored in Relativity for repeated use.System Types Refers to the properties on the base Artifact, which contains Artifact ID, Sys-

tem Created By, System Created On, System Last Modified By, and SystemLast Modified On.

Tab A tab in the Relativity web UI.User Individuals with access to Relativity. A user must be a member of group to

access a workspace.View Defines a set of criteria to control the contents, fields, and sort order of items

displayed on list pages in Relativity.

Page 81: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 81

Term DescriptionWorkspace A secure data repository for documents. It also contains views, layouts,

fields, choices, and other objects. Dynamic Objects and applications may beadded to workspaces.

6 DTO reference and code samplesDTOs are typed wrappers for Artifacts supported by the Services API. For more information, see Data TransferObjects (DTOs) on page 67.You can use the following table to locate code samples for DTOs. The table lists the Relativity version when thesupport for a specific operation was first introduced. Click the version number under an operation to display acode sample for it.

DTO Supported Operations(listed by earliest supported version)

Create Read Update Delete Query OtherBatch on the nextpage

7.5 7.5 7.5

BatchSet on page85

7.5 7.5 7.5 7.5 7.5 Cancel - 7.5Purge - 7.5

Choice on page 95 7.5 7.5Client on page 97 7.5 7.5 7.5 7.5 7.5Document onpage 103

7.5 7.5 7.5 7.5 7.5 Download native file - 7.5

Error on page 112 7.5Field on page 113 7.5 7.5 7.5 7.5Folder on page153

7.5 7.5 7.5 7.5

Group on page158

7.5 7.5 7.5 7.5 7.5

Layout on page163

7.5 7.5

MarkupSet onpage 166

7.5 7.5 7.5 7.5 7.5

ObjectType onpage 172

7.5 7.5 7.5 7.5 7.5

RDO on page 177 7.5 7.5 7.5 7.5 7.5Relativ-ityApplication onpage 186

7.5 7.5

RelativityScript onpage 189

7.5 7.5 Execute - 7.5Retrieve input -7.5

Tab on page 196 7.5 7.5

Page 82: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 82

DTO Supported Operations(listed by earliest supported version)

Create Read Update Delete Query OtherUser on page 198 7.5 7.5 7.5 7.5 7.5View on page 207 7.5 7.5Workspace onpage 210

7.5 7.5

6.1 BatchIn Relativity, an administrator creates a batch by splitting a static set of documents into multiple sets basedon the criteria for a review. For more information, see Batches in the Relativity 8.1 Documentation site.The Services API supports read, update, delete, and query operations on the Batch DTO.

6.1.1 Updating and reading a BatchWhen you update a Batch object, you can modify only the AssignedTo and BatchStatus properties. This codesamples illustrates how to modify these properties using the Update() method on the Batch repository.

public static bool Batch_Update_Using_Repository(IRSAPIClient proxy){

// STEP 1: Create an object specifying the Artifact ID// and the fields that you want returned.DTOs.Batch batch1 = new DTOs.Batch(1036607);batch1.Fields = FieldValue.AllFields;

// STEP 2: Read current values.ResultSet<DTOs.Batch> results = new ResultSet<DTOs.Batch>();try{

results = proxy.Repositories.Batch.Read(batch1);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}if (!results.Success){

Console.WriteLine("Error: " + results.Message);return false;

}

// STEP 3: Get the Artifact from the read results.DTOs.Batch batch2 = results.Results.FirstOrDefault().Artifact;

Page 83: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 83

Console.WriteLine("Batch Artifact ID: " + batch2.ArtifactID.ToString());Console.WriteLine("Batch Text Identifier: " + batch2.TextIdentifier);Console.WriteLine("Batch Status ID: " + batch2.BatchStatus.Name + ", ID: "

+ batch2.BatchStatus.ArtifactID.ToString());Console.WriteLine("Batch Assigned To: " + batch2.AssignedTo.FullName + ",

ID: " + batch2.AssignedTo.ArtifactID.ToString());

// STEP 4: Modify properties of the Batch.// For a Batch, you can only modify the AssignedTo and BatchStatusproperties.batch2.BatchStatus = new DTOs.Choice(1035249);batch2.AssignedTo = new DTOs.User(1016508);

// STEP 5: Call the Update() method on the Batch repository.WriteResultSet<DTOs.Batch> writeResultSet = null;try{

writeResultSet = proxy.Repositories.Batch.Update(new List<DTOs.Batch> { batch2 });

}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}if (writeResultSet.Success){

Console.WriteLine("Batch updated successfully");batch2 = results.Results.FirstOrDefault().Artifact;Console.WriteLine("Batch Artifact ID: " + batch2.ArtifactID.ToString());Console.WriteLine("Batch Text Identifier: " + batch2.TextIdentifier);Console.WriteLine("Batch Status ID: " +batch2.BatchStatus.ArtifactID.ToString());Console.WriteLine("Batch Assigned To ID: " +batch2.AssignedTo.ArtifactID.ToString());

}else{

string message = writeResultSet.Message;if (message == null && writeResultSet.Results.Count > 0 &&!writeResultSet.Results[0].Success)

message = writeResultSet.Results[0].Message;Console.WriteLine("Error: " + message);return false;

}

Page 84: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 84

// STEP 6: Read back the updated Artifact.try{

results = proxy.Repositories.Batch.Read(batch2);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

if (!results.Success){

Console.WriteLine("Error: " + results.Message);return false;

}

// STEP 7: Get the updated property values from the read results.DTOs.Batch batch3 = results.Results.FirstOrDefault().Artifact;Console.WriteLine("Batch Artifact ID: " + batch3.ArtifactID.ToString());Console.WriteLine("Batch Text Identifier: " + batch3.TextIdentifier);Console.WriteLine("Batch Status: " + batch3.BatchStatus.Name + ", ID: " +

batch3.BatchStatus.ArtifactID.ToString());Console.WriteLine("Batch Assigned To: " + batch3.AssignedTo.FullName + ",

ID: " + batch3.AssignedTo.ArtifactID.ToString());

return true;}

6.1.2 Querying for a BatchTo query for a Batch, you can use the fields listed in the following table. For more information, see Queryingon page 227.

Fields for Batch queriesArtifactID Batch SizeAssigned To Batch StatusBatch Batch UnitBatch Set Reviewed

This code sample illustrates how to set query conditions, call the Query() method on the Batch repository,and iterate through the result set.

public static bool Batch_Query_By_BatchSet_Using_Repository(IRSAPIClient proxy){

Page 85: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 85

// STEP 1: Create criteria that identifies a BatchSet object.WholeNumberCondition criteria = new WholeNumberCondition(BatchFieldNames.BatchSet, NumericConditionEnum.EqualTo, 1036606);

// STEP 2: Create a query that uses your criteria.DTOs.Query<DTOs.Batch> query = new DTOs.Query<DTOs.Batch>();query.Condition = criteria;query.Fields = FieldValue.AllFields;

// STEP 3: Call the Query() method on the Batch repository.QueryResultSet<DTOs.Batch> result = null;try{

result = proxy.Repositories.Batch.Query(query);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}Console.WriteLine(string.Format("Number of batches returned: {0}",result.Results.Count));

// STEP 3: Iterate through returned the results.foreach (DTOs.Result<DTOs.Batch> batchResult in result.Results){

DTOs.Batch batch = batchResult.Artifact;Console.WriteLine("Batch Name: " + batch.Name);Console.WriteLine("Batch Artifact ID: " + batch.ArtifactID);

}return true;

}

6.2 BatchSetIn Relativity, a batch set represents a group of batches, which are sets of documents. For more information,see Batches in the Relativity 8.1 Documentation site.The Services API supports all CRUD and query operations on the BatchSet DTO.

6.2.1 Creating, updating, and querying BatchSet objectsAfter you create a BatchSet DTO, you can update its properties by calling the Update() method on theBatchSet repository. This code sample illustrates how to create a BatchSet, read its fields from the database,update the fields, and then query for the BatchSet.

Page 86: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 86

public static bool Create_then_Update_A_BatchSet_Using_Repositories(IRSAPIClient proxy){

// STEP 1: Create a BatchSet DTO and set its properties.kCura.Relativity.Client.DTOs.BatchSet newBatchSet = newkCura.Relativity.Client.DTOs.BatchSet();

newBatchSet.Name = "My Batch Set";newBatchSet.BatchPrefix = "Batch";newBatchSet.MaximumBatchSize = 5;newBatchSet.AutoBatch = true;newBatchSet.MinimumBatchSize = 1;newBatchSet.AutoCreateRateMinutes = 30;newBatchSet.BatchDataSource = new kCura.Relativity.Client.DTOs.Artifact(1036604);

// STEP 2: Call the Services API to create the BatchSet.WriteResultSet<kCura.Relativity.Client.DTOs.BatchSet> createResults = null;try{

createResults = proxy.Repositories.BatchSet.Create(newBatchSet);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred creating the batchset: {0}", ex.Message));return false;

}

if (!createResults.Success){

Console.WriteLine(string.Format("An error occurred creating the batchset: {0}", createResults.Message));return false;

}

Int32 newID = createResults.Results[0].Artifact.ArtifactID;Console.WriteLine("ID of the new Batch Set: " + newID.ToString());

// STEP 3: Read the batch to get all the fields from the database.ResultSet<kCura.Relativity.Client.DTOs.BatchSet> readResults = null;kCura.Relativity.Client.DTOs.BatchSet batchSetRead = new BatchSet(newID);batchSetRead.Fields = FieldValue.AllFields;try{

readResults = proxy.Repositories.BatchSet.Read(batchSetRead);

Page 87: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 87

}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred reading the batch set:{0}", ex.Message));return false;

}if (!readResults.Success){

Console.WriteLine(string.Format("An error occurred reading the batch set:{0}", readResults.Message));return false;

}

kCura.Relativity.Client.DTOs.BatchSet readBatchSet = readResults.Results[0].Artifact;Console.WriteLine("Initial value of Name: " + readBatchSet.Name);Console.WriteLine("Initial value of AutoCreateRate: " +readBatchSet.AutoCreateRateMinutes.ToString());

// STEP 4: Modify properties of the BatchSet. The Name and TextIdentifierboth have the// same value which is the Batch Set Name. Since they have the same value,// you can update the BatchSet using the TextIdentifier.kCura.Relativity.Client.DTOs.BatchSet batchSet = readResults.Results[0].Artifact;batchSet.TextIdentifier = "Better Batchset";batchSet.AutoCreateRateMinutes = 45;

// MaximumBatchSize must be set for the update.batchSet.MaximumBatchSize = readBatchSet.MaximumBatchSize;WriteResultSet<kCura.Relativity.Client.DTOs.BatchSet> updateResults = null;

// STEP 5: Call the Services API to update the BatchSet just created.try{

updateResults = proxy.Repositories.BatchSet.Update(batchSet);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred updating the batchset: {0}", ex.Message));return false;

}

Page 88: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 88

if (!updateResults.Success){

Console.WriteLine(string.Format("An error occurred updating the batchset: {0}", updateResults.Message));return false;

}

// STEP 6: Verify that update worked by querying the BatchSet.Query<kCura.Relativity.Client.DTOs.BatchSet> batchSetQuery =

new Query<kCura.Relativity.Client.DTOs.BatchSet>();batchSetQuery.Fields = FieldValue.AllFields;batchSetQuery.Condition =

new WholeNumberCondition(ArtifactQueryFieldNames.ArtifactID,NumericConditionEnum.EqualTo, newID);

QueryResultSet<kCura.Relativity.Client.DTOs.BatchSet> queryResultSet = null;

try{

queryResultSet = proxy.Repositories.BatchSet.Query(batchSetQuery);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred reading the batch setafter updating: {0}", ex.Message));return false;

}kCura.Relativity.Client.DTOs.BatchSet readBatchSet2 = queryResultSet.Results[0].Artifact;Console.WriteLine("Updated value of Name: " + readBatchSet2.Name);Console.WriteLine("Updated value of AutoCreateRate: " +readBatchSet2.AutoCreateRateMinutes);

return true;}

6.2.2 Creating and deleting a BatchSetThis code sample illustrates how to call the Create() and Delete() methods on a BatchSet repository.

public static bool Create_then_Delete_A_BatchSet_Using_Repositories(IRSAPIClient proxy){

// STEP 1: Create a BatchSet DTO and set its properties.DTOs.BatchSet newBatchSet = new DTOs.BatchSet();newBatchSet.Name = "My Batch Set";

Page 89: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 89

newBatchSet.BatchPrefix = "Batch";newBatchSet.MaximumBatchSize = 5;newBatchSet.BatchDataSource = new DTOs.Artifact(1036604);

// STEP 2: Declare a variable to hold the returned values.WriteResultSet<DTOs.BatchSet> results =

new WriteResultSet<DTOs.BatchSet>();Int32 newID = new Int32();

// STEP 3: Call the Services API to create the BatchSet.try{

results = proxy.Repositories.BatchSet.Create(newBatchSet);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

if (results.Success){

newID = results.Results[0].Artifact.ArtifactID;

Console.WriteLine(string.Format("ID of the new Batch Set: {0}", newID));

// STEP 4: Instantiate BatchSet with the ID of the BatchSet that you wantto delete.DTOs.BatchSet batchSetToDelete = new DTOs.BatchSet(newID);

// STEP 5: Call the Services API to delete the BatchSet just created.try{

results = proxy.Repositories.BatchSet.Delete(batchSetToDelete);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}",ex.Message));return false;

}Console.WriteLine(string.Format("Overall Status of Deleting a Batch Set:{0}", results.Success));

}return true;

}

Page 90: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 90

6.2.3 Creating Batches for a BatchSetYou can use the CreateBatchesAsync() method to add Batch objects to a BatchSet as illustrated in this codesample. For more information about this method, see Asynchronous framework on page 78.

public static Boolean Create_Batches_For_BatchSet(IRSAPIClient proxy){

// STEP 1: Create a new BatchSet object.DTOs.BatchSet batchSet = new DTOs.BatchSet();batchSet.Name = "My Batch Set";batchSet.MaximumBatchSize = 5;batchSet.BatchPrefix = "APISAMPLES-";batchSet.BatchDataSource = new DTOs.Artifact(1036604);

// STEP 2: Call the Services API to create the BatchSet.WriteResultSet<DTOs.BatchSet> createResults;

try{

createResults = proxy.Repositories.BatchSet.Create(batchSet);}catch (Exception ex){

Console.WriteLine(String.Format("An error occurred: {0}", ex.Message));return false;

}

if (!createResults.Success){Console.WriteLine(String.Format("An error occurred: {0}",createResults.Message));return false;}// STEP 3: Add Handlers for events that may occur while creating Batches.proxy.ProcessProgress += HandleProcessProgressEvent;proxy.ProcessComplete += HandleProcessCompleteEvent;proxy.ProcessFailure += HandleProcessFailureEvent;proxy.ProcessCancelled += HandleProcessCancelEvent;

// STEP 4: Create Batches for the Batch Set. While the server is executingthis call,// your event handlers are called with progress and completion events.Int32 batchSetArtifactID = createResults.Results[0].Artifact.ArtifactID;ProcessOperationResult processResult;

try

Page 91: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 91

{processResult = proxy.Repositories.BatchSet.CreateBatchesAsync(newDTOs.BatchSet(batchSetArtifactID));

}catch (Exception ex){

Console.WriteLine(String.Format("An error occurred: {0}", ex.Message));return false;

}

if (!processResult.Success){

Console.WriteLine(String.Format("An error occurred: {0}",processResult.Message));return false;

}return true;

}

6.2.4 Querying for a Batch SetTo query for a BatchSet, you can use the fields listed in the following table. For more information, seeQuerying on page 227 and Creating, updating, and querying BatchSet objects on page 85.

Fields for BatchSet queriesArtifact ID Last Modified ByArtifact ID Last Modified OnAuto Create Rate (minutes) Last Successful RunBatch Data Source Maximum Batch SizeBatch Prefix Minimum Batch SizeCreated By NameCreated On ReviewedDocuments to be Batched SecurityFamily Field StatusLast Error Reported

6.2.5 Canceling the creation of a BatchSetWhen you cancel the creation of a BatchSet, Relativity stops creating new Batches but it doesn't delete thosethat were already created. This code sample illustrates how to use the FlagProcessForCancellationAsync() tocancel Batch creation. For more information about this method, see Asynchronous framework on page 78.

public static Boolean Cancel_Batch_Creation(IRSAPIClient proxy){

Page 92: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 92

// STEP 1: Create a new BatchSet object.DTOs.BatchSet batchSet = new DTOs.BatchSet();batchSet.Name = "My Batch Set";batchSet.MaximumBatchSize = 5;batchSet.BatchPrefix = "APISAMPLES-";batchSet.BatchDataSource = new DTOs.Artifact(1036604);

// STEP 2: Call the Services API to create the BatchSet.WriteResultSet<DTOs.BatchSet> createResults;try{

createResults = proxy.Repositories.BatchSet.Create(batchSet);}catch (Exception ex){

Console.WriteLine(String.Format("An error occurred: {0}", ex.Message));return false;

}

if (!createResults.Success){

Console.WriteLine(String.Format("An error occurred: {0}",createResults.Message));return false;

}

// STEP 3: Add Handlers for events that may occur while creating batches.proxy.ProcessProgress += HandleProcessProgressEvent;proxy.ProcessComplete += HandleProcessCompleteEvent;proxy.ProcessFailure += HandleProcessFailureEvent;proxy.ProcessCancelled += HandleProcessCancelEvent;

// STEP 4: Create batches for the Batch Set. While the server is executingthis call,// your event handlers will be called with progress and completion events.Int32 batchSetArtifactID = createResults.Results[0].Artifact.ArtifactID;ProcessOperationResult processResult;

try{

processResult = proxy.Repositories.BatchSet.CreateBatchesAsync(newDTOs.BatchSet(batchSetArtifactID));

}catch (Exception ex){

Page 93: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 93

Console.WriteLine(String.Format("An error occurred: {0}", ex.Message));return false;

}

if (!processResult.Success){

Console.WriteLine(String.Format("An error occurred: {0}",processResult.Message));return false;

}

// STEP 5: Cancel batch creation. After executing this call, the Relativityserver// stops creating Batches, but it doesn't delete the Batches that werealready created.System.Guid processID = processResult.ProcessID;try{

processResult = proxy.FlagProcessForCancellationAsync(proxy.APIOptions,processID);

}catch (Exception ex){

Console.WriteLine(String.Format("An error occurred cancelling batch setcreation: {0}", ex.Message));return false;

}

if (!processResult.Success){

Console.WriteLine(String.Format("An error occurred: {0}",processResult.Message));return false;

}

return true;}

6.2.6 Purging Batches for a BatchSetYou can use the PurgeBatchesAsync() method to delete the Batch objects associated with a BatchSet object asillustrated in this code sample. For more information about this method, see Asynchronous framework onpage 78.

public static Boolean Purge_Batches_For_BatchSet(IRSAPIClient proxy)

Page 94: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 94

{// STEP 1: Add Handlers for events that may occur while creating batches.proxy.ProcessProgress += HandleProcessProgressEvent;proxy.ProcessComplete += HandleProcessCompleteEvent;proxy.ProcessFailure += HandleProcessFailureEvent;proxy.ProcessCancelled += HandleProcessCancelEvent;

// STEP 2: Call the server method to delete the existing batches for aparticular batch set.Int32 batchSetArtifactID = 1036606;ProcessOperationResult processResult;try{

processResult = proxy.Repositories.BatchSet.PurgeBatchesAsync(newDTOs.BatchSet(batchSetArtifactID));

}catch (Exception ex){

Console.WriteLine(String.Format("An error occurred: {0}", ex.Message));return false;

}

if (!processResult.Success){

Console.WriteLine(String.Format("An error occurred: {0}",processResult.Message));return false;

}

return true;}

6.2.7 Event handlers used in code samplesThese event handlers are referenced in the previous code samples:

n Used for progress notification while executing an asynchronous method.

public static void HandleProcessProgressEvent(Object sender,

ProcessProgressEventArgs eventArgs)

{

ProcessInformation processInformation = eventArgs.ProcessInformation;

Console.WriteLine("For the Batch Set operation, the number of operations

completed is " + processInformation.OperationsCompleted.ToString());

}

Page 95: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 95

n Used for notification when an asynchronous method successfully finishes.

public static void HandleProcessCompleteEvent(Object sender,

ProcessCompleteEventArgs eventArgs)

{

ProcessInformation processInformation = eventArgs.ProcessInformation;

Console.WriteLine("The Batch Set operation completed");

}

n Used for notification when an asynchronous method finishes with an error.

public static void HandleProcessFailureEvent(Object sender, ProcessFailureEventArgs

eventArgs)

{

ProcessInformation processInformation = eventArgs.ProcessInformation;

if (processInformation.Success == false)

Console.WriteLine("There was a problem retrieving the

process information, the message is " + processInformation.Message);

else

Console.WriteLine("The Batch Set operation failed, the process state is "

+ processInformation.State.ToString());

}

n Used for notification when an asynchronous method stops due to a cancellation request.

public static void HandleProcessCancelEvent(Object sender, ProcessCancelEventArgs

eventArgs)

{

Console.WriteLine("The Batch Set operation was canceled");

}

6.3 ChoiceIn Relativity, choices are the predetermined values that you apply to single and multi-choice list fields. Formore information, see Choices in the Relativity 8.1 Documentation site.The Services API supports read and query operations on a Choice DTO.

6.3.1 Reading a ChoiceTo read Field values on a Choice, you can use the Read() method on the Choice repository as illustrated in thiscode sample.

public static bool Read_Choices(IRSAPIClient proxy){

Page 96: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 96

// STEP 1: Create DTO with criteria for the read.DTOs.Choice choiceToRead = new DTOs.Choice(1016577);choiceToRead.Fields = FieldValue.AllFields;

// STEP 2: Create ResultSet which contain Results from the read operation.ResultSet<DTOs.Choice> results = new ResultSet<DTOs.Choice>();

// STEP 3: Perform the read operation.try{

results = proxy.Repositories.Choice.Read(choiceToRead);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

// Check for success.if (!results.Success){

Console.WriteLine("The Read operation was not successful.{0}{1}",Environment.NewLine, results.Message);return false;

}Result<DTOs.Choice> choiceDtoArtifact = results.Results[0];

// Output the results.SampleHelpers.APIHelpers.Print_All_Properties(choiceDtoArtifact.Artifact);

return true;}

6.3.2 Querying on a ChoiceThis code sample illustrates how to query for Choice DTOs created at the administrator level in Relativity.

public static bool Query_for_Admin_Choices(IRSAPIClient proxy){

// STEP 1: Setup your query criteria.WholeNumberCondition criteria =

new WholeNumberCondition("Choice Type ID", NumericConditionEnum.EqualTo,1000036);

Query<DTOs.Choice> query = new DTOs.Query<DTOs.Choice> { Condition =criteria };

Page 97: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 97

query.Fields = FieldValue.AllFields;

// STEP 2: Create QueryResultSet to collect query results.QueryResultSet<DTOs.Choice> result = new QueryResultSet<DTOs.Choice>();

// STEP 3: Perform the query.try{

result = proxy.Repositories.Choice.Query(query, 0);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

// Check for success.if (!result.Success){

Console.WriteLine("The Query operation was not successful.{0}{1}",Environment.NewLine, result.Message);return false;

}Console.WriteLine("Number of Choices returned: {0}", result.Results.Count);

// Output the results.foreach (DTOs.Result<DTOs.Choice> choiceResult in result.Results){

Console.WriteLine("{0}Name:{1}", Environment.NewLine,choiceResult.Artifact.Name);Console.WriteLine("ArtifactID:{0}", choiceResult.Artifact.ArtifactID);

}return true;

}

6.4 ClientIn Relativity, clients are companies or other organizations associated with users and matters. For moreinformation, see Clients in the the Relativity 8.1 Documentation site.The Services API supports all CRUD and query operations on a Client DTO.

6.4.1 Creating a ClientTo create a Client, you must set the properties on the DTO and call the Create() method on the Clientrepository as illustrate in this code sample.

Page 98: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 98

public static bool Create_Client(IRSAPIClient proxy){

//STEP 1: Create a DTO by setting the necessary properties.DTOs.Client client = new DTOs.Client();client.Name = "Sample Client";client.ClientNumber = "Four more than Three";client.Status = new DTOs.Choice(669);

//STEP 2: Create a WriteResultSet. It provides details after the createoperation.WriteResultSet<DTOs.Client> resultSet = new WriteResultSet<DTOs.Client>();

//STEP 3: Perform the create operation.try{

resultSet = proxy.Repositories.Client.Create(client);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

//Check for success.if (!resultSet.Success){

Console.WriteLine("The Create operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

}

//Output the results.Console.WriteLine("The Create succeeded.");DTOs.Client createdClient = resultSet.Results[0].Artifact;

Console.WriteLine("{0}The Artifact of the New Client is: {1}",Environment.NewLine,

createdClient.ArtifactID);return true;

}

6.4.2 Reading a ClientTo read Field values on a Client, you can use the Read() method on the Client repository as illustrated in thiscode sample.

Page 99: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 99

public static bool Read_Client(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = -1;

//STEP 1: Create the Client DTO to read.kCura.Relativity.Client.DTOs.Client client = newkCura.Relativity.Client.DTOs.Client(1015461);client.Fields.Add(new FieldValue(ClientFieldNames.Name));

//STEP 2: Create ResultSet to collect information about the Read.ResultSet<kCura.Relativity.Client.DTOs.Client> resultSet =

new ResultSet<kCura.Relativity.Client.DTOs.Client>();

//STEP 3: Perform the Read.try{

resultSet = proxy.Repositories.Client.Read(client);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

//Check for success.if (!resultSet.Success){

Console.WriteLine("The Query operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

}

// Output the results.Console.WriteLine("Number of clients returned: {0}",resultSet.Results.Count);

foreach (Result<kCura.Relativity.Client.DTOs.Client> clientResult inresultSet.Results){

Console.WriteLine("{0}Name:{1}", Environment.NewLine,clientResult.Artifact.Name);Console.WriteLine("ArtifactID:{0}", clientResult.Artifact.ArtifactID);

}return true;

}

Page 100: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 100

6.4.3 Updating a ClientTo modify a Field on a Client, you can use the Update() method on the Client repository as illustrated in thiscode sample.

public static bool Update_Client(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = -1;

//STEP 1: Create the Client Artifact that you want to read.kCura.Relativity.Client.DTOs.Client client = newkCura.Relativity.Client.DTOs.Client(1015461);client.Fields.Add(new FieldValue(ClientFieldNames.Name));

//STEP 2: Create ResultSet to collect information about the Read.ResultSet<kCura.Relativity.Client.DTOs.Client> resultSet =

new ResultSet<kCura.Relativity.Client.DTOs.Client>();

//STEP 3: Perform the Read.try{

resultSet = proxy.Repositories.Client.Read(client);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

//Check for success.if (!resultSet.Success){

Console.WriteLine("The Query operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

}

//STEP 4: Get the Client Artifact and set the fields to be updated.kCura.Relativity.Client.DTOs.Client clientResult =resultSet.Results.FirstOrDefault().Artifact;clientResult.Name = "Updated Sample Client";

WriteResultSet<kCura.Relativity.Client.DTOs.Client> writeResultSet;

//STEP 5: Update the Client Artifact.try

Page 101: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 101

{writeResultSet = proxy.Repositories.Client.Update(clientResult);

}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

//Check for success.if (!writeResultSet.Success){

Console.WriteLine("The Update operation failed.{0}{1}",Environment.NewLine, writeResultSet.Message);return false;

}return true;

}

6.4.4 Deleting a ClientYou can delete a Client object by calling the Delete() method on the Client repository as illustrated in this codesample.

public static bool Delete_Client(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = -1;

//STEP 1: Create the Client artifact to delete.kCura.Relativity.Client.DTOs.Client client = newkCura.Relativity.Client.DTOs.Client(1015461);

//STEP 2: Create ResultSet to collect information about the Delete.ResultSet<kCura.Relativity.Client.DTOs.Client> resultSet =

new ResultSet<kCura.Relativity.Client.DTOs.Client>();

//STEP 3: Perform the Delete.try{

resultSet = proxy.Repositories.Client.Delete(client);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

Page 102: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 102

}

//Check for success.if (!resultSet.Success){

Console.WriteLine("The Query operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

}return true;

}

6.4.5 Querying for a ClientThis code sample illustrates how to set query conditions, call the Query() method on the Client repository,and iterate through the result set. For more information, see Querying on page 227.

public static bool Query_Client(IRSAPIClient proxy){

//STEP 1: Create Query and ObjectsCondition(s), it will provide detailsafter the Query Operation.WholeNumberCondition clientCondition =

new WholeNumberCondition(ArtifactQueryFieldNames.ArtifactID,NumericConditionEnum.EqualTo, 1016204);

Query<DTOs.Client> query = new Query<DTOs.Client> { Condition =clientCondition };query.Fields = FieldValue.AllFields;

//STEP 2: Create QueryResultSet to collect information about the DTO afterQuery.QueryResultSet<DTOs.Client> resultSet = new QueryResultSet<DTOs.Client>();

//STEP 3: Perform the Query.try{

resultSet = proxy.Repositories.Client.Query(query, 0);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

//Check for success.

Page 103: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 103

if (!resultSet.Success){

Console.WriteLine("The Query operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

}

// Output the results.Console.WriteLine("Number of clients returned: {0}",resultSet.Results.Count);

foreach (Result<DTOs.Client> clientResult in resultSet.Results){

Console.WriteLine("{0}Name:{1}", Environment.NewLine,clientResult.Artifact.Name);Console.WriteLine("ArtifactID:{0}", clientResult.Artifact.ArtifactID);

}return true;

}

6.5 DocumentIn Relativity, documents consist of the content for a review or other tasks, and they are stored in workspaces.For more information, see the Relativity 8.1 Documentation site.The Services API supports all CRUD and query operations on a Document DTO.

6.5.1 Fields on a Document DTOThe Document DTO supports fields available on documents through the Relativity web UI as well as thefollowing specialized fields:

n FolderName - represents the name of the folder in the Relativity, where the Document is located.n HasImages - indicates whether images of the Document exist.n HasNative - indicates whether a native file exists for the Document.n RelativityImageCount - provides the number of images associated with a Document.

6.5.2 Creating a DocumentWhen you call the Create() method on a Document DTO, you can set only these properties:

n RelativityNativeFileLocation – specifies the local path for the document native uploaded to Relativity,such as c:\myFolder\myDocument.docx. It is a required property that is used only by the Create()method.

n TextIdentifier – specifies the name of the document. It is a required property for the Create() method.See TextIdentifer property on DTOs on page 114.

n ParentArtifact – indicates the folder where the document is added. It is an optional property.

Page 104: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 104

Only these fields are supported on the Create() method for Document. The values of any other fields won't beupdated if you attempt to set them during a create operation. After the Create() method completes, you canuse the Update() method to populate other fields on the Document object.

Note: You can't update the native file through the Services API unless you delete and then recreate thedocument. However, you can use the Import API to update the native file. See Import API on the Relativity8.1 Developers site.

6.5.2.1 Sample Code

public static int Create_Document(IRSAPIClient proxy){

//STEP 1: Create the Document object, specifying an optional Parent Folder.The name of//the identifier field will change depending on the workspace, so use theTextIdentifier// property.DTOs.Document document = new DTOs.Document();document.RelativityNativeFileLocation ="C:\\SourceCode\\Mainline\\EDDS\\kCura.Relativity.Client.APISamples

\\SampleFiles\\LoremIpsum.docx";document.TextIdentifier = "My New Document 001";

//STEP 2: The Parent Folder is specified by setting Parent Artifact ID.Int32 folderId = 1003697;

//This step is optional.document.ParentArtifact = new DTOs.Artifact(folderId);WriteResultSet<DTOs.Document> createResults = newWriteResultSet<DTOs.Document>();

//STEP 3: Attempt to create the document.try{

createResults = proxy.Repositories.Document.Create(document);}catch (Exception ex){

// If an error occurs while trying to create the document, write an errormessage.Console.WriteLine("Error: " + ex.Message);return -1;

}//Check for success.if (createResults.Success){

Page 105: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 105

Console.WriteLine("Created a new document with ArtifactId ={0}", createResults.Results.First().Artifact.ArtifactID);

return createResults.Results.First().Artifact.ArtifactID;}else{

Console.WriteLine("Error creating the document: {0}",createResults.Message);return -1;

}}

6.5.3 Reading a DocumentThe Read() method doesn't return a native file for a document. You must use the Download() method if youwant the original native file. However, you can retrieve extracted text with the Read() method.

public static bool Read_Document(IRSAPIClient proxy){

// STEP 1: Create an object specifying the Artifact ID// and which fields to return.DTOs.Document document = new DTOs.Document(1035472);document.Fields = FieldValue.AllFields;

// STEP 2: Call the read method on the Document Repository.ResultSet<DTOs.Document> results = new ResultSet<DTOs.Document>();try{

results = proxy.Repositories.Document.Read(document);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

if (!results.Success){

Console.WriteLine("Error: " + results.Message);return false;

}

// STEP 3: Get the Document artifact from the read results.DTOs.Document documentArtifact = results.Results.FirstOrDefault().Artifact;

Page 106: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 106

Console.WriteLine("Document Control Number: " +documentArtifact.TextIdentifier);Console.WriteLine("Document Last Modified: " +documentArtifact.SystemLastModifiedOn);Console.WriteLine("Document Artifact ID: " + documentArtifact.ArtifactID);

return true;}

6.5.4 Updating a DocumentYou can modify properties of the Document by calling the Update() method as illustrated in this code sample.

public static bool Update_Document(IRSAPIClient proxy){

// STEP 1: Create an object specifying the Artifact ID// and which fields to return.DTOs.Document document = new DTOs.Document(1035472);document.Fields = FieldValue.AllFields;

// STEP 2: Read current values.ResultSet<DTOs.Document> results = new ResultSet<DTOs.Document>();try{

results = proxy.Repositories.Document.Read(document);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

if (!results.Success){

Console.WriteLine("Error: " + results.Message);return false;

}

// STEP 3: Get the Artifact from the read results.DTOs.Document docArtifact = results.Results[0].Artifact;Console.WriteLine("Document Artifact ID: " + docArtifact.ArtifactID);Console.WriteLine("Document Text Identifier: " +docArtifact.TextIdentifier);

Page 107: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 107

DTOs.Artifact singleObject1 = (DTOs.Artifact)(docArtifact["SingleObject"].Value);Console.WriteLine("Document Single Object: " +singleObject1.ArtifactID.ToString());

// STEP 4: Modify properties of the document.// Specify a new value for Text Identifier, a property of the Artifact.docArtifact.TextIdentifier = "John552";

// Specify a new value for Single Object, a custom field in Relativity.// Custom fields must be accessed using the Fields collection.// For a Single Object, we specify the ArtifactID.docArtifact["Single Object"].Value = 1036035;

// STEP 5: Call the Update method on the Document Respository.WriteResultSet<DTOs.Document> writeResultSet = null;try{

writeResultSet =proxy.Repositories.Document.Update(new List<DTOs.Document> { docArtifact });

}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

if (writeResultSet.Success){

Console.WriteLine("Document updated successfully");

docArtifact = results.Results[0].Artifact;Console.WriteLine("Document Artifact ID: " + docArtifact.ArtifactID);Console.WriteLine("Document Text Identifier: " +docArtifact.TextIdentifier);

int singleObjectID = (int)(docArtifact["Single Object"].Value);Console.WriteLine("Document Single Object: " + singleObjectID.ToString());

}else{

string message = writeResultSet.Message;

Page 108: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 108

if (message == null && writeResultSet.Results.Count > 0 &&!writeResultSet.Results[0].Success)

message = writeResultSet.Results[0].Message;Console.WriteLine("Error: " + message);return false;

}

// STEP 6: Read back the updated Artifact.try{

results = proxy.Repositories.Document.Read(document);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

if (!results.Success){

Console.WriteLine("Error: " + results.Message);return false;

}

// STEP 7: Get the updated property values from the read results.docArtifact = results.Results[0].Artifact;Console.WriteLine("Document Artifact ID: " + docArtifact.ArtifactID);Console.WriteLine("Document Text Identifier: " +docArtifact.TextIdentifier);

DTOs.Artifact singleObject2 = (DTOs.Artifact)(docArtifact["SingleObject"].Value);Console.WriteLine("Document Single Object: " +singleObject2.ArtifactID.ToString());

return true;}

6.5.5 Deleting a DocumentThis code sample illustrates how to remove a document from Relativity by calling the Delete() method on theDocument repository.

public static bool Delete_Document(IRSAPIClient proxy){

Page 109: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 109

DTOs.Document doc = new DTOs.Document(1035605);

WriteResultSet<DTOs.Document> writeResultSet = newWriteResultSet<DTOs.Document>();try{

writeResultSet = proxy.Repositories.Document.Delete(doc);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

if (!writeResultSet.Success){

string message = writeResultSet.Message;

if (message == null && writeResultSet.Results.Count > 0 &&!writeResultSet.Results[0].Success)

message = writeResultSet.Results[0].Message;Console.WriteLine("Error: " + message);return false;

}else{

Console.WriteLine("Document updated successfully");}

return true;}

6.5.6 Querying for a DocumentThe Services API doesn't support query conditions for the following fields on the Document DTO:

n Batch_AssignedTon Batch_BatchSetn Batch_Status

Note: The Services API returns query results for the Batch_AssignedTo, Batch_BatchSet, and Batch_Statusfields.

n RelativityNativeFileLocation (Set only during a create operation.)

Page 110: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 110

6.5.6.1 Sample CodeThis code sample illustrates how to set query conditions, call the Query() method on the Documentrepository, and iterate through the result set.

public static bool Query_Document_by_Control_Number(IRSAPIClient proxy){// STEP 1: Setup your query criteria.TextCondition criteria = new TextCondition("Control Number",TextConditionEnum.EqualTo, "AS000005");Query<DTOs.Document> query = new Query<DTOs.Document>{

Condition = criteria,RelationalField = new FieldValue("Group Identifier"),Fields = new List<FieldValue> { new FieldValue("Control Number") }

};

// STEP 2: Call the Query() method in the Document repository.QueryResultSet<DTOs.Document> result = null;try{

result = proxy.Repositories.Document.Query(query, 0);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

Console.WriteLine(string.Format("Number of documents returned: {0}",result.TotalCount));Console.WriteLine(string.Format("Additional Pages of Query ResultsAvailable?: {0}", !string.IsNullOrEmpty(result.QueryToken)));

// STEP 3: Iterate the returned Document result.foreach (DTOs.Result<DTOs.Document> docResult in result.Results){

DTOs.Document doc = docResult.Artifact;Console.WriteLine("Document Control Number: " + doc.TextIdentifier);Console.WriteLine("Document Artifact ID: " + doc.ArtifactID);

}

return true;}

Page 111: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 111

6.5.7 Downloading a native fileYou can use the Download() method on the repository for the Document DTO to download a native file. Youcan download a native file from Relativity as Stream object, or specify an output path on disk.

Note: Use the Download() method on the Document Repository class rather than this method on theFileTransferProxy class. This approach is recommended for downloading native files. See File field on page135.

6.5.7.1 Sample Code

public static Stream Download_Document_Native(IRSAPIClient proxy){

//STEP 1: Define the ArtifactID of the document which has a native file.DTOs.Document doc = new DTOs.Document(1035607);

//STEP 2: Listen to the Failure event to get exceptions.proxy.Failure += FileTransferFailureHandler;

//STEP 3: Call the DownloadNative() method.KeyValuePair<DownloadResponse, Stream> documentNativeResponse;try

{documentNativeResponse = proxy.Repositories.Document.DownloadNative(doc);

}catch (Exception ex){

//If an error occurs while trying to download the document, write anerror message.Console.WriteLine("Error: " + ex.Message);return null;

}//STEP 4: A 'null' Key and Value from the response indicates failure.if (documentNativeResponse.Key != null && documentNativeResponse.Value !=null)

{Console.WriteLine("Download succeeded: {0} bytes",documentNativeResponse.Value.Length);return documentNativeResponse.Value;}

else{return null;}

}

Page 112: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 112

private static void FileTransferFailureHandler(FailureEventArgs eventArgs){

Console.WriteLine("The following error occurred during the download forthe document with ArtifactId {0}:

{1}", eventArgs.TargetField.ObjectArtifactId, eventArgs.Exception);}

6.6 ErrorThe Services API provides an Error DTO, which represents an exception thrown in Relativity. The Services APIsupports only the create operation on an Error DTO. For more information, see Troubleshooting the ServicesAPI on page 236.

6.6.1 Writing to the error logYou can write an entry to the Relativity error log using the Create() method on the RSAPIClient proxy. Thismethod takes an ArtifactRequest parameter with the ArtifactTypeName set to Error or the ArtifactTypeID setto 18. The Fields collection provides the field values to set on the newly created Error object. TheMessage orFull Error field is required.When you call the Create() method, the value set in theWorkspace on the APIOptions object affects theinformation added to the error log :

n IfWorkspace is set to -1, the error log creates an error but not associate it with a specific workspace.n IfWorkspace is set to valid ID for a workspace, the error log automatically creates an error associated

with that workspace.n If you pass a new field named Workspace with a valid ID for a workspace (overriding the field in the

APIOptions object), the error log creates an error associated with the workspace specified by this field.The following sample code illustrates how to write errors to the Relativity error log.

public static bool Create_Error_Message(IRSAPIClient proxy){

// STEP 1: Create an Error DTO.DTOs.Error errorToCreate = new DTOs.Error();

// STEP 2: Create a unexpected condition which throws an exception.try{

throw new Exception("Invalid Data");}catch (Exception ex){

errorToCreate.FullError = ex.StackTrace;errorToCreate.Message = ex.Message;

}

Page 113: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 113

// Set additional fields. The Workspace can be inferred from the APIOptionsinstance.errorToCreate.SendNotification = false;errorToCreate.Server = Environment.MachineName;errorToCreate.Source = "3rd Party Application";errorToCreate.URL = "https://url/to/relativity/page.aspx";errorToCreate.Workspace = new DTOs.Workspace(1016204);

//STEP 3: Attempt to create the error.DTOs.WriteResultSet<DTOs.Error> resultSet = null;try{

resultSet = proxy.Repositories.Error.Create(errorToCreate);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

//STEP 4: Check for success.if (resultSet.Success){

Console.WriteLine("Error Message successfully written to Relativity ErrorLog");

}else{

Console.WriteLine("Error Message not written to Relativity Error Log");return false;

}return true;

}

6.7 FieldRelativity uses Fields to store document and other metadata, as well as coding selections made by a reviewer.It provides multiple Field types to support this functionality, which are also available through the Services API.

6.7.1 System type fieldsSystem type fields are properties on the base Artifact class. Each DTO type has the following consistent set ofbase properties returned on the Artifact:

Page 114: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 114

Base Artifact Properties in the DTO Layer

ArtifactID SystemCreatedByArtifactTypeID SystemCreatedOnArtifactTypeName SystemLastModifiedByArtifactTypeGuids SystemLastModifiedOnGuids

ParentArtifact

6.7.1.1 TextIdentifer property on DTOsExcept for the Error DTO, all other DTOs have a TextIdentifier property that displays the Identifier field of anobject. For example, TextIdentifier equals the Name field on instances of Relativity Dynamic Objects RDOs.You can use it in place of the Name property on RDOs. If you set both the TextIdentifier and Name propertiesduring object creation, their values must be equal or you receive an error message.Use the constant kCura.Relativity.Client.Constants.RELATIVITY_TEXT_IDENTIFIER to reference the RelativityText Identifier field.

6.7.1.2 Using system type fieldsSince system type Fields don't have IDs, you must request them by name. Certain Fields have both a displayname used in the Relativity web UI, and an SQL column name used to reference the Field in the database. Forexample, Field has a property with the display name Created By that contains a username as a String, and anSQL column name of CreatedByName. Another property on Field has no display name, but an SQL columnname of CreatedBy, which returns the user’s ID.You can use either namewhen requesting Fields during a read or query operation. The Services API returnsthe Field using the name referenced in your request. If you don't specify any Fields in a request, the APIreturns all Fields using the display names when they exist and the SQL names when no display names areavailable.You can also set the StrictMode to maintain consistency on the Fields returned by the Services API, and fielddirectives to indicate when you want all or no Fields returned. See StrictMode property and Field directives onpage 73.

6.7.2 Field typesThe Services API supports several Field types that you can use on DTOs, including fixed-length text, single andmultiple choice, single and multiple object, and others.

6.7.2.1 FixedLengthText and LongText FieldsIn Relativity, a FixedLengthText field is larger than 4,999 characters, while a fixed length fields is less than orequal to this number of characters. For DTOs, text fields are set and returned as Strings.

View the code for creating an RDO and setting the value of a FixedLengthText field

DTOs.RDO obj = new DTOs.RDO();

Page 115: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 115

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.FIXED_LENGTH_FIELD, "Field Value"));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(obj);

View the code for reading a FixedLengthText field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.FIXED_LENGTH_FIELD));

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Read(obj);DTOs.RDO resultsObject = results.Results[0].Artifact;

string fieldValue = resultsObject[GUIDS.FIXED_LENGTH_FIELD].ValueAsFixedLengthText;

View the code for updating a FixedLengthText field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.FIXED_LENGTH_FIELD, "Updated FieldValue"));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(obj);

View the code for querying on RDOs with a value in their FixedLengthText fields

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();

query.ArtifactTypeGuid = GUIDS.OBJECT_ARTIFACT_TYPE_GUID;query.Fields = DTOs.FieldValue.AllFields;query.Condition = new TextCondition(GUIDS.FIXED_LENGTH_FIELD,TextConditionEnum.EqualTo, "Field Value");

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(query);

6.7.2.2 SingleChoice FieldsIn Relativity, a SingleChoice field has a predetermined set of values called choices. A user can only select one ofthese choices for coding or other purposes. Use these guidelines for SingleChoice fields:

n Create or update SingleChoice fields on documents or RDOs. Set the FieldValue to a Choice DTO instan-tiated with the Artifact ID or Artifact GUID. You can't set the values on SingleChoice fields to a text

Page 116: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 116

representation of a Choice. For example, you can set the value of the Field Single Choice Field on aDocument or RDO to a Choice using its ArtifactID (such as 100456) or its GUID.

n Retrieve a list of valid Choices for a SingleChoice field as follows:o Perform a read operation using the Artifact ID or GUID for Single Choice Field and the Arti-

factTypeName of Field (or ArtifactTypeID = 14).o Request that the Choices field is returned. A List of kCura.Relativity.Client.DTOs.Choice is

returned as illustrated in the following code.

DTOs.Field choiceFieldToRead = new DTOs.Field(1038781);

choiceFieldToRead.Fields.Add(new DTOs.FieldValue

(DTOs.FieldFieldNames.Choices));

var readResults = proxy.Repositories.Field.Read(choiceFieldToRead);

DTOs.MultiChoiceFieldValueList choices = readResults.Results[0].Artifact

[DTOs.FieldFieldNames.Choices].ValueAsMultipleChoice;

n Read operations on a SingleChoice field return the following data:o Type of the Value returned using the ValueAsSingleChoice is kCura.Relativity.Choice.DTOso Text value of the Choice set on the Field is the Name property of the Choice objecto ArtifactID property of the Choice object is the ArtifactID of the Choice definition within theWork-

space.o ArtifactGuids property is a List of GUIDs assigned to Choice definition.

View sample code for creating an RDO and setting the value of a SingleChoice field

DTOs.RDO obj = new DTOs.RDO();

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);DTOs.Choice choice = new DTOs.Choice(GUIDS.SINGLE_CHOICE_1);obj.Fields.Add(new DTOs.FieldValue(GUIDS.SINGLE_CHOICE_FIELD, choice));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(obj);

View sample code for reading a SingleChoice field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.SINGLE_CHOICE_FIELD));

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Read(obj);DTOs.RDO resultsObject = results.Results[0].Artifact;

DTOs.Choice choiceValue = resultsObject[GUIDS.SINGLE_CHOICE_FIELD].ValueAsSingleChoice;

Page 117: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 117

View sample code for updating a SingleChoice field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);DTOs.Choice choice = new DTOs.Choice(GUIDS.SINGLE_CHOICE_1);obj.Fields.Add(new DTOs.FieldValue(GUIDS.SINGLE_CHOICE_FIELD, choice));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(obj);

View sample code for querying for RDOs with a value in their SingleChoice fields

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();

query.ArtifactTypeGuid = GUIDS.OBJECT_ARTIFACT_TYPE_GUID;query.Fields = DTOs.FieldValue.AllFields;query.Condition = new SingleChoiceCondition(GUIDS.SINGLE_CHOICE_FIELD,

SingleChoiceConditionEnum.AnyOfThese, new Int32[] { ARTIFACTID.SINGLE_CHOICE_1 });

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(query);

6.7.2.3 File FieldsYou use a File type field to upload a file for a non-document object. When you add a File field, Relativityautomatically creates other fields containing file metadata, such as File Size, File Icon, and Text fields. For moreinformation and code samples, see File field on page 135.

6.7.2.4 MultiChoice FieldsIn Relativity, a MultiChoice field has a predetermined set of values called choices. A user can select severalchoices for coding or other purposes. Use these guidelines for MultiChoice fields:

n Create and update operations require you to set the values of a MultiChoice Field by defining aMultiChoiceFieldValueList, which is used to set and return MultiChoice Fields on DTOs. When you havea .NET List of Choice DTOs (FieldValueList<DTOs.Choice>), the UpdateBehavior property indicates howthe IDs in the FieldValueList are applied to the field (Replace or Merge). The default behavior is Replace,when no value is specified.If necessary, you can modified this list directly and pass it back in an update operation. You canpopulate this list from a read operation, or manually set it using a constructor that takes aList<DTOs.Choice> or parameter array of DTOs.Choice.

n Read or query operations return a MultiChoice value as a FieldValueList<DTOs.Choice> using theValueAsMultipleChoice property.

View sample code for creating an RDO and setting the value of a MultiChoice field

DTOs.RDO obj = new DTOs.RDO();

Page 118: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 118

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);

DTOs.MultiChoiceFieldValueList choices = new DTOs.MultiChoiceFieldValueList();

choices.Add(new DTOs.Choice(GUIDS.MULTI_CHOICE_1));

choices.Add(new DTOs.Choice(GUIDS.MULTI_CHOICE_2));

obj.Fields.Add(new DTOs.FieldValue(GUIDS.MULTI_CHOICE_FIELD, choices));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(obj);

View sample code for reading a MultiChoice field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);

obj.Fields.Add(new DTOs.FieldValue(GUIDS.MULTI_CHOICE_FIELD));

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Read(obj);

DTOs.RDO resultsObject = results.Results[0].Artifact;

DTOs.FieldValueList<DTOs.Choice> fieldValue =

(DTOs.FieldValueList<DTOs.Choice>) resultsObject[GUIDS.MULTI_CHOICE_

FIELD].ValueAsMultipleChoice;

View sample code for updating a MultiChoice field on an RDOThis sample also illustrates how to set the behavior of theMultiChoice Update to Replace, which modifies theexisting value.

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);

DTOs.MultiChoiceFieldValueList choices = new DTOs.MultiChoiceFieldValueList();

choices.Add(new DTOs.Choice(GUIDS.MULTI_CHOICE_1));

choices.Add(new DTOs.Choice(GUIDS.MULTI_CHOICE_2));

choices.UpdateBehavior = MultiChoiceUpdateBehavior.Replace;

obj.Fields.Add(new DTOs.FieldValue(GUIDS.MULTI_CHOICE_FIELD, choices));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(obj);

View sample code for querying for RDOs with values in their MultiChoice fields

Page 119: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 119

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();

query.ArtifactTypeGuid = GUIDS.OBJECT_ARTIFACT_TYPE_GUID;

query.Fields = DTOs.FieldValue.AllFields;

query.Condition = new MultiChoiceCondition(GUIDS.MULTI_CHOICE_FIELD,

MultiChoiceConditionEnum.AnyOfThese,

new Int32[] { ARTIFACTID.MULTI_CHOICE_1, ARTIFACTID.MULTI_CHOICE_2 });

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(query);

6.7.2.5 SingleObject FieldsIn Relativity, a SingleObject field defines a one-to-many relationship between two objects. Use theseguidelines for SingleObject fields:

n Create and update operations on a SingleObject field require you to pass DTO with the ArtifactID prop-erty set.

n On read and query operations, the ValueAsSingleObject property returns a SingleObject as a DTO withthe type of the object that you specified in the operation. On these DTOs, only the ArtifactID on thebase Artifact is populated, while the Fields collections is empty.

Note: If the DTO layer doesn't support the requested object type, then Artifact is used as the return type.

View sample code for creating an RDO and setting the value of a SingleObject field

DTOs.RDO obj = new DTOs.RDO();

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);

DTOs.Artifact fieldObj = new DTOs.Artifact(ARTIFACTID.FAKE_OBJECT_1);

obj.Fields.Add(new DTOs.FieldValue(GUIDS.SINGLE_OBJECT_FIELD, fieldObj));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(obj);

View sample code for reading a SingleObject field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);

obj.Fields.Add(new DTOs.FieldValue(GUIDS.SINGLE_OBJECT_FIELD));

DTOs.ResultSet<DTOs.RDO> results = new DTOs.ResultSet<DTOs.RDO>();

results = client.Repositories.RDO.Read(obj);

DTOs.RDO resultsObject = results.Results[0].Artifact;

DTOs.Artifact artifactValue = resultsObject[GUIDS.SINGLE_OBJECT_

FIELD].ValueAsSingleObject;

Page 120: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 120

View sample code for updating a SingleObject field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);

DTOs.Artifact fieldObj = new DTOs.Artifact(ARTIFACTID.FAKE_OBJECT_1);

obj.Fields.Add(new DTOs.FieldValue(GUIDS.SINGLE_OBJECT_FIELD, fieldObj));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(obj);

View sample code for querying on RDOs with values in their SingleObject fields

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();

query.ArtifactTypeGuid = GUIDS.OBJECT_ARTIFACT_TYPE_GUID;

query.Fields = DTOs.FieldValue.AllFields;

query.Condition = new ObjectCondition(GUIDS.SINGLE_OBJECT_FIELD,

ObjectConditionEnum.AnyOfThese, new Int32[] { ARTIFACTID.FAKE_OBJECT_1 });

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(query);

6.7.2.6 MultiObject FieldsIn Relativity, MultiObject fields define a many-to-many relationship between two objects. Use theseguidelines for MultiObject fields:

n Create and update operations on MultiObject fields require you to pass a FieldValueList containing DTOobjects with their ArtifactID property set.

n Read and query operations return a FieldValueList of the DTO for the object, using theGetValueAsMultipleObject<T>() method, where T is the type of Object. On these DTOs, only theArtifactID on the base Artifact is populated, while the Fields collections is empty.

Note: If the DTO layer doesn't support the requested object type, then Artifact is used as the return type.

View sample code for creating an RDO and setting the value of a MultiObject field

DTOs.RDO obj = new DTOs.RDO();

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);

DTOs.FieldValueList<DTOs.Artifact> objects = new DTOs.FieldValueList<DTOs.Artifact>();

objects.Add(new DTOs.Artifact(ARTIFACTID.FAKE_OBJECT_1));

objects.Add(new DTOs.Artifact(ARTIFACTID.FAKE_OBJECT_2));

obj.Fields.Add(new DTOs.FieldValue(GUIDS.MULTI_OBJECT_FIELD, objects));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(obj);

View sample code for reading a MultiObject field on an RDO

Page 121: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 121

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);

obj.Fields.Add(new DTOs.FieldValue(GUIDS.MULTI_OBJECT_FIELD));

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Read(obj);

DTOs.RDO resultsObject = results.Results[0].Artifact;

DTOs.FieldValueList<DTOs.Artifact> fieldValue =

resultsObject[GUIDS.MULTI_OBJECT_FIELD].GetValueAsMultipleObject<DTOs.Artifact>();

View sample code for updating a MultiObject field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);

DTOs.FieldValueList<DTOs.Artifact> objects = new DTOs.FieldValueList<DTOs.Artifact>();

objects.Add(new DTOs.Artifact(ARTIFACTID.FAKE_OBJECT_1));

objects.Add(new DTOs.Artifact(ARTIFACTID.FAKE_OBJECT_2));

obj.Fields.Add(new DTOs.FieldValue(GUIDS.MULTI_OBJECT_FIELD, objects));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(obj);

View sample code for querying on RDOs with values in their MultiObject fields

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();

query.ArtifactTypeGuid = GUIDS.OBJECT_ARTIFACT_TYPE_GUID;

query.Fields = DTOs.FieldValue.AllFields;

query.Condition = new ObjectsCondition(GUIDS.MULTI_OBJECT_FIELD,

ObjectsConditionEnum.AnyOfThese,

new Int32[] { ARTIFACTID.FAKE_OBJECT_1, ARTIFACTID.FAKE_OBJECT_2 });

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(query);

6.7.2.7 User FieldsIn Relativity, a User field contains the rights that a user has to the current workspace. Use these guidelines forUser fields:

n Create and update operations require you to set the User field to a User DTO with the ArtifactID prop-erty populated.

n On read and query operations, the ValueAsUser property returns the Value property of the User field asa type kCura.Relativity.Client.DTOs.User, which is populated with the ArtifactID and Name properties.

View sample code for creating an RDO and setting the value of a User field

Page 122: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 122

DTOs.RDO obj = new DTOs.RDO();

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);DTOs.User user = new DTOs.User(ARTIFACTID.USER);obj.Fields.Add(new DTOs.FieldValue(GUIDS.USER_FIELD, user));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(obj);

View sample code for reading a User field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.USER_FIELD));

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Read(obj);DTOs.RDO resultsObject = results.Results[0].Artifact;

DTOs.User userValue = resultsObject[GUIDS.USER_FIELD].ValueAsUser;

View sample code for updating a User field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);DTOs.User user = new DTOs.User(ARTIFACTID.USER);obj.Fields.Add(new DTOs.FieldValue(GUIDS.USER_FIELD, user));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(obj);

View sample code for querying on RDOs with values in their User fields

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();

query.ArtifactTypeGuid = GUIDS.OBJECT_ARTIFACT_TYPE_GUID;query.Fields = DTOs.FieldValue.AllFields;query.Condition = new UserCondition(GUIDS.USER_FIELD,UserConditionEnum.EqualTo, "User Name");

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(query);

6.7.2.8 WholeNumber FieldsRelativity uses WholeNumber fields to store any natural numbers. Use these guidelines for WholeNumberfields

Page 123: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 123

n Create and update operations require you to set theWholeNumber field to a whole number value.n Read and query operations on aWholeNumber field return the Value property as an integer using the

ValueAsWholeNumber property.

View sample code for creating an RDO and setting the value of a WholeNumber field

DTOs.RDO obj = new DTOs.RDO();

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);int wholeNumber = 100;obj.Fields.Add(new DTOs.FieldValue(GUIDS.WHOLE_NUMBER_FIELD, wholeNumber));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(obj);

View sample code for reading aWholeNumber field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.WHOLE_NUMBER_FIELD));

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Read(obj);DTOs.RDO resultsObject = results.Results[0].Artifact;int? fieldValue = resultsObject[GUIDS.WHOLE_NUMBER_FIELD].ValueAsWholeNumber;

View sample code for updating aWholeNumber field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);int wholeNumber = 5;obj.Fields.Add(new DTOs.FieldValue(GUIDS.WHOLE_NUMBER_FIELD, wholeNumber));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(obj);

View sample code for querying on RDOs with values in their WholeNumber fields

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();

query.ArtifactTypeGuid = GUIDS.OBJECT_ARTIFACT_TYPE_GUID;query.Fields = DTOs.FieldValue.AllFields;int queryWholeNumber = 250;query.Condition = new WholeNumberCondition(GUIDS.WHOLE_NUMBER_FIELD,

NumericConditionEnum.GreaterThan, queryWholeNumber);

Page 124: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 124

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(query);

6.7.2.9 Decimal FieldsIn Relativity, Decimal fields store numeric values that may include decimals. Use these guidelines for Decimalfields:

n Create and update operations require you to set the Decimal field to a decimal value.n Read and query operations on a Decimal field return the Value property of the field as a decimal using

the ValueAsDecimal property.

View sample code for creating an RDO and setting the value of a Decimal field

DTOs.RDO obj = new DTOs.RDO();

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);var decimalNumber = 100.25;obj.Fields.Add(new DTOs.FieldValue(GUIDS.DECIMAL_FIELD, decimalNumber));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(obj);

View sample code for reading a Decimal field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.DECIMAL_FIELD));

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Read(obj);DTOs.RDO resultsObject = results.Results[0].Artifact;

decimal? fieldValue = resultsObject[GUIDS.DECIMAL_FIELD].ValueAsDecimal;

View sample code for updating a Decimal field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);decimal decimalNumber = 5.0M;obj.Fields.Add(new DTOs.FieldValue(GUIDS.DECIMAL_FIELD, decimalNumber));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(obj);

View sample code for querying on RDOs with values in their Decimal fields

Page 125: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 125

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();

query.ArtifactTypeGuid = GUIDS.OBJECT_ARTIFACT_TYPE_GUID;query.Fields = DTOs.FieldValue.AllFields;decimal queryDecimal = 50.0M;

query.Condition = new DecimalCondition(GUIDS.DECIMAL_FIELD,NumericConditionEnum.GreaterThan, new Decimal[] { queryDecimal });

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(query);

6.7.2.10 Currency FieldsRelativity uses Currency fields to store numeric values in a currency format. Use these guidelines for Currencyfields:

n Create and update operations require you to set the Currency field to a decimal value.n Read and query operations on a Currency field return the Value property of the field decimal using the

ValueAsCurrency property.

View sample code for creating an RDO and setting the value of a Currency field

DTOs.RDO obj = new DTOs.RDO();

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);var currencyValue = 100.00M;obj.Fields.Add(new DTOs.FieldValue(GUIDS.CURRENCY_FIELD, currencyValue));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(obj);

View sample code for reading a Currency field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.CURRENCY_FIELD));

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Read(obj);DTOs.RDO resultsObject = results.Results[0].Artifact;

decimal? fieldValue = resultsObject[GUIDS.CURRENCY_FIELD].ValueAsCurrency;

View sample code for updating a Currency field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);

Page 126: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 126

var currencyValue = 5.00;obj.Fields.Add(new DTOs.FieldValue(GUIDS.CURRENCY_FIELD, currencyValue));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(obj);

View sample code for querying on RDOs with values in their Currency fields

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();

query.ArtifactTypeGuid = GUIDS.OBJECT_ARTIFACT_TYPE_GUID;query.Fields = DTOs.FieldValue.AllFields;decimal currencyValue = 100.00M;query.Condition = new DecimalCondition(GUIDS.CURRENCY_FIELD,

NumericConditionEnum.GreaterThan, new Decimal[] { currencyValue });

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(query);

6.7.2.11 Date FieldsRelativity uses Date fields to store the date or date and time. Use these guidelines for Date fields:

n Create and update operations require you to set the Date field to a .NET DateTime value.n Read and query operations on a Date field return the Value property of the field as a .NET DateTime

using the ValueAsDate property.

View sample code for creating an RDO and setting the value of a Date field

DTOs.RDO obj = new DTOs.RDO();

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.DATE_FIELD, DateTime.Now));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(obj);

View sample code for reading a Date field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.DATE_FIELD, DateTime.Now));

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Read(obj);DTOs.RDO resultsObject = results.Results[0].Artifact;

DateTime? fieldValue = resultsObject[GUIDS.DATE_FIELD].ValueAsDate;

View sample code for updating a Date field on an RDO

Page 127: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 127

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.DATE_FIELD, DateTime.Now));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(obj);

View sample code for querying on RDOs with values in their Date fields

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();

query.ArtifactTypeGuid = GUIDS.OBJECT_ARTIFACT_TYPE_GUID;query.Fields = DTOs.FieldValue.AllFields;query.Condition = new DateTimeCondition(GUIDS.DATE_FIELD,DateTimeConditionEnum.GreaterThan, DateTime.Now);

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(query);

6.7.2.12 Yes/No FieldsIn Relativity, a Yes/No field stores a Boolean value. Use these guidelines for Yes/No fields:

n Create and update operations require you to set the Yes/No field to a .NET Boolean value.n Read and query operations on Yes/No field return the Value property of the field as a .NET Boolean

using the ValueAsYesNo Property.

View sample code for creating an RDO and setting the value of a Yes/No field

DTOs.RDO obj = new DTOs.RDO();

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.YES_NO_FIELD, true));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Create(obj);

View sample code for reading a Yes/No field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.YES_NO_FIELD));

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Read(obj);DTOs.RDO resultsObject = results.Results[0].Artifact;

bool? fieldValue = resultsObject[GUIDS.YES_NO_FIELD].ValueAsYesNo;

Page 128: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 128

View sample code for updating a Yes/No field on an RDO

DTOs.RDO obj = new DTOs.RDO(artifactId);

obj.ArtifactTypeGuids.Add(GUIDS.OBJECT_ARTIFACT_TYPE_GUID);obj.Fields.Add(new DTOs.FieldValue(GUIDS.YES_NO_FIELD, false));

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.RDO.Update(obj);

View sample code for querying on RDOs with values in their Yes/No fields

DTOs.Query<DTOs.RDO> query = new DTOs.Query<DTOs.RDO>();

query.ArtifactTypeGuid = GUIDS.OBJECT_ARTIFACT_TYPE_GUID;query.Fields = DTOs.FieldValue.AllFields;query.Condition = new BooleanCondition(GUIDS.YES_NO_FIELD,BooleanConditionEnum.EqualTo, true);

DTOs.ResultSet<DTOs.RDO> results = client.Repositories.RDO.Query(query);

6.7.3 Supported operations for Field typesThe following operations are supported for Field types on DTOs:

Operation Supported for Fields on DTOsCreate a Field on a DTO RDO and Document DTOsRead Field metadata All DTOsDelete a Field (except system Field) from a DTO All DTOsQuery on Field metadata All DTOs

Note: For information about updating DTOs, see DTO reference and code samples on page 81. When youupdate Documents and RDOs, the value of each Field on an object in the Fields collection is overwrittenwith a new value, except for MultiChoice Fields. SeeMultiChoice Fields on page 117.

6.7.4 Field code samplesRelativity uses fields to store object information, document metadata, and coding choices. For moreinformation, see Fields in the Relativity 8.1 Documentation site.The Services API supports create, read, delete, and query operations on a Field DTO.

6.7.4.1 Creating a FieldYou can use the Create() on the Field repository to add a new field to Relativity. The ObjectType indicates theobject associated with this Field, such as Document as illustrated in this sample code.

Page 129: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 129

public static bool Create_Field_Using_Repository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = 1016204;

// STEP 1: Create a Field DTO and populate the Fields.DTOs.Field dto = new DTOs.Field();dto.Name = "This is a Single Choice field by GUID11";dto.ObjectType = new DTOs.ObjectType() { DescriptorArtifactTypeID = (int)ArtifactType.Document };

// The ObjectType DTO can also be instantiated with the GUID of the// ObjectType instead of setting the DescriptorArtifactTypeID.// dto.ObjectType = new DTOs.ObjectType(new Guid("4D3BA67C-9F88-4D29-8E6C-6DECB6A682D1"));dto.FieldTypeID = kCura.Relativity.Client.FieldType.SingleChoice;dto.IsRequired = false;dto.Unicode = false;dto.AvailableInFieldTree = false;dto.OpenToAssociations = false;dto.Linked = false;dto.AllowSortTally = true;dto.Wrapping = true;dto.AllowGroupBy = false;dto.AllowPivot = false;dto.IgnoreWarnings = true;dto.Width = "";

// STEP 2: Call the Create method on the repository and pass the DTO.WriteResultSet<DTOs.Field> resultSet;try {

resultSet = proxy.Repositories.Field.Create(dto);}catch (Exception ex) {

Console.WriteLine("Error: " + ex.Message);return false;

}

if (!resultSet.Success) {Console.WriteLine("Error: " + resultSet.Message);foreach (Result<DTOs.Field> result in resultSet.Results) {

Console.WriteLine("Result Error: " + result.Message);}return false;

}Console.WriteLine("Overall status of creating a Field: " +resultSet.Success);

Page 130: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 130

Console.WriteLine("New Artifact ID: " + resultSet.Results.FirstOrDefault().Artifact.ArtifactID);

return true;}

6.7.4.2 Creating a Relational FieldIn Relativity, a relational field is used to identify a group of related documents. You can upload your own iconfor a relational field, which is displayed in the Related Items pane of the reviewer interface. For moreinformation, see PaneIcon property on page 144.This code sample illustrates how to create a relational Field and set its pane icon.

public void Create_RelationalField(){

try{

using (IRSAPIClient proxy =new RSAPIClient(new Uri("net.pipe://localhost/Relativity.Services"),new IntegratedAuthCredentials()))

{proxy.APIOptions.WorkspaceID = WORKSPACE_ID;

var fieldDTO = new kCura.Relativity.Client.DTOs.Field();fieldDTO.Name = "Relational Field 1";fieldDTO.FieldTypeID = (Int32)FieldType.FixedLengthText;fieldDTO.ObjectType = new kCura.Relativity.Client.DTOs.ObjectType() { DescriptorArtifactTypeID = (Int32)ArtifactType.Document };fieldDTO.Length = 100;fieldDTO.IsRequired = false;fieldDTO.IncludeInTextIndex = false;fieldDTO.Unicode = false;fieldDTO.AllowHTML = false;fieldDTO.OpenToAssociations = false;fieldDTO.Linked = false;fieldDTO.AllowSortTally = false;fieldDTO.Width = "100";fieldDTO.Wrapping = false;fieldDTO.AllowPivot = false;fieldDTO.AllowGroupBy = false;

// Set IsRelational to true.fieldDTO.IsRelational = true;

// After IsRelational is set to true, add other required fields.fieldDTO.FriendlyName = "New Relational Field Friendly Name";

Page 131: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 131

fieldDTO.Order = 100;fieldDTO.ImportBehavior = ImportBehavior.LeaveBlankValuesUnchanged;fieldDTO.RelationalView = null; //Null is the default "All Items"view.

// The field "PaneIcon" takes a RelationalFieldIcon object thatcontains a path and a byte array// for the icon that represents the field at the bottom of thedocument review page.string path = "c:\\icon.png";System.IO.FileStream ifStream = System.IO.File.OpenRead(path);Int32 len = (Int32)ifStream.Length;System.IO.BinaryReader reader = new System.IO.BinaryReader(ifStream);byte[] byteArr = new byte[len];reader.Read(byteArr, 0, len);fieldDTO.PaneIcon = new RelationalFieldIcon(path, byteArr);

WriteResultSet<kCura.Relativity.Client.DTOs.Field> writeResults =proxy.Repositories.Field.Create(fieldDTO);

if (writeResults.Success){

Console.WriteLine(string.Format("Field with name {0} was createdwith Artifact ID {1}.", fieldDTO.Name, writeResults.Results[0].Artifact.ArtifactID));

}else{

Console.WriteLine(string.Format("An error occurred creating field:{0}", writeResults.Message));

for (Int32 i = 0; i <= writeResults.Results.Count - 1; i++){

if (!writeResults.Results[i].Success){Console.WriteLine(String.Format("An error occurred in create request {0}: {1}", i, writeResults.Results[i].Message));

foreach (string warning in writeResults.Results[0].WarningMessages){Console.WriteLine("Warning: {0}", warning);}}

Page 132: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 132

}}

}}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));}

}

6.7.4.3 Reading a FieldTo read values on a Field, you can use the Read() method on the Field repository as illustrated in this codesample.

public static bool Read_Field_Using_Repository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = 1016204;

// STEP 1: Call the Read() method on the Field repository, passing a FieldDTO.ResultSet<DTOs.Field> results;try {

results = proxy.Repositories.Field.Read(new DTOs.Field(1035984) { Fields= FieldValue.AllFields });

}catch (Exception ex) {

Console.WriteLine("Error: " + ex.Message);return false;

}

if (!results.Success) {Console.WriteLine("Error: " + results.Message);foreach (Result<DTOs.Field> result in results.Results) {

Console.WriteLine("Result Error: " + result.Message);}

return false;}// STEP 2: Get the Field artifact from the read results.DTOs.Field fieldArtifact = results.Results.FirstOrDefault().Artifact;

Console.WriteLine("Field Name: " + fieldArtifact.Name);Console.WriteLine("Field Type: " + fieldArtifact.FieldTypeID);Console.WriteLine("Object Type: " +fieldArtifact.ObjectType.DescriptorArtifactTypeID);

Page 133: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 133

foreach (DTOs.Choice choice in fieldArtifact.Choices)Console.WriteLine("Valid Choice for Field = " + choice.Name + ":" +choice.ArtifactID );

return true;}

6.7.4.4 Deleting a FieldYou can use the Delete() method on the Field repository to remove fields as illustrated in this code sample.

public static bool Delete_Field_Using_Repository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = 1016204;

// STEP 1: Define the Field to delete.kCura.Relativity.Client.DTOs.Field dto = newkCura.Relativity.Client.DTOs.Field(1039140);ResultSet<kCura.Relativity.Client.DTOs.Field> results;

// STEP 2: Delete the Field.try{

results = proxy.Repositories.Field.Delete(dto);}catch (Exception ex){

Console.WriteLine("Error: " + ex.Message);return false;

}

if (!results.Success){

Console.WriteLine("Error: " + results.Message);foreach (Result<kCura.Relativity.Client.DTOs.Field> result inresults.Results){

Console.WriteLine("Result Error: " + result.Message);}return false;

}return true;

}

Page 134: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 134

6.7.4.5 Querying for a FieldThis code sample illustrates how to set query conditions, call the Query() method on the Field repository, anditerate through the result set. For more information, see Querying on page 227.

public static bool Query_Field_Using_Repository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = 1016204;

// STEP 1: Define the query.Query<kCura.Relativity.Client.DTOs.Field> query = newQuery<kCura.Relativity.Client.DTOs.Field>();query.Fields = FieldValue.AllFields;query.Condition =

new WholeNumberCondition(ArtifactQueryFieldNames.ArtifactID,NumericConditionEnum.EqualTo, 1039140);

ResultSet<kCura.Relativity.Client.DTOs.Field> results;

// STEP 2: Query for the Field.try{

results = proxy.Repositories.Field.Query(query);}catch (Exception ex){

Console.WriteLine("Error: " + ex.Message);return false;

}if (!results.Success){

Console.WriteLine("Error: " + results.Message);

foreach (Result<kCura.Relativity.Client.DTOs.Field> result inresults.Results){

Console.WriteLine("Result Error: " + result.Message);}return false;

}

// STEP 3: Get the Field artifact from the read results.kCura.Relativity.Client.DTOs.Field fieldArtifact =results.Results.FirstOrDefault().Artifact;

Console.WriteLine("Field Name: " + fieldArtifact.Name);Console.WriteLine("Field Type: " + fieldArtifact.FieldTypeID);

Page 135: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 135

Console.WriteLine("Object Type: " +fieldArtifact.ObjectType.DescriptorArtifactTypeID);

foreach (kCura.Relativity.Client.DTOs.Choice choice infieldArtifact.Choices)

Console.WriteLine("Valid Choice for Field = " + choice.Name + ":" +choice.ArtifactID);

return true;}

6.7.5 File fieldA File type field is used to upload a file for a non-document object. When you add a File field, Relativityautomatically creates other fields containing file metadata, such as File Size, File Icon, and Text fields.

Note: The following sample code uses the variable called proxy to reference an instance of the RSAPIClientclass that already has the APIOptions property set. For simplicity, this sample code doesn't check oncompleted operations or provide error handling.

6.7.5.1 Creating a File field on an RDOYou can create a dynamic object and then add a File field on it. The following sections describe this two partprocess.

Creating a Dynamic ObjectType

Create a Dynamic ObjectType that will be referenced in other code samples illustrating File field usage. ThisDynamic ObjectType will be called Our File Container.Create an ObjectType instance as follows:

var objectType = new ObjectType();

Set the values for the appropriate fields:

objectType.CopyInstancesOnWorkspaceCreation = false;objectType.Name = “Our File Container”;objectType.ParentArtifactTypeID = (int)ArtifactType.Case;objectType.Pivot = false;objectType.RelativityApplications = new FieldValueList<RelativityApplication>();objectType.SnapshotAuditingEnabledOnDelete = true;

Using the DTO layer, call the Create() method of the ObjectType repository:

Page 136: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 136

var createResults = proxy.Repositories.ObjectType.Create(objectType);

Save the value of the ArtifactID property for later use in file uploading:

var ourFileContainerInstanceArtifactId = createResults.Results[0].Artifact.ArtifactID;

To create an instance of the Dynamic ObjectType, you need to determine the DescriptorArtifactTypeID, whichis a unique identifier for the newly created Dynamic Object type. Create a Query instance as follows:

var query = new Query<ObjectType>();

Set the values for the appropriate fields. In general, you request only the fields that you need, rather than usethe AllFields directive.

query.Condition = new TextCondition(“Name”, TextConditionEnum.EqualTo, “OurFile Container”);query.Fields = FieldValue.AllFields;

Call the Query() method of the ObjectType repository:

var queryResults = proxy.Repositories.ObjectType.Query(query);

Save the value of the DescriptorArtifactTypeID property for later use in field creation. You might also want toconfirm that the query executed successfully.

var descriptorArtifactTypeId = queryResults.Results[0].Artifact.DescriptorArtifactTypeID;

Creating a File field

You can create a new File field on a Dynamic ObjectType. In the following sample code, the variabledescriptorArtifactTypeId refers to the value retrieved from Creating a File field on an RDO on the previouspage.Create a Field instance:

var field = new kCura.Relativity.Client.DTOs.Field();

Set the values for the appropriate fields:

Page 137: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 137

field.AllowGroupBy = false;field.AllowPivot = false;field.AllowSortTally = false;field.FieldTypeID = FieldType.File;field.IgnoreWarnings = true;field.IsRequired = false;field.Linked = false;field.Name = “File Field For Our File Container”;

This ObjectType was added in Creating a File field on an RDO on page 135:

field.ObjectType = new ObjectType { DescriptorArtifactTypeID =descriptorArtifactTypeId };field.OpenToAssociations = false;field.Width = String.Empty;field.Wrapping = false;

Call the Create() method of the Field repository:

var createResults = proxy.Repositories.Field.Create(field);

Save the value of the ArtifactID property for use in file uploading later:

var fileFieldArtifactId = createResults.Results[0].Artifact.ArtifactID;

6.7.5.2 Uploading to a File fieldYou can upload a file to a File field. You need to obtain the following identifiers to upload the file:

n ArtifactID of the File field associated with the object typen ArtifactID of the object instance with a File field that needs to be populated

Use this variable for the newly created File field:

fileFieldArtifactId

Use this variable for the newly created instance of our Dynamic Object type (Our File Container):

ourFileContainerInstanceArtifactId

Create an UploadRequest instance:

var uploadRequest = new UploadRequest(proxy.APIOptions);

Page 138: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 138

Set the values for the appropriate fields:

uploadRequest.Metadata.FileName = @”C:\path\to\my\file.docx”;uploadRequest.Metadata.FileSize = new FileInfo(uploadRequest.Metadata.FileName).Length;

This optional property indicates that the current contents in the File field will be overwritten:

uploadRequest.Overwrite = true;uploadRequest.Target.FieldId = fileFieldArtifactId;uploadRequest.Target.ObjectArtifactId = ourFileContainerInstanceArtifactId;

(Optional) Register an event handler for the UploadComplete event:

proxy.UploadComplete += UploadCompleteHandler;

Call the Upload() method on the RSAPIClient:

proxy.Upload(uploadRequest);

6.7.5.3 Downloading from a File fieldYou can download a file from a File field. The Services API provides an overloaded Download() method for thispurpose:

n DownloadResponse Download(FileRequest fileRequest, string outputPath) - Downloads the file tothe location specified by outputPath.

n KeyValuePair<DownloadResponse, Stream> Download(FileRequest fileRequest) - Downloads the fileto the Stream of the KeyValuePair.

In addition, you need to obtain the following identifiers to upload the file:

n ArtifactID of the File field associated with the object typen ArtifactID of the object instance with a file that needs to be downloaded

Use this variable for the ArtifactID of the newly created File field:

fileFieldArtifactId

Use this variable for the newly created instance of our Dynamic Object type (Our File Container):

ourFileContainerInstanceArtifactId

Create a FileRequest instance as follows:

Page 139: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 139

var fileRequest = new FileRequest(proxy.APIOptions);fileRequest.Target.FieldId = fileFieldArtifactId;fileRequest.Target.ObjectArtifactId = ourFileContainerInstanceArtifactId;

Register an event handler for the DownloadComplete event:

proxy.DownloadComplete += DownloadCompleteHandler;

Call one of the overload Download() methods on the RSAPIClient:

proxy.Download(fileRequest, @”C:\path\to\downloaded\file.docx”);

6.7.5.4 Getting a download URL for a File fieldYou can retrieve a URL from the File field on a Dynamic Object and then use the URL to download theassociated file. The following code sample illustrates how to call the GetFileFieldDownloadURL() method onthe proxy and download the required file.

public static bool GetFileFieldDownloadURL(IRSAPIClient proxy){

// STEP 1: Set APIOptions and instantiate a new DownloadURLRequest with theAPIOptions.proxy.APIOptions.WorkspaceID = 1015926;var downloadUrlRequest = new DownloadURLRequest(proxy.APIOptions);

// STEP 2: Set properties in the DownloadURLRequest.downloadUrlRequest.BaseURI = new Uri("http://localhost");

// Set the ObjectArtifactID or ObjectArtifactGuid that identifies theinstance of the RDO.downloadUrlRequest.Target.ObjectArtifactGuid = new Guid("B5FD94BB-0226-4CA5-B227-5F3F7BEE4D8A");

// Set the FieldID, FieldName, or FieldGuid of the File File.downloadUrlRequest.Target.FieldId = 1042467;

// STEP 3: Call the GetFileFieldDownloadURL method on the proxy.DownloadURLResponse response;try {

response = proxy.Repositories.RDO.GetFileFieldDownloadURL(downloadUrlRequest);

}catch (Exception ex) {

Page 140: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 140

Console.WriteLine("An error occurred calling GetFileFieldDownloadURL: {0}", ex.Message);return false;

}

if (response.Success) {Console.WriteLine("File Field Download URL: {0}", response.URL);

}else {

Console.WriteLine("An error occurred calling GetFileFieldDownloadURL: {0}", response.Message);return false;

}

// STEP 4: Download the File using the URL.HttpClient httpClient = new HttpClient();httpClient.BaseAddress = new Uri("http://localhost/");

HttpResponseMessage httpResponse = httpClient.GetAsync(response.URL).Result;

if (httpResponse.IsSuccessStatusCode) {try {

// Read the file.Stream resultStream = httpResponse.Content.ReadAsStreamAsync().Result;var contentDisposition =httpResponse.Content.Headers.ContentDisposition;

string fileName = contentDisposition.FileName;

using (var fileStream = File.Create("C:\\path" + fileName)) {resultStream.CopyTo(fileStream);

}Console.WriteLine("Received file: {0}", fileName);

}catch (Exception ex) {

// An exception occurred when attempting to read and save the filelocally.// Handle the exception.Console.WriteLine("Error saving File locally: {0}", ex.Message);return false;

}}else {

Console.WriteLine("HTTP response not successful: {0}",httpResponse.StatusCode);return false;

Page 141: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 141

}

return true;}

6.7.5.5 Clearing a File fieldYou can clear a File field through the Services API. You need to obtain the following identifiers to clear the field:

n ArtifactID of the File field associated with the object typen ArtifactID of the object instance with a File fields that needs to be cleared

Use this variable for the ArtifactID of the newly created File field:

fileFieldArtifactId

Use this variable for the newly created instance of our Dynamic Object type:

ourFileContainerInstanceArtifactId

Create a FileRequest instance as follows:

var fileRequest = new FileRequest(proxy.APIOptions);fileRequest.Target.FieldId = fileFieldArtifactId;fileRequest.Target.ObjectArtifactId = ourFileContainerInstanceArtifactId;

Call the Clear() method on the RSAPIClient:

proxy.Clear(fileRequest);

6.7.6 Fields used by Field type, User, and GroupField, User, and Group objects use special fields that aren't used by other system types.

6.7.6.1 Fields used by the Field objectsThe Field system type uses specialized properties including IgnoreWarnings and the PaneIcon. In addition, theResult object available when a Field is create contains the specialized properties WarningMessage andIsWarning.

WarningMessage and IsWarning properties

The Create function can return warning messages when a Field object is created. If there are warnings, thesemessages are set on theWarningMessage property of the Result object, and IsWarning property is set toTrue. Since theWarningMessage property has a List datatype, multiple warning messages can be returned ifnecessary.

Page 142: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 142

IgnoreWarnings property

The Field DTO contains an IgnoreWarnings Boolean property, which you can use to control howwarningmessages are handled. When the IgnoreWarnings property is set to False and warnings are returned, theCreate call will fail. When IgnoreWarnings property is set to True and warnings are returned, the Create call willsucceed.In most cases, the code calling the API handles messages returned when the IgnoreWarnings property is setto False, and a Create call returns warnings. Depending on the programming logic, the IgnoreWarningsproperty could be set to True, and the Create call could be repeated when the warnings should be ignored.When Fields are created, theMessage property of a Result object can return multiple errors. Each error will beprefixed with the string API_Field_Validation_Error. This functionality contrasts with other areas in the API,which return only a single error message.

View sample code illustrating how to use IgnoreWarnings property on a Field

public void Create_Field_With_IgnoreWarnings(){

try{

using (IRSAPIClient proxy =new RSAPIClient(new Uri("net.pipe://localhost/Relativity.Services"),new IntegratedAuthCredentials()))

{proxy.APIOptions.WorkspaceID = WORKSPACE_ID;

var fieldDTO = new kCura.Relativity.Client.DTOs.Field();fieldDTO.Name = "Test Field with Warning 1";fieldDTO.FieldTypeID = (Int32)FieldType.FixedLengthText;fieldDTO.ObjectType = new kCura.Relativity.Client.DTOs.ObjectType() { DescriptorArtifactTypeID = (Int32)ArtifactType.Document };fieldDTO.Length = 100;fieldDTO.IsRequired = false;fieldDTO.IncludeInTextIndex = false;fieldDTO.Unicode = false;fieldDTO.AllowHTML = false;fieldDTO.OpenToAssociations = false;fieldDTO.Linked = false;fieldDTO.AllowSortTally = false;fieldDTO.Width = "100";fieldDTO.Wrapping = false;fieldDTO.AllowPivot = false;fieldDTO.IsRelational = false;

// Set AllowGroupBy to true, which should trigger the warning message:// "Setting Allow Group By on a text field containing a large numbercan// of values can negatively impact system performance."

Page 143: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 143

// When Ignore Warnings is set to false and warnings are returned, theCreate call fails.// When Ignore Warnings is set to true and warnings are returned, theCreate call succeeds.fieldDTO.AllowGroupBy = true;fieldDTO.IgnoreWarnings = false;

WriteResultSet<kCura.Relativity.Client.DTOs.Field> writeResults =proxy.Repositories.Field.Create(fieldDTO);

if (writeResults.Success){

Console.WriteLine(string.Format("Field with name {0} was createdwith ArtifacT ID {1}.",

fieldDTO.Name, writeResults.Results[0].Artifact.ArtifactID));}else{

Console.WriteLine(string.Format("An error occurred creating field:{0}",

writeResults.Message));

for (Int32 i = 0; i <= writeResults.Results.Count - 1; i++){

if (!writeResults.Results[i].Success){Console.WriteLine(String.Format("An error occurred in create request {0}: {1}", i,writeResults.Results[i].Message));

foreach (string warning in writeResults.Results[0].WarningMessages){Console.WriteLine("Warning: {0}", warning);}}

}}

}}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));}

Page 144: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 144

}

PaneIcon property

When you create a Relational Field, you must set a property for the pane icon that is displayed in theRelativity viewer. This icon should be a PNG of 16 x 16 pixels. On DTOs, the pane icon uses theRelationalFieldIcon object, which contains the same Data and Path properties as the FileValue object. Youmust set the Path and Data properties on the PaneIcon when creating a Relational Field. The Field DTO has aproperty called PaneIcon that takes a RelationalFieldIcon object as its value. On query and read operations,only the Path value is returned.This code sample illustrates how to create a Relational Field with a PaneIcon. It uses the RelationalFieldIcon.

var fieldDTO = new DTOs.Field();string path = "c:\\path\\icon.png";System.IO.FileStream ifStream = System.IO.File.OpenRead(path);Int32 len = (Int32)ifStream.Length;System.IO.BinaryReader reader = new System.IO.BinaryReader(ifStream);byte[] byteArr = new byte[len];reader.Read(byteArr, 0, len);fieldDTO.PaneIcon = new RelationalFieldIcon(path, byteArr);

/// Set additional fields on the Field DTO.

DTOs.WriteResultSet<DTOs.RDO> results = client.Repositories.Field.Create(fieldDTO);

This code sample illustrates how to read a PaneIcon field on a Field.

DTOs.Field dto = new DTOs.Field(1038285);dto.Fields.Add(new DTOs.FieldValue(DTOs.FieldFieldNames.PaneIcon));

var readResults = proxy.Repositories.Field.Read(dto);

DTOs.RelationalFieldIcon paneIcon =readResults.Results[0].Artifact[DTOs.FieldFieldNames.PaneIcon].ValueAsRelationalFieldIcon;

6.7.6.2 Fields used by Group and User objectsGroups and Users require several special fields that aren't used by other system types. These fields includePassword, User, and Group.

Password fields

To create a User, the Password, User Must Change Password on Next Login, and Send New Password Tofields are required password settings. Use these general guidelines when working with password fields:

Page 145: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 145

n When working with Users, query for the values needed and save their Choice IDs in variables or a cacheas you would for other Single Choice fields. Single Choice fields accept Choice IDs rather than Choicenames.

n The general guidelines for creating a User also apply on update, except that the Password field can beset to the Choice called Use Current Password. In this case, no other password fields are required,except for User Must Change Password On Next Login. This setting indicates that the passwordshouldn't be altered.

Note: These Fields exist as properties on the User DTO.

PasswordPassword is a Single Choice field. Use the following guidelines when working with this field:

n Set this Field to one of these Choice values: Auto-generate Password orManually set password.n Retrieve the Choice IDs for this Field by calling the Query method and passing in a Query object with a

TextCondition on the field named Choice Typewith Password as the text.n When the Password field is set to Auto-generate Password, a valid password is automatically gen-

erated for the user.n When the Password field is set toManually set password, a Field named NewPassword is required.

This Field is used to provide the new password when a User is being created.n Make sure that the password meets the following requirements:

o Limited to between 8 and 50 characters in length.o Contains at least one uppercase letter, one lower case letter, one numeral, and one special char-

acter.o Doesn't contain the special characters backslash (\), quotation mark ("), greater than (>), or less

than (<).o Can't be one of the previous X passwords, where X is the value in the EDDS Configuration Table

named MaxPasswordHistory.User Must Change Password on Next LoginUser Must Change Password on Next Login is a Yes/No field.Send New Password To

Send New Password To field is a Single Choice Field. Use the following guidelines when working with this field:

n Set the Send New Password To field to one of these Choice ID values:o Me (email) - Sends the password to the user logged in to the Services API.o This user (email) - Sends the password to the user being created or edited.o Return - Create or Update call returns the password in a field named Password in the

MetaDataArtifact property of a Result object.n Retrieve the Choice IDs for the Send New Password To field by calling the Query() method and passing

in a Query object with a TextCondition on the field named Choice Typewith Send new password to asthe text.

n Configuration settings for sending email messages are stored in the EDDS Configuration Table.

Groups field

When creating or updating a User, you can include the Groups field to set or modify the groups that includethe user as a member. A Groups property also exists on the Group DTO. Follow these guidelines when working

Page 146: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 146

with the Groups field:

n On create, the value of the Groups field is a list of ArtifactIDs, which indicate the groups that will includethe user as a member.

n On create, don't include the Everyone group in the list of ArtifactIDs. The user is automatically added tothe Everyone group.

n If an error while adding a user to a group, the user will still be created.n On update, the value of the Groups field is a MultiUpdateValue object, which contains the Value and

Behavior properties. The Value property is a list of ArtifactIDs, and Behavior property specifies how theArtifact IDs are applied to the user.

Note: You can only use the MultiUpdateValue class as a parameter when you update User and Group objects.This class has a Behavior property, which is a MultiUpdateBehavior enum. This enumeration is also availableonly for use with User and Group objects.

n When using DTOs, the Groups property takes a FieldValueList containing a List of Group DTOs.n If the behavior is set to Update, you must include the Everyone group in the list of ArtifactIDs.

Users field

You can include the User field when you want to set or modify users assigned to the Group that you areupdating or creating. Follow these guidelines when working with the Users field:

n On create, the value of the Users field is a list of ArtifactIDs that indicate the users that you wantincluded in a group.

n On update, the value of the Users field is MultiUpdateValue object, which contains the Value andBehavior properties. The Value property is a list of ArtifactIDs, and Behavior property specifies how theArtifactIDs should be applied to the user.

Note: You can only use the MultiUpdateValue class as a parameter when you update User and Group objects.This class has a Behavior property, which is a MultiUpdateBehavior enum. This enumeration is also availableonly for use with User and Group objects.

n When using the DTOs, the Users property takes a MultiUserFieldValueList. When you have a .NET Listof User DTOs (FieldValueList<DTOs.Choice>), the UpdateBehavior property indicates how the IDs in theFieldValueList are applied to the field (Replace, Add, or Remove). The default behavior is Replace, whenno value is specified.

6.7.7 Constant Field namesThe Services API supports constant strings for Field names on multiple Relativity objects. Most of theseclasses extend the base class ArtifactFieldNames. You may also want to consider using enumerations orconstants instead of strings in your code. The Services API uses these constant Field names when you enablethe StrictMode property or use DTOs. See the following resources:

n Data Transfer Objects (DTOs) on page 67n StrictMode property and Field directives on page 73n Best practices for the Services API on page 75

ArtifactFieldNames (base class)

Page 147: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 147

Property Field NameSystemCreatedBy "System Created By"SystemCreatedOn "System Created On"SystemLastModifiedBy "System Last Modified By"SystemLastModifiedOn "System Last Modified On"TextIdentifier "Relativity Text Identifier"

ArtifactQueryFieldNames (doesn't extend ArtifactFieldNames)

Property Field NameArtifactID "Artifact ID"ArtifactGUID "Artifact GUID"ParentArtifactID "Parent Artifact ID"

BatchFieldNames

Property Field NameAssignedTo "Assigned To"BatchNumber "Batch Number"BatchSet "Batch Set"BatchSize "Batch Size"BatchStatus "Batch Status"BatchUnit "Batch Unit"Name "Name"Reviewed "Reviewed"

BatchSetFieldNames

Property Field NameAutoBatch "Auto Batch"AutoCreateRateMinutes "Auto Create Rate(minutes)"BatchDataSource "Batch Data Source"BatchPrefix "Batch Prefix"BatchUnitField "Batch Unit Field"DocumentsToBeBatched "Documents to be Batched"FamilyField "Family Field"LastErrorReported "Last Error Reported"LastSuccessfulRun "Last Successful Run"MaximumBatchSize "Maximum Batch Size"MinimumBatchSize "Minimum Batch Size"Name "Name"ReviewedField "Reviewed Field"Status "Status"

ClientFieldNames

Page 148: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 148

Property Field NameClientNumber "Client Number"Name "Name"Status "Status"

ChoiceFieldNames

Property Field NameChoiceTypeID "Choice Type ID"HighlightStyleID "Highlight Style ID"Name "Name"ObjectTypeName "Object Type Name"Order "Order"RelativityApplications "Relativity Applications"

DocumentFieldNames

Property Field NameBatch "Batch"Batch_AssignedTo "Batch::Assigned To"Batch_BatchSet "Batch::Batch Set"Batch_Status "Batch::Status"FileIcon "File Icon"FolderName "Folder Name"HasImages "Has Images"HasInlineTags "Has Inline Tags"HasNative "Has Native"RelativityImageCount "Relativity Image Count"RelativityNativeFileLocation "Relativity Native File Location"RelativityNativeTimeZoneOffset "Relativity Native Time Zone Offset"RelativityNativeType "Relativity Native Type"SupportedByViewer "Supported By Viewer"TimeZoneField "Time Zone Field"

ErrorFieldNames

Property Field NameFullError "Full Error"Message "Message"SendNotification "Send Notification"Server "Server"Source "Source"URL "URL"Workspace "Workspace"

FieldFieldNames

Page 149: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 149

Property Field NameAllowGroupBy "AllowGroup By"AllowHTML "AllowHTML"AllowPivot "Allow Pivot"AllowSortTally "Allow Sort/Tally"AssociativeObjectType "Associative Object Type"AutoAddChoices "Auto Add Choices"AvailableInFieldTree "Available In Field Tree"AvailableInViewer "Available In Viewer"Choices "Choices"FieldTreeView "Field Tree View"FieldTypeID "Field Type ID"FilterType "Filter Type"Formatting "Formatting"FriendlyName "Friendly Name"IgnoreWarnings "IgnoreWarnings"ImportBehavior "Import Behavior"IncludeInTextIndex "Include in Text Index"IsIdentifier "Is Identifier"IsRelational "Is Relational"IsRequired "Is Required"KeyboardShortcut "Keyboard Shortcut"Length "Length"Linked "Linked"Name "Name"NoValue "No Value"ObjectType "Object Type"OpenToAssociations "Open to Associations"Order "Pane Order"PaneIcon "Pane Icon"PopupPickerView "Popup Picker View"PropagateTo "Propagate To"RelationalView "Relational View"RelativityApplications "Relativity Applications"Unicode "Unicode"Width "Width"Wrapping "Wrapping"YesValue "Yes Value"

FolderFieldNames

Property Field NameName "Name"

Page 150: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 150

GroupFieldNames

Property Field NameGroupType "Group Type"Name "Name"Users "Users"WorkspaceGroupIDs "Workspace Group IDs"Workspaces "Workspaces"

LayoutFieldNames

Property Field NameName "Name"ObjectType "Object Type"Order "Order"OverwriteProtection "Overwrite Protection"RelativityApplications "Relativity Applications"

MarkupSetFieldNames

Property Field NameName "Name"Order "Order"RedactionText "Redaction Text"

ObjectTypeFieldNames

Property Field NameCopyInstancesOnWorkspaceCreation "Copy Instances On Workspace Creation"DescriptorArtifactTypeID "Descriptor Artifact Type ID"Dynamic "Dynamic"Name "Name"ParentArtifactTypeID "Parent ArtifactTypeID"Pivot "Pivot"RelativityApplications "Relativity Applications"SnapshotAuditingEnabledOnDelete "Snapshot Auditing Enabled On Delete"ViewEnabled "View Enabled"

RDOFieldNames (doesn't extend ArtifactFieldNames)

Property Field NameName "Name"

RelativityApplicationFieldNames

Property Field NameAgentTypes "Agent Types"ApplicationFields "Fields"ApplicationInstallationStatus "Application Installation Status"

Page 151: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 151

Property Field NameApplicationIsDirty "Application Is Dirty"Choices "Choices"CustomPages "Custom Pages"EventHandlers "Event Handlers"LastExported "Last Exported"Layouts "Layouts"Locked "Locked"Name "Name"ObjectRules "Object Rules"ObjectTypes "Object Types"OriginSignature "Origin Signature"RelativityScripts "Relativity Scripts"TabDisplay "Tab Display"Tabs "Tabs"Version "Version"Views "Views"

RelativityScriptFieldNames

Property Field NameBody "Body"Category "Category"Description "Description"Key "Key"Name "Name"RelativityApplications "Relativity Applications"Version "Version"

TabFieldNames

Property Field NameExternalLink "External Link"IsDefault "Is Default"IsVisible "Is Visible"LinkType "Link Type"Name "Name"ObjectType "Object Type"Order "Order"RelativityApplications "Relativity Applications"TabDisplay "Tab Display"

UserFieldNames

Page 152: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 152

Property Field NameAdvancedSearchPublicByDefault "Advanced Search Public By Default"AuthenticationData "Authentication Data"BetaUser "Beta User"ChangePassword "Change Password"ChangePasswordNextLogin "Change Password Next Login"ChangeSettings "Change Settings"Client "Client"DataFocus "Data Focus"DefaultSelectedFileType "Default Selected File Type"DocumentSkip "Document Skip"EmailAddress "Email Address"EnforceViewerCompatibility "Enforce Viewer Compatibility"FirstName "First Name"FullName "Full Name"Groups "Groups"InvalidLoginAttempts "Invalid Login Attempts"ItemListPageLength "Item List Page Length"KeyboardShortcuts "Keyboard Shortcuts"LastName "Last Name"MaximumPasswordAge "Maximum Password Age"NativeViewerCacheAhead "Native Viewer Cache Ahead"Password "Password"PasswordAction "Password Action"PasswordLastResetOn "Password Last Reset On"RelativityAccess "Relativity Access"SendPasswordTo "Send Password To"ShowFilters "Show Filters"SkipDefaultPreference "Skip Default Preference"TrustedIPs "Trusted IPs"Type "Type"Workspaces "Workspaces"WorkspaceUserIDs "Workspace User IDs"

ViewFieldNames

Property Field NameDisplayField "Display Field"GroupDefinitionField "Group Definition Field"IndentationDefinitionField "Indentation Definition Field"IsVisible "Is Visible"Name "Name"ObjectType "Object Type"

Page 153: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 153

Property Field NameOrder "Order"RelativityApplications "Relativity Applications"RenderLinks "Render Links"VisibleInDropdown "Visible In Dropdown"VisualizationType "Visualization Type"

WorkspaceFieldNames

Property Field NameAccessible "Accessible"Client "Client"DatabaseLocation "Database Location"DefaultFileLocation "Default File Location"DownloadHandlerApplicationPath "Download Handler Application Path"MatterID "Matter ID"Name "Name"ResourcePoolID "Resource Pool ID"RootFolderID "Root Folder ID"ServerID "Server ID"SQLFullTextLanguageCodeID "SQL Full Text Language Code ID"Status "Status"

6.8 FolderWithin a Relativity workspace, you can use folders to organize content. For more information, see theRelativity 8.1 Documentation site.The Services API supports perform create,read, delete, and query operations on a Folder DTO.

6.8.1 Creating a FolderYou can use the Create() method on the Folder repository to add a new folder to Relativity as illustrated in thiscode sample.

public static bool Create_Folder_Using_Repository(IRSAPIClient proxy){

//STEP 1: Create a Folder object.DTOs.Folder folder = new DTOs.Folder { ParentArtifact = new DTOs.Artifact(1003697), Name = "My New Folder" };

//STEP 2: Set Folder properties.//STEP 3: Create the Folder.DTOs.WriteResultSet<DTOs.Folder> results;try

Page 154: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 154

{results = proxy.Repositories.Folder.Create(folder);

}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

//STEP 4: Check for success.if (!results.Success){

Console.WriteLine("Error: " + results.Message);return false;

}else{

Console.Write("Folder created successfully.");}return true;

}

6.8.2 Reading a FolderTo read Field values on a Folder, you can use the Read() method on the Folder repository as illustrated in thiscode sample.

public static bool Read_Folder_Using_Repository(IRSAPIClient proxy){

// STEP 1: Read current values.Folder requestArtifact = new Folder(1003697);requestArtifact.Fields.Add(new FieldValue(FolderFieldNames.Name));

ResultSet<Folder> readResult1;

try{

readResult1 = proxy.Repositories.Folder.Read(requestArtifact);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred while reading thefolder: {0}", ex.Message));return false;

}

Page 155: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 155

if (!readResult1.Success){

Console.WriteLine("Error reading the folder: " + readResult1.Message);return false;

}

// STEP 2: Get the folder from the read results.Folder readArtifact = readResult1.Results.FirstOrDefault().Artifact;

if (readArtifact == null){

Console.WriteLine("There is no folder with ArtifactID 1038603");return false;

}else{

Console.WriteLine(String.Format("ArtifactID:{0} ParentArtifactID:{1} -{2}", readArtifact.ArtifactID,

readArtifact.ParentArtifact.ArtifactID, readArtifact.Name));}return true;

}

6.8.3 Deleting a FolderYou can use the Delete() method on a Folder repository to remove it as illustrated in this code sample.

public static bool Delete_Folder_Using_Repository(IRSAPIClient proxy){

// STEP 1: Read current values.DTOs.Folder requestArtifact = new Folder(1036275);

ResultSet<DTOs.Folder> readResult1;

try{

readResult1 = proxy.Repositories.Folder.Read(requestArtifact);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred while reading thefolder: {0}", ex.Message));return false;

}

Page 156: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 156

if (!readResult1.Success){

Console.WriteLine("Error reading the folder: " + readResult1.Message);return false;

}

// STEP 2: Get the folder from the read results.DTOs.Folder readArtifact = readResult1.Results.FirstOrDefault().Artifact;if (readArtifact == null){

Console.WriteLine("There is no folder with ArtifactID 1037993");return false;

}// STEP 3: Delete the folder.WriteResultSet<DTOs.Folder> deleteResult;

try{

deleteResult = proxy.Repositories.Folder.Delete(requestArtifact);}catch (Exception ex){

Console.WriteLine("An error occurred deleting the folder: {0}",ex.Message);return false;

}

if (!deleteResult.Success){

Console.WriteLine("Error deleting the folder: " + deleteResult.Message);return false;

}// STEP 4: To confirm the deletion, try to find the folder again.// Since the folder doesn't exist, the read operation fails.(ResultSet.Success is set to false).// You can query for the folder's ArtifactID. The result is Success with 0results.WholeNumberCondition artifactIDCondition =

new WholeNumberCondition(ArtifactQueryFieldNames.ArtifactID,NumericConditionEnum.EqualTo, 1037993);

DTOs.Query<DTOs.Folder> query = new DTOs.Query<DTOs.Folder>{

Condition = artifactIDCondition};

Page 157: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 157

QueryResultSet<DTOs.Folder> queryResult;

try{

queryResult = proxy.Repositories.Folder.Query(query);}catch (Exception ex){

Console.WriteLine("An error occurred querying the folder after it wasdeleted: {0}", ex.Message);return false;

}

if (queryResult.Success){

if (queryResult.Results.Count == 0)Console.WriteLine("Delete succeeded, the folder has been deleted");

}else{

Console.WriteLine("Error querying the folder after deletion: " +queryResult.Message);return false;

}return true;

}

6.8.4 Querying for a FolderTo query for a Folder, you can use the fields listed in the following table. For more information, see Queryingon page 227.

Fields for Folder queriesArtifact ID System Created ByName System Created OnParent Artifact ID System Last Modified ByParent Artifact Name System Last Modified On

The following sample code illustrates how to query for Folder DTOs using a repository.

public static bool Query_Folder_Using_Repository(IRSAPIClient proxy){

// STEP 1: Create the query.Query<Folder> query = new Query<kCura.Relativity.Client.DTOs.Folder>();query.Fields.Add(new FieldValue(FolderFieldNames.Name));

Page 158: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 158

ResultSet<Folder> readResult1;

// STEP 2: Query for the folders.try{

readResult1 = proxy.Repositories.Folder.Query(query);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred while querying for thefolder: {0}", ex.Message));return false;

}

if (!readResult1.Success){

Console.WriteLine("Error reading the folder: " + readResult1.Message);return false;

}

// STEP 3: Use the results.foreach (Result<Folder> folder in readResult1.Results){

Console.WriteLine(String.Format("ArtifactID:{0} ParentArtifactID:{1} -{2}",

folder.Artifact.ArtifactID, folder.Artifact.ParentArtifact.ArtifactID,folder.Artifact.Name));

}return true;

}

6.9 GroupWithin Relativity, you can use groups to organize users. You can then assign a specific set of permissions toeach group. For more information, see Groups in the Relativity 8.1 Documentation site.The Services API supports create, read, delete, and query operations on a Group DTO.

6.9.1 Creating a GroupYou can add a Group to Relativity by calling the Create() method on the Group repository as illustrated in thiscode sample. See Fields used by Group and User objects on page 144.

public static bool Create_Group(IRSAPIClient proxy){

// STEP 1: Create a DTO and set its properties.

Page 159: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 159

DTOs.Group newGroup = new DTOs.Group();newGroup.Name = "Sample Group";

// STEP 2: Create a WriteResultSet. It provide details after the createoperation completes.WriteResultSet<DTOs.Group> resultSet = new WriteResultSet<DTOs.Group>();

// STEP 3: Create the new Group.try{

resultSet = proxy.Repositories.Group.Create(newGroup);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

// Check for success.if (!resultSet.Success){

Console.WriteLine("The Create operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

}

// Output the results.Console.WriteLine("The Create succeeded.");DTOs.Group createdGroup = resultSet.Results[0].Artifact;

Console.WriteLine("{0}The Artifact of the New Group is: {1}",Environment.NewLine, createdGroup.ArtifactID);// Console.WriteLine("The name of the Group is: {0}",createdGroup.GroupName);

return true;}

6.9.2 Reading a GroupTo read Field values, you can use the Read() method on the Group repository as illustrated in this codesample.

public static bool Read_Group(IRSAPIClient proxy){

Page 160: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 160

// STEP 1: Create a DTO with criteria you want to read.DTOs.Group groupToRead = new DTOs.Group(1016219);groupToRead.Fields = FieldValue.AllFields;

// STEP 2: Create ResultSet to store Results.ResultSet<DTOs.Group> resultSet = new ResultSet<DTOs.Group>();

// STEP 3: Perform the read operation.try{

resultSet = proxy.Repositories.Group.Read(groupToRead);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

// Check for success.if (!resultSet.Success){

Console.WriteLine("The Read operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

}

// Output the results.Console.WriteLine("Read completed successfully.");DTOs.Group readGroup = resultSet.Results[0].Artifact;SampleHelpers.APIHelpers.Print_All_Properties(readGroup);

return true;}

6.9.3 Updating a GroupYou can use the Update() on the Group repository to modify its properties as illustrated in this code sample.See Fields used by Group and User objects on page 144.

public static bool Update_Group(IRSAPIClient proxy){

// STEP 1: Create DTO, and set its properties.DTOs.Group newGroup = new DTOs.Group(1016219);newGroup.Name = "Sample Group";

Page 161: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 161

// STEP 2: Create a WriteResultSet. It provides details after the updateoperation.WriteResultSet<DTOs.Group> resultSet = new WriteResultSet<DTOs.Group>();

// STEP 3: Perform the update operation.try{

resultSet = proxy.Repositories.Group.Update(newGroup);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

// Check for success.if (!resultSet.Success){

Console.WriteLine("The Update operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

}

Console.WriteLine("Updated completed successfully.");DTOs.Group updatedGroup = resultSet.Results[0].Artifact;// Console.WriteLine("The updated name of the Group is: {0}",updatedGroup.GroupName);

return true;}

6.9.4 Deleting a GroupYou can remove a Group from Relativity by calling the Delete() method on the Group repository as illustratedin this code sample.

public static bool Delete_Group(IRSAPIClient proxy){

// STEP 1: Create a DTO populated with criteria for a DTO you want todelete.DTOs.Group groupToDelete = new DTOs.Group(1016219);

// STEP 2: Create a WriteResultSet. It provides details after the deleteoperation completes.WriteResultSet<DTOs.Group> resultSet = new WriteResultSet<DTOs.Group>();

Page 162: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 162

// STEP 3: Perform the delete operation.try{

resultSet = proxy.Repositories.Group.Delete(groupToDelete);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

// Check for success.if (!resultSet.Success){

Console.WriteLine("The Delete operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

}

// Output the results.Console.WriteLine("Delete completed successfully.");DTOs.Group deletedGroup = resultSet.Results.ElementAt(0).Artifact;Console.WriteLine("The Artifact ID of the deleted Group is: {0}",deletedGroup.ArtifactID);

return true;}

6.9.5 Querying for a GroupThis code sample illustrates how to set query conditions, call the Query() method on the Group repository,and iterate through the result set.

public static bool Query_Group(IRSAPIClient proxy){

// STEP 1: Create a Query and ObjectsCondition. It provides details afterthe query operation.ObjectsCondition workspaceCondition =

new ObjectsCondition("Workspaces", ObjectsConditionEnum.AnyOfThese, newInt32[] { 1016204 });

Query<DTOs.Group> query = new DTOs.Query<DTOs.Group> { Condition =workspaceCondition };query.Fields = FieldValue.AllFields;

Page 163: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 163

// STEP 2: Create QueryResultSet to collect information about the DTO afterthe query completes.QueryResultSet<DTOs.Group> resultSet = new QueryResultSet<DTOs.Group>();

// STEP 3: Perform the query.try{

resultSet = proxy.Repositories.Group.Query(query, 0);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

// Check for success.if (!resultSet.Success){

Console.WriteLine("The Query operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

}

// Output the results.Console.WriteLine(string.Format("Number of Groups returned: {0}",resultSet.Results.Count));

foreach (DTOs.Result<DTOs.Group> groupResult in resultSet.Results){

Console.WriteLine(string.Format("{0}Name:{1}", Environment.NewLine,groupResult.Artifact.Name));Console.WriteLine(string.Format("ArtifactID:{0}",groupResult.Artifact.ArtifactID));

}

return true;}

6.10 LayoutIn Relativity, layouts are web-based coding forms that enable users to view and edit document fields. Formore information, see Layouts in the Relativity 8.1 Documentation site.The Services API supports read and query operations on a Layout DTO.

Page 164: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 164

6.10.1 Reading a LayoutTo read Field values on a Layout, you can use the Read() method on the Layout repository as illustrated in thiscode sample.

public static bool Read_Layout_Using_Repository(IRSAPIClient proxy){

//STEP 1: Create a Layout DTO for the Layout to be read.DTOs.Layout layoutDTO = new DTOs.Layout(1036682);layoutDTO.Fields = FieldValue.AllFields;ResultSet<DTOs.Layout> layoutReadResults = new ResultSet<DTOs.Layout>();

//STEP 2: Try to read the Layout.try{

layoutReadResults = proxy.Repositories.Layout.Read(layoutDTO);}catch (Exception ex){

Console.WriteLine("An error occurred reading the layout: {0}",ex.Message);return false;

}

//STEP 3: Check for success.if (!layoutReadResults.Success){

Console.WriteLine("An error occurred reading the layout: {0}",layoutReadResults.Message);

foreach (Result<DTOs.Layout> readResult in layoutReadResults.Results){

if (!readResult.Success){

Console.WriteLine(" An error occurred in read request: {0}",readResult.Message);

}}return false;

}//STEP 4: Output the name.Console.WriteLine("Successfully read the layout '{0}'!",layoutReadResults.Results[0].Artifact.Name);

return true;}

Page 165: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 165

6.10.2 Querying for a LayoutTo query for a Layout, you can use the fields listed in the following table. For more information, see Queryingon page 227.

Fields for Layout queriesArtifactID NotesCreated By Object TypeCreated By Order in DropdownKeywords Overwrite ProtectionLast Modified By OwnersLast Modified On Relativity ApplicationsName Security

This code sample illustrates how to set query conditions, call the Query() method on the Layout repository,and iterate through the result set.

public static bool Query_Layout_Using_Repository(IRSAPIClient proxy){

//STEP 1: Create the query criteria.ObjectsCondition relAppCondition =

new ObjectsCondition("Relativity Applications",ObjectsConditionEnum.AllOfThese, new int[] { 1035699 });

Query<DTOs.Layout> layoutQuery = new Query<DTOs.Layout>{

Condition = relAppCondition,Fields = FieldValue.AllFields

};

//STEP 2: Try to query for the Layout.QueryResultSet<DTOs.Layout> layoutQueryResults = null;

try{

layoutQueryResults = proxy.Repositories.Layout.Query(layoutQuery);}catch (Exception ex){

Console.WriteLine("An error occurred querying for layouts: {0}",ex.Message);return false;

}

//STEP 3: Check for success.if (!layoutQueryResults.Success)

Page 166: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 166

{Console.WriteLine("An error occurred querying for layouts: {0}",layoutQueryResults.Message);return false;

}

//STEP 4: Display the results.Console.WriteLine("Number of layouts returned: {0}",layoutQueryResults.Results.Count);

foreach (Result<DTOs.Layout> layoutResult in layoutQueryResults.Results){

DTOs.Layout curLayout = layoutResult.Artifact;Console.WriteLine("Layout Name: {0}", curLayout.TextIdentifier);Console.WriteLine("Layout ArtifactID: {0}", curLayout.ArtifactID);

}return true;

}

6.11 MarkupSetIn Relativity, markup sets are securable highlights and redactions available to reviewers. For moreinformation, seeMarkup sets in the Relativity 8.1 Documentation site.The Services API supports all CRUD and query operations on a MarkupSet DTO.

6.11.1 Creating a MarkupSetYou can add aMarkupSet to Relativity by calling the Create() method on theMarkupSet repository asillustrated in this code sample.

public static bool Create_MarkupSet_Using_Repository(IRSAPIClient proxy){

// STEP 1: Create a MarkupSet DTO and populate the fields.DTOs.MarkupSet markupSetDTO = new DTOs.MarkupSet();markupSetDTO.Name = "New Markup Set";markupSetDTO.Order = 10;markupSetDTO.RedactionText =

new List<String>(new string[] {"Each", "string", "here", "is", "on", "a","new", "line."});

// STEP 2: Call the Create() method on the repository and pass in the DTO.DTOs.WriteResultSet<DTOs.MarkupSet> createResults;try{

createResults = proxy.Repositories.MarkupSet.Create(markupSetDTO);

Page 167: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 167

}catch (Exception ex){

Console.WriteLine("An error occurred creating the Markup Set: {0}",ex.Message);return false;

}

// STEP 3: Check for success.if (!createResults.Success){

Console.WriteLine("An error occurred creating the Markup Set: {0}",createResults.Results[0].Message);return false;

}else{

Console.WriteLine("Successfully created Markup Set '{0}'!",markupSetDTO.Name);

}

return true;}

6.11.2 Reading a MarkupSetTo read Field values, you can use the Read() method on theMarkupSet repository as illustrated in this codesample.

public static bool Read_MarkupSet_Using_Repository(IRSAPIClient proxy){

// STEP 1: Create the MarkupSet DTO.kCura.Relativity.Client.DTOs.MarkupSet markupSet = newkCura.Relativity.Client.DTOs.MarkupSet(1039144);markupSet.Fields = kCura.Relativity.Client.DTOs.FieldValue.AllFields;

// STEP 2: Read the MarkupSet DTO from the repository.kCura.Relativity.Client.DTOs.ResultSet<kCura.Relativity.Client.DTOs.MarkupSet> resultSet;

try{

resultSet = proxy.Repositories.MarkupSet.Read(markupSet);}catch (Exception ex)

Page 168: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 168

{Console.WriteLine("An error occurred reading the MarkupSet: {0}",ex.Message);return false;

}

// STEP 3: Check for success.if (!resultSet.Success){

Console.WriteLine("An error occurred reading the MarkupSet: {0}",resultSet.Message);return false;

}kCura.Relativity.Client.DTOs.MarkupSet markupSetResult =resultSet.Results.FirstOrDefault().Artifact;Console.WriteLine("MarkupSet Name: {0}", markupSetResult.Name);

return true;}

6.11.3 Updating a MarkupSetYou can use the Update() on theMarkupSet repository to modify its properties as illustrated in this codesample.

public static bool Update_MarkupSet_Using_Repository(IRSAPIClient proxy){

// STEP 1: Create the MarkupSet DTO.kCura.Relativity.Client.DTOs.MarkupSet markupSet = newkCura.Relativity.Client.DTOs.MarkupSet(1039144);markupSet.Fields = kCura.Relativity.Client.DTOs.FieldValue.AllFields;

// STEP 2: Read the MarkupSet DTO from the repository.kCura.Relativity.Client.DTOs.ResultSet<kCura.Relativity.Client.DTOs.MarkupSet> resultSet;

try{

resultSet = proxy.Repositories.MarkupSet.Read(markupSet);}catch (Exception ex){

Console.WriteLine("An error occurred reading the MarkupSet: {0}",ex.Message);return false;

Page 169: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 169

}

// STEP 3: Check for success.if (!resultSet.Success){

Console.WriteLine("An error occurred reading the MarkupSet: {0}",resultSet.Message);return false;

}

kCura.Relativity.Client.DTOs.MarkupSet markupSetResult =resultSet.Results.FirstOrDefault().Artifact;Console.WriteLine("MarkupSet Name: {0}", markupSetResult.Name);

// STEP 4: Update the DTO in the repository.markupSetResult.Name = "Updated Markup Set";markupSetResult.Order = 20;markupSetResult.RedactionText.Add("New Markup Text");kCura.Relativity.Client.DTOs.ResultSet<kCura.Relativity.Client.DTOs.MarkupSet> updatedResultSet;

try{

updatedResultSet = proxy.Repositories.MarkupSet.Update(markupSetResult);}catch (Exception ex){

Console.WriteLine("An error occurred Updating the MarkupSet: {0}",ex.Message);return false;

}

// STEP 5: Check for success.if (!updatedResultSet.Success){

Console.WriteLine("An error occurred Updating the MarkupSet: {0}",updatedResultSet.Message);return false;

}return true;

}

6.11.4 Deleting a MarkupSetYou can remove a MarkupSet from Relativity by calling the Delete() method on theMarkupSet repository asillustrated in this code sample.

Page 170: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 170

public static bool Delete_MarkupSet_Using_Repository(IRSAPIClient proxy){

// STEP 1: Create the MarkupSet DTO.kCura.Relativity.Client.DTOs.MarkupSet markupSet = newkCura.Relativity.Client.DTOs.MarkupSet(1039144);

// STEP 2: Delete the MarkupSet from the repository.kCura.Relativity.Client.DTOs.ResultSet<kCura.Relativity.Client.DTOs.MarkupSet> resultSet;

try{

resultSet = proxy.Repositories.MarkupSet.Delete(markupSet);}catch (Exception ex){

Console.WriteLine("An error occurred deleting the MarkupSet: {0}",ex.Message);return false;

}

// STEP 3: Check for success.if (!resultSet.Success){

Console.WriteLine("An error occurred deleting the MarkupSet: {0}",resultSet.Message);return false;

}return true;

}

6.11.5 Querying for a MarkupSetTo query for a MarkupSet, you can use the fields listed in the following table. For more information, seeQuerying on page 227.

Fields for MarkupSet queriesArtifact ID Last Modified OnCreated By NotesCreated On OrderNameKeywords

Redaction Text – returned as List<string> to accommodatemultiplevalues.

Last Modified By Security

This code sample illustrates how to set query conditions, call the Query() method on theMarkupSetrepository, and iterate through the result set.

Page 171: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 171

public static bool Query_MarkupSet_Using_Repository(IRSAPIClient proxy){

// STEP 1: Create the query criteria.DTOs.Query<DTOs.MarkupSet> markupSetQuery = new DTOs.Query<DTOs.MarkupSet>();

List<String> desiredRedactionText =new List<string>(new string[] { "Each", "string", "here", "is", "on","a", "new", "line." });

markupSetQuery.Condition = new MultiLineStringCondition(DTOs.MarkupSetFieldNames.RedactionText, TextConditionEnum.EqualTo,desiredRedactionText);markupSetQuery.Fields = DTOs.FieldValue.AllFields;

// STEP 2: Call the Query() method on the repository.DTOs.QueryResultSet<DTOs.MarkupSet> queryResults;try{

queryResults = proxy.Repositories.MarkupSet.Query(markupSetQuery);}catch (Exception ex){

Console.WriteLine("An error occurred querying for the MarkupSet: {0}",ex.Message);return false;

}

// STEP 3: Check for success.if (!queryResults.Success){

Console.WriteLine("An error occurred querying for the MarkupSet: {0}",queryResults.Message);return false;

}else{

Console.WriteLine("Query returned {0} MarkupSets!",queryResults.Results.Count);

foreach (DTOs.Result<DTOs.MarkupSet> markupSetResult inqueryResults.Results){

Console.WriteLine("MarkupSet Name: {0}",markupSetResult.Artifact.Name);

Page 172: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 172

}}

return true;}

6.12 ObjectTypeAn ObjectType is Relativity Dynamic Object (RDO) type that you add to a workspace. It is synonymous withArtifactType. For more information, see Object type details in the Relativity 8.1 Documentation site.The Services API supports all CRUD and query operations on a ObjectType DTO.

6.12.1 Creating an ObjectTypeYou can add an ObjectType to Relativity by calling the Create() method on the ObjectType repository asillustrated in this code sample.

public static bool Create_ObjectType_Using_Repository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = 1016204;

// STEP 1: Create an ObjectType DTO and populate the Fields.DTOs.ObjectType objectTypeDTO = new DTOs.ObjectType();

objectTypeDTO.Name = "New Object Type";objectTypeDTO.ParentArtifactTypeID = 8;objectTypeDTO.SnapshotAuditingEnabledOnDelete = true;objectTypeDTO.Pivot = true;objectTypeDTO.CopyInstancesOnWorkspaceCreation = false;objectTypeDTO.Sampling = true;objectTypeDTO.PersistentLists = false;objectTypeDTO.RelativityApplications =

new List<DTOs.RelativityApplication> { new DTOs.RelativityApplication(1037990),

new DTOs.RelativityApplication(1037639) };

// STEP 2: Call the Create method on the repository, passing the DTO.WriteResultSet<DTOs.ObjectType> resultSet;try {

resultSet = proxy.Repositories.ObjectType.Create(objectTypeDTO);}catch (Exception ex) {

Console.WriteLine("Error: " + ex.Message);return false;

}

Page 173: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 173

if (!resultSet.Success) {Console.WriteLine("Error: " + resultSet.Message);foreach (Result<DTOs.ObjectType> result in resultSet.Results) {

Console.WriteLine("Result Error: " + result.Message);}return false;

}

Console.WriteLine("Overall status of creating an object type: " +resultSet.Success);Console.WriteLine("New Artifact ID: " + resultSet.Results.FirstOrDefault().Artifact.ArtifactID);

return true;}

6.12.2 Reading an ObjectTypeTo read Field values, you can use the Read() method on the ObjectType repository as illustrated in this codesample.

public static bool Read_ObjectType_Using_Repository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = 1016204;

// STEP 1: Call the Read() method on the ObjectType repository and pass anObjectType DTO.ResultSet<DTOs.ObjectType> results;try {

results =proxy.Repositories.ObjectType.Read(new DTOs.ObjectType(1036210) { Fields = FieldValue.AllFields });

}catch (Exception ex) {

Console.WriteLine("Error: " + ex.Message);return false;

}

if (!results.Success) {Console.WriteLine("Error: " + results.Message);

foreach (Result<DTOs.ObjectType> result in results.Results){

Console.WriteLine("Result Error: " + result.Message);

Page 174: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 174

}return false;

}

// STEP 2: Get the Object Type artifact from the read results.DTOs.ObjectType objectTypeArtifact = results.Results.FirstOrDefault().Artifact;

Console.WriteLine("Object Type Artifact ID: " +objectTypeArtifact.ArtifactID);Console.WriteLine("Object Type Name: " + objectTypeArtifact.Name);Console.WriteLine("Object Type Artifact Type ID: " +objectTypeArtifact.DescriptorArtifactTypeID);

return true;}

6.12.3 Updating an ObjectTypeYou can use the Update() method on the ObjectType repository to modify its properties as illustrated in thiscode sample.

public static bool Update_ObjectType_Using_Repository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = 1016204;

// STEP 1: Create an ObjectType DTO and populate the Fields you want toupdate.DTOs.ObjectType objectTypeDTO = new DTOs.ObjectType(1035966);objectTypeDTO.Name = "Renamed Object Type";

// STEP 2: Call the Update() method on the repository and pass the DTO.WriteResultSet<DTOs.ObjectType> resultSet;try {

resultSet = proxy.Repositories.ObjectType.Update(objectTypeDTO);}catch (Exception ex) {

Console.WriteLine("Error: " + ex.Message);return false;

}

if (!resultSet.Success) {Console.WriteLine("Error: " + resultSet.Message);

foreach (Result<DTOs.ObjectType> result in resultSet.Results) {

Page 175: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 175

Console.WriteLine("Result Error: " + result.Message);}return false;

}

Console.WriteLine("Overall status of Updating an object type: " +resultSet.Success);

// STEP 3: Read back the Artifact for verification.ResultSet<DTOs.ObjectType> readResult;try {

readResult = proxy.Repositories.ObjectType.Read(objectTypeDTO);}catch (Exception ex) {

Console.WriteLine("Error: " + ex.Message);return false;

}

if (!readResult.Success) {Console.WriteLine("Error: " + readResult.Message);foreach (Result<DTOs.ObjectType> result in resultSet.Results) {

Console.WriteLine("Result Error: " + result.Message);}return false;

}

Console.WriteLine("Updated Object Type Name: " +readResult.Results.FirstOrDefault().Artifact.Name);

return true;}

6.12.4 Deleting an ObjectTypeYou can remove an ObjectType from Relativity by calling the Delete() method on the ObjectType repository asillustrated in this code sample.

public static bool Delete_ObjectType_Using_Repository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = 1016204;

// STEP 1: Call the delete method on the ArtifactType Repository, passingthe ObjectType DTO.ResultSet<DTOs.ObjectType> results;try {

Page 176: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 176

results = proxy.Repositories.ObjectType.Delete(new DTOs.ObjectType(1038017));

}catch (Exception ex) {

Console.WriteLine("Error: " + ex.Message);return false;

}

if (results.Success)Console.WriteLine("Status of Delete: " + results.Success);

elseConsole.WriteLine("Error deleting object type: " + results.Results[0].Message);

return true;}

6.12.5 Querying for an ObjectTypeThis code sample illustrates how to set query conditions, call the Query() method on the ObjectTyperepository, and iterate through the result set.

public static bool Query_ObjectType_Using_Repository(IRSAPIClient proxy){

// STEP 1: Setup your query criteria.TextCondition criteria =

new TextCondition(kCura.Relativity.Client.DTOs.ObjectTypeFieldNames.Name,TextConditionEnum.EqualTo,

"Employees");

Query<DTOs.ObjectType> query = new Query<DTOs.ObjectType>{

Condition = criteria,Fields = FieldValue.AllFields

};

// STEP 2: Call the Query() method in the ObjectType repository.QueryResultSet<DTOs.ObjectType> result = new QueryResultSet<DTOs.ObjectType>();try {

result = proxy.Repositories.ObjectType.Query(query, 0);}catch (Exception ex) {

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

Page 177: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 177

}

Console.WriteLine(string.Format("Number of documents returned: {0}",result.TotalCount));Console.WriteLine(string.Format("Additional Pages of Query ResultsAvailable?: {0}",

!string.IsNullOrEmpty(result.QueryToken)));

// STEP 3: Iterate over the returned ObjectType result.foreach (DTOs.Result<DTOs.ObjectType> objTypeResult in result.Results) {

DTOs.ObjectType objType = objTypeResult.Artifact;Console.WriteLine("Object Type Name: " + objTypeResult.Artifact.Name);Console.WriteLine("Object Type Artifact Type ID: " +objTypeResult.Artifact.DescriptorArtifactTypeID);

}

return true;}

6.13 RDOA Relativity Dynamic Object (RDO) is custom object that you create in a workspace. It has a uniqueArtifactTypeID in the workspace where it is created. For more information, see Relativity objects in theRelativity 8.1 Documentation site.The Services API supports all CRUD and query operations on an RDO.

6.13.1 Creating an RDOYou can add an RDO to Relativity by calling the Create() method on the RDO repository. This code sample useGUIDs to reference Fields, but you can also reference Fields by their names or ArtifactIDs. See GUIDs inapplication development on page 78.

public void Create_an_RDO_UsingGUIDs(){

try{

using (IRSAPIClient proxy =new RSAPIClient(new Uri("net.pipe://localhost/Relativity.Services"),new IntegratedAuthCredentials()))

{proxy.APIOptions.WorkspaceID = WORKSPACE_ID;

// STEP 1: Create an RDO DTO and set the ArtifactTypeGuids.var dto = new RDO();

Page 178: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 178

dto.ArtifactTypeGuids.Add(new Guid("EE5BD2B1-47A8-45CE-AA5B-2115B6DD86A4"));

// STEP 2: Add FieldValues to the Fields collection. Specify the GUID// of the Field that you want to set. Set the FixedLengthText fields.dto.Fields.Add(new FieldValue(new Guid("37159592-B5B6-4405-AF74-10B5728890B4"), "Smith"));dto.Fields.Add(new FieldValue(new Guid("3BDC0971-A87C-414E-9A37-FC477279BBAD"), "Joe"));

// Set a SingleChoice Type field to a Choice using the GUID thatrepresents// the Choice artifact.dto.Fields.Add(new FieldValue(new Guid("4F06AC67-822A-414F-B6C1-5D4007E998EF"), new kCura.Relativity.Client.DTOs.Choice(new Guid("4501A308-5E68-4314-AEDC-4DEB527F12A8"))));

// Set A MultiChoice field by creating a MultiChoiceFieldValueList asits value.// The MultiChoiceFieldValueList contains Choice DTOs, which are setusing GUIDs that represent// the Choice artifact.var multiChoices =new MultiChoiceFieldValueList(new kCura.Relativity.Client.DTOs.Choice(new Guid("6A1D5E35-B4B3-4962-9EEB-6E6D3016D40C")),new kCura.Relativity.Client.DTOs.Choice(new Guid("E647DF05-2E51-41E7-B6A3-C3F1CD723C54")));

// Set the UpdateBehavior depending on whether you want to Merge orReplace the new values.multiChoices.UpdateBehavior = MultiChoiceUpdateBehavior.Replace;

// Set the MultiChoice field using its GUID and set the value to theMultiChoiceFieldValueList.dto.Fields.Add(new FieldValue(new Guid("C9D1C1E7-61B1-46EE-A35D-406FC9503DE5"), multiChoices));

// Set a User field to a User DTO.dto.Fields.Add(new FieldValue(new Guid("C1A2DB49-3282-40CF-84A0-8DEEB4E76764"),

new kCura.Relativity.Client.DTOs.User(1015411)));

// Set a SingleObject to a DTO for the object. In this example, aSingleObject Field takes a Document.var obj = new kCura.Relativity.Client.DTOs.Document(1038372);

Page 179: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 179

dto.Fields.Add(new FieldValue(new Guid("68094937-3E3A-42D4-B71B-132C8A4C51F7"), obj));

// Set a MultiObject to a FieldValueList of the Type of objects. Inthis example, a MultiObject Field takes instances of RDOs.FieldValueList<RDO> objects = new FieldValueList<RDO>();objects.Add(new RDO(1067600));objects.Add(new RDO(1067613));dto.Fields.Add(new FieldValue(new Guid("467D2CDE-7892-4463-9890-805B937E3945"), objects));

// STEP 3: Call the Create() method on the RDO Respository.WriteResultSet<RDO> writeResults = proxy.Repositories.RDO.Create(dto);

if (writeResults.Success){

Console.WriteLine(string.Format("Object was created with ArtifactID {0}.", writeResults.Results[0].Artifact.ArtifactID));

}else{

Console.WriteLine(string.Format("An error occurred creating object:{0}", writeResults.Message));

for (Int32 i = 0; i <= writeResults.Results.Count - 1; i++){

if (!writeResults.Results[i].Success){Console.WriteLine(String.Format("An error occurred in create request {0}: {1}", i, writeResults.Results[i].Message));}

}}

}}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));}

}

6.13.2 Creating an RDO as a child objectYou can create an RDO that is a child of another object other than Workspace. You must set the ParentArtifactproperty of the child object to the DTO Artifact of its parent object as illustrated in this code sample.

Page 180: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 180

// Create an instance of the parent object with ArtifactTypeName “ParentObj”.var rdo = new RDO("ParentObj");rdo.TextIdentifier = "Test Parent Object";var parentCreate = proxy.Repositories.RDO.Create(rdo);

// Create an instance of the child object with ArtifactTypeName “ChildObj”// and set the ParentArtifact to the parent object instance previously created.var childRDO = new RDO("ChildObj");childRDO.TextIdentifier = "Child of Test Parent Object";childRDO.ParentArtifact =

new kCura.Relativity.Client.DTOs.Artifact(parentCreate.Results[0].Artifact.ArtifactID);

var childCreate = proxy.Repositories.RDO.Create(childRDO);

6.13.3 Reading an RDOTo read Field values, you can use the Read() method on the RDO repository as illustrated in this code sample.

public void Read_an_RDO_Using_Repository2(){

try{

using (IRSAPIClient proxy =new RSAPIClient(new Uri("net.pipe://localhost/Relativity.Services"),new IntegratedAuthCredentials()))

{proxy.APIOptions.WorkspaceID = WORKSPACE_ID;

// STEP 1: Call the Read() method on the RDO repository.RDO employee = new RDO(1067694);employee.ArtifactTypeID = 1000030;employee.Fields = FieldValue.AllFields;ResultSet<RDO> results = new ResultSet<RDO>();results = proxy.Repositories.RDO.Read(employee);

//Check for success.if (!results.Success){

Console.WriteLine("An error occurred!");Console.WriteLine(results.Message);

}else{

Console.WriteLine(string.Format("An error occurred reading object:{0}", results.Message));

Page 181: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 181

for (Int32 i = 0; i <= results.Results.Count - 1; i++){

if (!results.Results[i].Success){Console.WriteLine(String.Format("An error occurred in read request {0}: {1}", i,results.Results[i].Message));}

}}// STEP 2: Get the Artifact from the read results.employee = results.Results.Single().Artifact;FieldValue lastNameField = employee["Last Name"];FieldValue employmentLevelField = employee["Employment Level"];FieldValue hrRepField = employee["HR Rep"];FieldValue skillsInventoryField = employee["Skills Inventory"];FieldValue keyDocumentField = employee["Key Document"];FieldValue favoriteDocumentsField = employee["Favorite Documents"];

Console.WriteLine("Artifact: {0} Field: {1} Value: {2}",employee.ArtifactID, lastNameField.Name,lastNameField.ValueAsFixedLengthText);

// The SingleChoice field returns a Choice DTO.Console.WriteLine("Artifact: {0} Field: {1} Value: {2}",employee.ArtifactID, employmentLevelField.Name,employmentLevelField.ValueAsSingleChoice.ArtifactID);

// The MultipleChoice field returns a MultiChoiceFieldValueListcontaining a List of Choice DTOs.MultiChoiceFieldValueList multiChoiceList =

skillsInventoryField.ValueAsMultipleChoice;

for (int index = 0; index < multiChoiceList.Count; index++){

kCura.Relativity.Client.DTOs.Choice choice = multiChoiceList[index];

Console.WriteLine("Artifact: {0} Field: {1} Value: {2}",employee.ArtifactID, skillsInventoryField.Name + " " + "Choice " +index, choice.ArtifactID);

}// The User field returns a User DTO.

Page 182: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 182

Console.WriteLine("Artifact: {0} Field: {1} Value: {2}",employee.ArtifactID, hrRepField.Name,hrRepField.ValueAsUser.ArtifactID + " - " +hrRepField.ValueAsUser.FullName);

// The SingleObject field is returned as an Artifact DTO.kCura.Relativity.Client.DTOs.Artifact documentArtifact =keyDocumentField.ValueAsSingleObject;Console.WriteLine("Artifact: {0} Field: {1} Value: {2}",employee.ArtifactID,

keyDocumentField.Name, documentArtifact.ArtifactID);

// The MultipleObject field is returned as FieldValueList<Artifact>.FieldValueList<kCura.Relativity.Client.DTOs.Artifact> multiObject =

favoriteDocumentsField.GetValueAsMultipleObject<kCura.Relativity.Client.DTOs.Artifact>();

for (int index = 0; index < multiObject.Count; index++){

Int32 id = multiObject[index].ArtifactID;Console.WriteLine("Artifact: {0} Field: {1} Value: {2}",employee.ArtifactID,

favoriteDocumentsField.Name + " Object " + index, id);}

}}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));}

}

6.13.4 Updating an RDOYou can use the Update() method on an RDO repository to modify its properties as illustrated in this codesample.

public void Update_RDO_Using_Repository(){

try{

using (IRSAPIClient proxy =new RSAPIClient(new Uri("net.pipe://localhost/Relativity.Services"),new IntegratedAuthCredentials()))

{

Page 183: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 183

proxy.APIOptions.WorkspaceID = WORKSPACE_ID;

// STEP 1: Create an RDO DTO and add the FieldValue that you want toupdate.RDO artifact = new RDO("Employees", 1067694);artifact.Fields.Add(new FieldValue() {Name = "Last Name", Value ="Smith, Jr."});

// STEP 2: Call the Update() method on the RDO respository.WriteResultSet<RDO> writeResultSet = proxy.Repositories.RDO.Update(artifact);

if (!writeResultSet.Success){

Console.WriteLine("Error: " + writeResultSet.Message);

for (Int32 i = 0; i <= writeResultSet.Results.Count - 1; i++){

if (!writeResultSet.Results[i].Success){Console.WriteLine(String.Format("An error occurred in update request {0}: {1}", i, writeResultSet.Results[i].Message));}

}}

}}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));}

}

6.13.5 Deleting an RDOYou can remove an RDO from Relativity by calling the Delete() method on the RDO repository as illustrated inthis code sample.

public void Delete_RDO(){

using (IRSAPIClient proxy =new RSAPIClient(new Uri("net.pipe://localhost/Relativity.Services"), newIntegratedAuthCredentials()))

{

Page 184: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 184

try{

proxy.APIOptions.WorkspaceID = WORKSPACE_ID;

//Step 1: Create a DTO for an instance of the "Employees" RDO.var dtoToDelete = new RDO("Employees", 1067605);

//Step 2: Call Delete on the RDO Repository and pass the RDO DTO.WriteResultSet<RDO> deleteResult = proxy.Repositories.RDO.Delete(dtoToDelete);

if (!deleteResult.Success){

Console.WriteLine("Error deleting the object: " +deleteResult.Message);

for (Int32 i = 0; i <= deleteResult.Results.Count - 1; i++){

if (!deleteResult.Results[i].Success){Console.WriteLine(String.Format("An error occurred in delete request {0}: {1}", i,deleteResult.Results[i].Message));}

}}

}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}",ex.Message));

}}

}

6.13.6 Querying for an RDOThis code sample illustrates how to set query conditions, call the Query() method on the RDO repository, anditerate through the result set.

public void Query_an_RDO_Using_Repository(){

using (IRSAPIClient proxy =new RSAPIClient(new Uri("net.pipe://localhost/Relativity.Services"), newIntegratedAuthCredentials()))

Page 185: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 185

{try{

proxy.APIOptions.WorkspaceID = WORKSPACE_ID;

// STEP 1: Setup your query criteria.TextCondition lastNameCriteria = new TextCondition("Last Name",TextConditionEnum.EqualTo, "Smith");TextCondition firstNameCriteria = new TextCondition("Name",TextConditionEnum.EqualTo, "Mike");CompositeCondition condition = new CompositeCondition(lastNameCriteria, CompositeConditionEnum.And,

firstNameCriteria);

kCura.Relativity.Client.DTOs.Query<RDO> query = new Query<RDO>{ArtifactTypeID = 1000030,

Condition = condition};

query.Fields.Add(new FieldValue("Employment Level"));query.Fields.Add(new FieldValue("Skills Inventory"));query.Fields.Add(new FieldValue("HR Rep"));query.Fields.Add(new FieldValue("Last Name"));query.Fields.Add(new FieldValue("Name"));

// STEP 2: Call the Query() method on the RDO repository.QueryResultSet<RDO> results = new QueryResultSet<RDO>();results = proxy.Repositories.RDO.Query(query);

//Check for success.if (!results.Success){

Console.WriteLine("An error occurred!");Console.WriteLine(results.Message);

}

// STEP 3: Get the Artifact from the query results.RDO employee = results.Results.Single().Artifact;Console.WriteLine(">>>" + employee + "<<<");

}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}",ex.Message));

}}

}

Page 186: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 186

6.14 RelativityApplicationYou can develop applications that use Relativity Dynamic Objects (RDOs), custom pages, event handlers, andother platform components. For more information, see Application Deployment System on the Relativity 8.1Developers site.The Services API supports all read and query operations on a RelativityApplication DTO.

6.14.1 Reading a RelativityApplicationTo read Field values on RelativityApplication object, you can use the Read() method on theRelativityApplication repository as illustrated in this code sample.

public static bool ReadRelativityApplicationUsingRepository(IRSAPIClient proxy){

// STEP 1: Create a RelativityApplication DTO for the application that youwant to read.RelativityApplication relativityApplication = new RelativityApplication(1037631);relativityApplication.Fields.Add(new FieldValue(RelativityApplicationFieldNames.Name));relativityApplication.Fields.Add(new FieldValue(RelativityApplicationFieldNames.Version));

ResultSet<RelativityApplication> readResultSet = null;

// STEP 2: Try to read the RelativityApplication object.try{

readResultSet = proxy.Repositories.RelativityApplication.Read(relativityApplication);

}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

// STEP 3: Check for success.if (!readResultSet.Success){

Console.WriteLine("An error occurred reading the Relativity Application:{0}", readResultSet.Message);

foreach (Result<RelativityApplication> readResult inreadResultSet.Results){

Page 187: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 187

if (!readResult.Success){Console.WriteLine(" An error occurred in the read result: {0}",readResult.Message);}

}return false;

}RelativityApplication readApplication = readResultSet.Results[0].Artifact;

// STEP 4: Display the name and version of the Relativity application.Console.WriteLine("Relativity Application Name: {0}{1}Relativity ApplicationVersion: {2}",

readApplication.Name, Environment.NewLine, readApplication.Version);

return true;}

6.14.2 Deleting a Relativity ApplicationYou can call the Delete() method on the RelativityApplication repository to delete an application. TheApplication Deployment System (ADS) also provides functionality for deleting and uninstalling applicationsthrough the Relativity UI. For more information, see e Application Deployment System in the Relativity 8.1Developers site.

public static bool DeleteRelativityApplicationUsingRepository(IRSAPIClientproxy){

// STEP 1: Create a RelativityApplication DTO for the application that youwant to delete.RelativityApplication relativityApplication = new RelativityApplication(1037639);WriteResultSet<RelativityApplication> writeResultSet = null;

// STEP 2: Try to delete the Relativity Application.try{

writeResultSet = proxy.Repositories.RelativityApplication.Delete(relativityApplication);

}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

Page 188: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 188

//STEP 3: Check for success.if (!writeResultSet.Success){

Console.WriteLine("An error occurred deleting the Relativity Application:{0}", writeResultSet.Message);

foreach (Result<RelativityApplication> writeResult inwriteResultSet.Results){

if (!writeResult.Success){

Console.WriteLine(" An error occurred in the delete result: {0}",writeResult.Message);

}}return false;

}return true;

}

6.14.3 Querying for a RelativityApplicationTo query for a RelativityApplication object, you can use the fields listed in the following table. For moreinformation, see Querying on page 227.

Fields for Application queriesGuid NameID VersionInDevelopment

This code sample illustrates how to set query conditions, call the Query() method on the RelativityApplicationrepository, and iterate through the result set.

public static bool QueryRelativityApplicationUsingRepository(IRSAPIClientproxy){

// STEP 1: Create a Relativity Application DTO for the application to query.Query<kCura.Relativity.Client.DTOs.RelativityApplication> query = newQuery<RelativityApplication>();

query.Fields.Add(new FieldValue(ArtifactQueryFieldNames.ArtifactID));query.Fields.Add(new FieldValue(RelativityApplicationFieldNames.Name));query.Fields.Add(new FieldValue(RelativityApplicationFieldNames.Version));

query.Condition =

Page 189: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 189

new WholeNumberCondition(ArtifactQueryFieldNames.ArtifactID,NumericConditionEnum.EqualTo, 1037631);

ResultSet<RelativityApplication> readResultSet = null;

//STEP 2: Attempt to query the Relativity Application.try{

readResultSet = proxy.Repositories.RelativityApplication.Query(query);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

//STEP 3: Check for success.if (!readResultSet.Success){

Console.WriteLine("An error occurred reading the Relativity Application:{0}", readResultSet.Message);

foreach (Result<RelativityApplication> readResult inreadResultSet.Results){

if (!readResult.Success){Console.WriteLine(" An error occurred in the read result: {0}",readResult.Message);}

}return false;

}RelativityApplication readApplication = readResultSet.Results[0].Artifact;

//STEP 4: Display the name and version of the Relativity application.Console.WriteLine("Relativity Application Name: {0}{1}Relativity ApplicationVersion: {2}",

readApplication.Name, Environment.NewLine, readApplication.Version);

return true;}

6.15 RelativityScriptUsing the Services API, you can execute SQL-based scripts that have been added to workspaces through theRelativity web UI. These scripts extend the functionality of the Services API by working directly with the

Page 190: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 190

database to retrieve or modify data for report generation or other purposes. For more information, see Scriptdevelopment on the Relativity 8.1 Developers site.The Services API supports read and query operations on the RelativityScript DTO, as well as the functionalityfor executing a script and retrieving its inputs.

6.15.1 Reading a RelativityScriptTo read Field values, you can use the Read() method on the RelativityScript repository as illustrated in thiscode sample.

public static bool Read_RelativityScript_Using_Repository(IRSAPIClient proxy){

// STEP 1: Create a RelativityScript DTO for the RelativityScript that youwant to read.DTOs.RelativityScript relScriptDTO = new DTOs.RelativityScript(1015032);relScriptDTO.Fields = DTOs.FieldValue.AllFields;

// STEP 2: Attempt to read the RelativityScript.DTOs.ResultSet<DTOs.RelativityScript> relScriptReadResults =

new DTOs.ResultSet<DTOs.RelativityScript>();

try{

relScriptReadResults = proxy.Repositories.RelativityScript.Read(relScriptDTO);

}catch (Exception ex){

Console.WriteLine("An error occurred reading the Relativity Script: {0}",ex.Message);return false;

}

// STEP 3: Check for success.if (!relScriptReadResults.Success){

Console.WriteLine("An error occurred reading the Relativity Script: {0}",relScriptReadResults.Message);

foreach (DTOs.Result<DTOs.RelativityScript> readResult inrelScriptReadResults.Results){

if (!readResult.Success){

Console.WriteLine(" An error occurred in read request: {0}",readResult.Message);

Page 191: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 191

}}return false;

}

relScriptDTO = relScriptReadResults.Results[0].Artifact;

// STEP 4: Retrieve the body as XML and output the name.XmlDocument bodyXml = relScriptDTO.Body;Console.WriteLine("Successfully read the Relativity Script '{0}'!",relScriptDTO.Name);

return true;}

6.15.2 Querying for a RelativityScriptThis code sample illustrates how to set query conditions, call the Query() method on the RelativityScriptrepository, and iterate through the result set.

public static bool Query_RelativityScript_Using_Repository(IRSAPIClient proxy){

// STEP 1: Create the query criteria.TextCondition nameCondition = new TextCondition(DTOs.RelativityScriptFieldNames.Name,

TextConditionEnum.Like, "Billing Statistics");DTOs.Query<DTOs.RelativityScript> relScriptQuery = new

DTOs.Query<DTOs.RelativityScript>{

Condition = nameCondition,Fields = DTOs.FieldValue.AllFields

};

// STEP 2: Attempt to query for the RelativityScript.DTOs.QueryResultSet<DTOs.RelativityScript> relScriptQueryResults = null;try{

relScriptQueryResults = proxy.Repositories.RelativityScript.Query(relScriptQuery);

}catch (Exception ex){

Console.WriteLine("An error occurred querying for Relativity Scripts: {0}", ex.Message);

Page 192: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 192

return false;}

// STEP 3: Check for success.if (!relScriptQueryResults.Success){

Console.WriteLine("An error occurred querying for Relativity Scripts: {0}", relScriptQueryResults.Message);return false;

}

// STEP 4: Display the results.Console.WriteLine("Number of Relativity Scripts returned: {0}",relScriptQueryResults.Results.Count);

foreach (DTOs.Result<DTOs.RelativityScript> relScriptResult inrelScriptQueryResults.Results){

DTOs.RelativityScript curRelScript = relScriptResult.Artifact;Console.WriteLine("Relativity Script Name: {0}",curRelScript.TextIdentifier);Console.WriteLine("Relativity Script ArtifactID: {0}",curRelScript.ArtifactID);

}

return true;}

6.15.3 Executing a RelativityScriptYou can use the ExecuteRelativityScript() method to run a Relativity script by passing in the script ID, and thescript input as a string. (You can perform a query to obtain the script ID.) The ExecuteRelativityScript() methodmay return a list of Artifacts and Fields, or the status of database rows affected by the script. You must be amember of the Relativity Script Admin group to use this method.The script should be configured with a return type of Table and have an integer column named ArtifactID. Foreach row in the output table, an Artifact object will be created with the ArtifactID from the ArtifactID column,and a set of Fields will be created for the remaining columns. The column names will be the Field names.When you execute a Relativity script, you can pass values for input parameters that are defined in the scriptbody. In addition to the standard script properties, the following script called Script for Sample Projectincludes the input parameter _identifier that is named ControlNumber. For more information, see Scriptdevelopment on the Relativity 8.1 Developers site.

<script><name>Script for Sample Project</name>

Page 193: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 193

<description></description><category></category><input>

<constant id="_identifier" name="ControlNumber" type="text" /></input><action returns="table"><![CDATA[

SELECT ArtifactID, ControlNumber, ExtractedText FROM [Document]WHERE ControlNumber = #_identifier#]]></action>

</script>

The following code sample illustrates how to pass a value for a script parameter when running a script bycalling the ExecuteRelativityScript() method on a RelativityScript DTO Repository object.

public static bool ExecuteRelativityScript(IRSAPIClient proxy){

// STEP 1: Query by name for the script that you want to run.// Alternatively, if you have the ArtifactID, you can create a// RelativityScript object without querying as exemplified here:// DTOs.RelativityScript script = new DTOs.RelativityScript(1036254);DTOs.RelativityScript script;TextCondition nameCondition =

new TextCondition(DTOs.RelativityScriptFieldNames.Name,TextConditionEnum.EqualTo,

"Script For Sample Project");DTOs.Query<DTOs.RelativityScript> relScriptQuery = new

DTOs.Query<DTOs.RelativityScript>{

Condition = nameCondition,Fields = DTOs.FieldValue.NoFields

};

try{

DTOs.QueryResultSet<DTOs.RelativityScript> relScriptQueryResults = null;relScriptQueryResults = proxy.Repositories.RelativityScript.Query(relScriptQuery);

if (!relScriptQueryResults.Success){

Console.WriteLine(string.Format("An error occurred finding the script:{0}",

relScriptQueryResults.Message));return false;

}

Page 194: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 194

script = relScriptQueryResults.Results[0].Artifact;}catch (Exception ex){

Console.WriteLine("An error occurred querying for Relativity Scripts: {0}", ex.Message);return false;

}

// STEP 2: Set the input parameter used in the Relativity Script.// The following sample Relativity Script contains an input parameter called"ControlNumber":// <input>// <constant id="_identifier" name="ControlNumber" type="text" />// </input>

RelativityScriptInput input = new RelativityScriptInput("ControlNumber","AS000005");List<RelativityScriptInput> inputList = new List<RelativityScriptInput> { input };

// STEP 3: Call the script.RelativityScriptResult scriptResult = null;try{

scriptResult =proxy.Repositories.RelativityScript.ExecuteRelativityScript(script,inputList);

}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

//Check for success.if (!scriptResult.Success){

Console.WriteLine(string.Format(scriptResult.Message));return false;

}else{

Int32 observedOutput = scriptResult.Count;Console.WriteLine(string.Format("Number of documents returned: {0}",observedOutput));

Page 195: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 195

foreach (Artifact art in scriptResult.Artifacts){

Console.WriteLine(string.Format("{0}: {1}", art.ArtifactID, art.Fields[1].Value));

}}return true;

}

6.15.4 Retrieving Input for a RelativityScriptYou can use the GetRelativityScriptInputs() method to retrieve a list of input data for a script. An individualinput parameter is represented by an instance of the RelativityScriptInputDetails class. You must be amember of the Relativity Script Admin group to use the GetRelativityScriptInputs() method. The followingcode sample illustrates how to use this method.

public static IList<RelativityScriptInputDetails> GetRelativityScriptInputs(IRSAPIClient proxy){

List<RelativityScriptInputDetails> scriptInputList = null;.// STEP 1: Using ArtifactID, set the script you want to run.DTOs.RelativityScript script = new DTOs.RelativityScript(1036254);

// STEP 2: Call GetRelativityScriptInputs.try{

scriptInputList =proxy.Repositories.RelativityScript.GetRelativityScriptInputs(script);

}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return scriptInputList;

}

// STEP 3: Each RelativityScriptInputDetails object can be used to generatea RelativityScriptInput object,// but this example only displays information about each input.foreach (RelativityScriptInputDetails relativityScriptInputDetails inscriptInputList){

Console.WriteLine("Input Name: {0}\nInput Id: {1}\nInput Type: {2}\nInputIs Required: {3}\n",

Page 196: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 196

relativityScriptInputDetails.Name,relativityScriptInputDetails.Id,relativityScriptInputDetails.InputType,relativityScriptInputDetails.IsRequired);

}

return scriptInputList;}

6.16 TabYou select tabs to access Relativity features, such as documents, RDOs, or applications. You can also use tabsas links to custom pages and other external resources. For more information, see Tabs in the Relativity 8.1Documentation site, and Custom pages in the Relativity 8.1 Developers site.The Services API supports read and query operations on a Tab DTO.

6.16.1 Reading a TabTo read Field values on a Tab, you can use the Read() method on the Tab repository as illustrated in this codesample.

public static bool Read_Tab(IRSAPIClient proxy){

// STEP 1: Call the Read() method on the Tab repository.DTOs.Tab requestedTab = new DTOs.Tab(1034254);requestedTab.Fields = DTOs.FieldValue.AllFields;

DTOs.ResultSet<DTOs.Tab> results = null;try{

results = proxy.Repositories.Tab.Read(requestedTab);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

//Check for success.if (!results.Success){

Console.WriteLine("An error occurred!");Console.WriteLine(results.Message);return false;

}

Page 197: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 197

// STEP 2: Get the Artifact from the read results.DTOs.Tab tab = results.Results[0].Artifact;Console.WriteLine(">>>" + tab.ToString() + "<<<");

return true;}

6.16.2 Querying for a TabThis code sample illustrates how to set query conditions, call the Query() method on the Tab repository, anditerate through the result set.

public static bool Query_Tabs(IRSAPIClient proxy){

// STEP 1: Setup your query criteria.DTOs.Query<DTOs.Tab> query = new DTOs.Query<DTOs.Tab>();TextCondition parentCriteria = new TextCondition(DTOs.TabFieldNames.LinkType, TextConditionEnum.EqualTo, "Parent");

query.Condition = parentCriteria;query.Fields = DTOs.FieldValue.AllFields;

// STEP 2: Call the query method on the Tab Repository.DTOs.QueryResultSet<DTOs.Tab> results = null;try{

results = proxy.Repositories.Tab.Query(query);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

//Check for success.if (!results.Success){

Console.WriteLine("An error occurred!");Console.WriteLine(results.Message);return false;

}

// STEP 3: Get the tabs from the query results.foreach (DTOs.Result<DTOs.Tab> tabResult in results.Results)

Page 198: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 198

{DTOs.Tab tab = tabResult.Artifact;Console.WriteLine(tab.Name + " is a Parent tab.");

}

return true;}

6.17 UserIndividuals are added to Relativity as users, who are then added to groups associated with workspaces. Formore information, see Users in the the Relativity 8.1 Documentation site.The Services API supports all CRUD and query operations on a User DTO.

6.17.1 Creating a UserYou can add a User to Relativity by calling the Create() method on the User repository. For more informationabout Password fields, see Fields used by Group and User objects on page 144.This code sample illustrates how to create the User DTO and references several utility methods for retrievingArtifactIDs. See Utility methods used in User DTO creation on page 201.

public static bool CreateUserUsingRepository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = -1;

int defaultSelectedFileType = 1;int userType = 3;int documentSkip = 1000003;int skipDefaultPreference = 1000004;int password = 1000005;int sendNewPasswordTo = 1000006;

// STEP 1: Get the ArtifactIDs for the required Choice, Group, and Clientobjects.int returnPasswordCodeID = FindChoiceArtifactID(proxy, sendNewPasswordTo,"Return");int passwordCodeID = FindChoiceArtifactID(proxy, password, "Auto-generatepassword");int documentSkipCodeID = FindChoiceArtifactID(proxy, documentSkip,"Enabled");

int documentSkipPreferenceCodeID = FindChoiceArtifactID(proxy,skipDefaultPreference, "Normal");

Page 199: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 199

int defaultFileTypeCodeID = FindChoiceArtifactID(proxy,defaultSelectedFileType, "Native");int userTypeCodeID = FindChoiceArtifactID(proxy, userType, "Internal");

int everyoneGroupArtifactID = FindGroupArtifactID(proxy, "Everyone");int clientArtifactID = FindClientArtifactID(proxy, "Relativity Template");

// STEP 2: Create a User DTO for the User that you want to create.kCura.Relativity.Client.DTOs.User userDTO = newkCura.Relativity.Client.DTOs.User();

userDTO.AdvancedSearchPublicByDefault = true;userDTO.AuthenticationData = "";userDTO.BetaUser = false;userDTO.ChangePassword = true;

userDTO.ChangePasswordNextLogin = false;userDTO.ChangeSettings = true;userDTO.Client = new kCura.Relativity.Client.DTOs.Client(clientArtifactID);userDTO.DataFocus = 1;

userDTO.DefaultSelectedFileType = new kCura.Relativity.Client.DTOs.Choice(defaultFileTypeCodeID);userDTO.DocumentSkip = new kCura.Relativity.Client.DTOs.Choice(documentSkipCodeID);userDTO.EmailAddress = "[email protected]";userDTO.EnforceViewerCompatibility = true;

userDTO.FirstName = "Bruce";userDTO.Groups =

new List<kCura.Relativity.Client.DTOs.Group>{ new kCura.Relativity.Client.DTOs.Group(everyoneGroupArtifactID) };

userDTO.ItemListPageLength = 25;userDTO.KeyboardShortcuts = true;

userDTO.LastName = "User for User Create Testing";userDTO.MaximumPasswordAge = 0;userDTO.NativeViewerCacheAhead = true;userDTO.PasswordAction = new kCura.Relativity.Client.DTOs.Choice(passwordCodeID);

userDTO.RelativityAccess = true;userDTO.SendPasswordTo = new kCura.Relativity.Client.DTOs.Choice(returnPasswordCodeID);

Page 200: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 200

userDTO.SkipDefaultPreference = new kCura.Relativity.Client.DTOs.Choice(documentSkipPreferenceCodeID);userDTO.TrustedIPs = "";userDTO.Type = new kCura.Relativity.Client.DTOs.Choice(userTypeCodeID);

WriteResultSet<kCura.Relativity.Client.DTOs.User> createResults =new WriteResultSet<kCura.Relativity.Client.DTOs.User>();

// STEP 3: Attempt to create the User.try{

createResults = proxy.Repositories.User.Create(userDTO);}catch (Exception ex){

Console.WriteLine(String.Format("An error occurred: {0}", ex.Message));return false;

}

// Check for success.if (!createResults.Success){

Console.WriteLine(String.Format("An error occurred creating user: {0}",createResults.Message));

foreach (Result<kCura.Relativity.Client.DTOs.User> createResult increateResults.Results){

if (!createResult.Success){

Console.WriteLine(String.Format(" An error occurred in createrequest: {0}", createResult.Message));

}}return false;

}

//STEP 4: Output the password.Console.WriteLine(String.Format("Password for created user is {0}",

createResults.Results[0].Artifact["Password"]));

return true;}

Page 201: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 201

6.17.2 Utility methods used in User DTO creationThe code sample illustrating how to create the User DTO uses the following utility methods to facilitate theretrieval of ArtifactIDs for Choices, Groups, and Clients.FindChoiceArtifactID() method

private static int FindChoiceArtifactID(IRSAPIClient proxy, int choiceType,string value){

int artifactID = 0;

WholeNumberCondition choiceTypeCondition =new WholeNumberCondition(ChoiceFieldNames.ChoiceTypeID,NumericConditionEnum.EqualTo, (int)choiceType);

TextCondition choiceNameCondition =new TextCondition(ChoiceFieldNames.Name, TextConditionEnum.EqualTo,value);

CompositeCondition choiceCompositeCondition =new CompositeCondition(choiceTypeCondition, CompositeConditionEnum.And,choiceNameCondition);

Query<kCura.Relativity.Client.DTOs.Choice> choiceQuery =new Query<kCura.Relativity.Client.DTOs.Choice>(new List<FieldValue> { new

FieldValue(ArtifactQueryFieldNames.ArtifactID) },choiceCompositeCondition, new List<Sort>());

try{

QueryResultSet<kCura.Relativity.Client.DTOs.Choice> choiceQueryResult =proxy.Repositories.Choice.Query(choiceQuery);

if (choiceQueryResult.Success && choiceQueryResult.Results.Count == 1){

artifactID = choiceQueryResult.Results.FirstOrDefault().Artifact.ArtifactID;

}else{

Console.WriteLine("The choice could not be found.");}

}catch (Exception ex){

Console.WriteLine(String.Format("An error occurred: {0}", ex.Message));

Page 202: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 202

}return artifactID;

}

FindGroupArtifactID() method

private static int FindGroupArtifactID(IRSAPIClient proxy, string group){

int artifactID = 0;

TextCondition groupCondition =new TextCondition(GroupFieldNames.Name, TextConditionEnum.EqualTo,group);

Query<kCura.Relativity.Client.DTOs.Group> queryGroup =newkCura.Relativity.Client.DTOs.Query<kCura.Relativity.Client.DTOs.Group> { Condition = groupCondition };

queryGroup.Fields.Add(new FieldValue(ArtifactQueryFieldNames.ArtifactID));

try{

QueryResultSet<kCura.Relativity.Client.DTOs.Group> resultSetGroup =proxy.Repositories.Group.Query(queryGroup, 0);

if (resultSetGroup.Success && resultSetGroup.Results.Count == 1){

artifactID = resultSetGroup.Results.FirstOrDefault().Artifact.ArtifactID;

}else{

Console.WriteLine("The Query operation failed.{0}{1}",Environment.NewLine, resultSetGroup.Message);

}}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}",ex.Message));

}return artifactID;

}

FindClientArtifactID() method

Page 203: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 203

private static int FindClientArtifactID(IRSAPIClient proxy, string group){

int artifactID = 0;

TextCondition clientCondition =new TextCondition(ClientFieldNames.Name, TextConditionEnum.EqualTo,group);

Query<kCura.Relativity.Client.DTOs.Client> queryClient =new Query<kCura.Relativity.Client.DTOs.Client> { Condition =clientCondition };

queryClient.Fields = FieldValue.AllFields;

try{

QueryResultSet<kCura.Relativity.Client.DTOs.Client> resultSetClient =proxy.Repositories.Client.Query(queryClient, 0);

if (resultSetClient.Success && resultSetClient.Results.Count == 1){

artifactID = resultSetClient.Results.FirstOrDefault().Artifact.ArtifactID;

}else{

Console.WriteLine("The Query operation failed.{0}{1}",Environment.NewLine, resultSetClient.Message);

}}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));}return artifactID;

}

6.17.3 Reading a UserTo read Field values, you can use the Read() method on the User repository as illustrated in this code sample.

public static bool ReadUserUsingRepository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = -1;

Page 204: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 204

// STEP 1: Create the User DTO.kCura.Relativity.Client.DTOs.User user = newkCura.Relativity.Client.DTOs.User(1015464);user.Fields = FieldValue.AllFields;ResultSet<kCura.Relativity.Client.DTOs.User> userResults = null;

//STEP 2: Read the User DTO.try{

userResults = proxy.Repositories.User.Read(user);}catch (Exception ex){

Console.WriteLine("An error occurred reading the user: {0}", ex.Message);return false;

}

//STEP 3: Check for success.if (!userResults.Results.Any()){

Console.WriteLine("Could not find the user: {0}", userResults.Message);return false;

}return true;

}

6.17.4 Updating a UserYou can use the Update() method on the User repository to modify its properties as illustrated in this codesample. See Fields used by Group and User objects on page 144.

public static bool UpdateUserUsingRepository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = -1;

//STEP 1: Define the query.Condition userQueryCondition =

new TextCondition(UserFieldNames.FirstName, TextConditionEnum.EqualTo,"Bruce");

Query<kCura.Relativity.Client.DTOs.User> userQuery =new Query<kCura.Relativity.Client.DTOs.User>(FieldValue.AllFields,userQueryCondition, new List<Sort>());

QueryResultSet<kCura.Relativity.Client.DTOs.User> userQueryResults = null;

Page 205: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 205

//STEP 2: Query for the User.try{

userQueryResults = proxy.Repositories.User.Query(userQuery);}catch (Exception ex){

Console.WriteLine("An error occurred querying for the user: {0}",ex.Message);return false;

}

if (!userQueryResults.Results.Any()){

Console.WriteLine("Could not find the user: {0}",userQueryResults.Message);return false;

}

//STEP 3: Retreive the User artifact and update it.kCura.Relativity.Client.DTOs.User userToUpdate =userQueryResults.Results.First().Artifact;userToUpdate.FirstName = "Steve";WriteResultSet<kCura.Relativity.Client.DTOs.User> userUpdateResults = null;

//STEP 4: Complete the update.try{

userUpdateResults = proxy.Repositories.User.Update(userToUpdate);}catch (Exception ex){

Console.WriteLine("An error occurred updating the user: {0}",ex.Message);return false;

}

//STEP 5: Check for success.if (userUpdateResults.Success){

Console.WriteLine("The user has been updated!");}else{

Page 206: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 206

Console.WriteLine("An error occurred updating the user: {0}",userUpdateResults.Message);return false;

}return true;

}

6.17.5 Deleting a UserYou can remove a User from Relativity by calling the Delete() method on the User repository as illustrated inthis code sample.

public static bool DeleteUserUsingRepository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = -1;

// STEP 1: Create the User DTO.kCura.Relativity.Client.DTOs.User user = newkCura.Relativity.Client.DTOs.User(1015464);ResultSet<kCura.Relativity.Client.DTOs.User> userResults = null;

// STEP 2: Delete the User.try{

userResults = proxy.Repositories.User.Delete(user);}catch (Exception ex){

Console.WriteLine("An error occurred deleting for the user: {0}",ex.Message);return false;

}

// STEP 3: Check for success.if (!userResults.Results.Any()){

Console.WriteLine("Could not delete the user: {0}", userResults.Message);return false;

}return true;

}

6.17.6 Querying for a UserThis code sample illustrates how to set query conditions, call the Query() method on the User repository, anditerate through the result set.

Page 207: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 207

public static bool QueryUserUsingRepository(IRSAPIClient proxy){

proxy.APIOptions.WorkspaceID = -1;

// STEP 1: Create the query for a given user.Condition userQueryCondition =

new TextCondition(UserFieldNames.FirstName, TextConditionEnum.EqualTo,"Bruce");

Query<kCura.Relativity.Client.DTOs.User> userQuery =new Query<kCura.Relativity.Client.DTOs.User>(FieldValue.AllFields,userQueryCondition, new List<Sort>());

QueryResultSet<kCura.Relativity.Client.DTOs.User> userQueryResults = null;

// STEP 2: Query for the user.try{

userQueryResults = proxy.Repositories.User.Query(userQuery);}catch (Exception ex){

Console.WriteLine("An error occurred querying for the user: {0}",ex.Message);return false;

}

// STEP 3: Check for success.if (!userQueryResults.Results.Any()){

Console.WriteLine("Could not find the user: {0}",userQueryResults.Message);return false;

}return true;

}

6.18 ViewRelativity uses views to provide customizable item lists. For more information, see Views in the Relativity 8.1Documentation site.The Services API supports read and query operations on a ViewDTO.

Page 208: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 208

6.18.1 Reading a ViewTo read Field values on a View, you can use the Read() method on the View repository as illustrated in thiscode sample.

public static bool Read_View_Using_Repository(IRSAPIClient proxy){

// STEP 1: Create a View DTO for the View to be read.DTOs.View viewDTO = new DTOs.View(1034249);viewDTO.Fields = FieldValue.AllFields;ResultSet<DTOs.View> viewReadResults = new ResultSet<DTOs.View>();

// STEP 2: Try to read the View.try{

viewReadResults = proxy.Repositories.View.Read(viewDTO);}catch (Exception ex){

Console.WriteLine("An error occurred reading the view: {0}", ex.Message);return false;

}

// STEP 3: Check for success.if (!viewReadResults.Success){

Console.WriteLine("An error occurred reading the view: {0}",viewReadResults.Message);

foreach (Result<DTOs.View> readResult in viewReadResults.Results){

if (!readResult.Success){

Console.WriteLine(" An error occurred in read request: {0}",readResult.Message);

}}return false;

}// STEP 4: Output the name.Console.WriteLine("Successfully read the view '{0}'!",viewReadResults.Results[0].Artifact.Name);

return true;}

Page 209: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 209

6.18.2 Querying for a ViewThis code sample illustrates how to set query conditions, call the Query() method on the View repository, anditerate through the result set.

public static bool Query_View_Using_Repository(IRSAPIClient proxy){

// STEP 1: Create the Query criteria.ObjectsCondition relAppCondition =

new ObjectsCondition("Relativity Applications",ObjectsConditionEnum.AllOfThese, new int[] { 1035699 });

Query<DTOs.View> viewQuery = new Query<DTOs.View>{

Condition = relAppCondition,Fields = FieldValue.AllFields

};

// STEP 2: Try to query for the View.QueryResultSet<DTOs.View> viewQueryResults = null;

try{

viewQueryResults = proxy.Repositories.View.Query(viewQuery);}catch (Exception ex){

Console.WriteLine("An error occurred querying for views: {0}",ex.Message);return false;

}

// STEP 3: Check for success.if (!viewQueryResults.Success){

Console.WriteLine("An error occurred querying for views: {0}",viewQueryResults.Message);return false;

}

// STEP 4: Display the results.Console.WriteLine("Number of views returned: {0}",viewQueryResults.Results.Count);

foreach (Result<DTOs.View> viewResult in viewQueryResults.Results){

Page 210: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 210

DTOs.View curView = viewResult.Artifact;

Console.WriteLine("View Name: {0}", curView.TextIdentifier);Console.WriteLine("View ArtifactID: {0}", curView.ArtifactID);

}

return true;}

6.19 WorkspaceIn Relativity, workspaces are secure data repositories for storing documents and applications. For additionalinformation, seeWorkspaces in the Relativity 8.1 Documentation site.The Services API supports read and query operations on aWorkspace DTO.

6.19.1 Reading a WorkspaceTo read Field values on aWorkspace, you can use the Read() method on theWorkspace repository asillustrated in this code sample.

public static bool Read_Workspace(IRSAPIClient proxy){

// STEP 1: Create ResultSet to store Results.ResultSet<DTOs.Workspace> resultSet = new ResultSet<DTOs.Workspace>();

// STEP 2: Perform the Read operation.// You could create a DTOs.Workspace object, set its ArtifactID property,// and use the Workspace object as the parameter. However, this example// demonstrates using the ArtifactID as a parameter.try{

resultSet = proxy.Repositories.Workspace.Read(1016204);}catch (Exception ex){

Console.WriteLine("An error occurred: {0}", ex.Message);return false;

}

// Check for success.if (!resultSet.Success){

Console.WriteLine("The Read operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

Page 211: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 211

}

// Display results.Console.WriteLine("Read completed successfully.");

foreach (DTOs.Result<DTOs.Workspace> workspaceResult in resultSet.Results){

Console.WriteLine(String.Format("{0}Name:{1}", Environment.NewLine,workspaceResult.Artifact.Name));Console.WriteLine(String.Format("ArtifactID:{0}",workspaceResult.Artifact.ArtifactID));

}

return true;}

6.19.2 Querying for a WorkspaceThis code sample illustrates how to set query conditions, call the Query() method on theWorkspacerepository, and iterate through the result set.

public static bool Query_Workspace(IRSAPIClient proxy)

{//STEP 1: Create a Query and WholeNumberCondition.WholeNumberCondition workspaceCondition =

new WholeNumberCondition(ArtifactQueryFieldNames.ArtifactID,NumericConditionEnum.EqualTo, 1016204);

Query<DTOs.Workspace> query = new DTOs.Query<DTOs.Workspace> { Condition =workspaceCondition };query.Fields = FieldValue.AllFields;

//STEP 2: Create QueryResultSet to collect information about the DTO afterQuery.QueryResultSet<DTOs.Workspace> resultSet = newQueryResultSet<DTOs.Workspace>();

//STEP 3: Perform the Query.try{

resultSet = proxy.Repositories.Workspace.Query(query, 0);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));

Page 212: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 212

return false;}

//Check for success.if (!resultSet.Success){

Console.WriteLine("The Query operation failed.{0}{1}",Environment.NewLine, resultSet.Message);return false;

}

// Display the results.Console.WriteLine(string.Format("Number of Workspaces returned: {0}",resultSet.Results.Count));

foreach (DTOs.Result<DTOs.Workspace> workspaceResult in resultSet.Results){

Console.WriteLine(string.Format("{0}Name:{1}", Environment.NewLine,workspaceResult.Artifact.Name));Console.WriteLine(string.Format("ArtifactID:{0}",workspaceResult.Artifact.ArtifactID));

}

return true;

}

7 Additional Services API functionalityThe Services API includes additional features for querying, file transfers, mass operations, and others.

7.1 File transfersThrough the Services API, you can perform download and upload requests on a File field as well as clear thefield.

7.1.1 Supported file transfer operationsThe RSAPIClient supports the following operations for file transfers:

n Download () - The following overloaded methods are available:o Download(FileRequest) - downloads the contents of a Relativity file field and returns it in the

form of a Stream object. It takes a FileRequest and returns an instance of DownloadResponse. Itraises the DownloadComplete event when the operation is successful.

o Download(FileRequest, String) - accepts a FileRequest, and a String which represents thedestination location of the file on disk.

Page 213: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 213

Note: You can also download files by using the URL retrieved from a File field on a Dynamic Object. SeeGetting a download URL for a File field on page 139.

n Upload () - takes an UploadRequest. It raises the UploadComplete event when the operation is suc-cessful. The Upload() and Download() methods support zero-length files.

n Clear () - clears the value of a file field in Relativity. It returns no response when it completes suc-cessfully.

When an operation fails on thesemethods, a Failure event is raised that contains instance of FailureEventArgsclass. This instance contains the exception that would have been thrown during a failed operation. SeeRSAPIClient events in the Services API class library.

7.1.2 File transfer error messagesThe following table lists error classes associated with various operations related to file transfers.

Operation Error ClassesAll Operations FileTransferFault

InvalidFieldIdFaultInvalidObjectArtifactIdFaultInvalidWorkspaceIdFaultMissingFileFieldFault

Upload() FileSizeMismatchFaultNoOverwriteFaultOperationInProgressfault

Download() EmptyFieldFaultClear() No error messages

7.1.3 Error classesIn the Services API, you can use error classes to obtain additional information for troubleshooting. Each errorclass uses one or more dedicated messages. The returned exception object has as a property namedMessage. The following table lists the error classes as well as their associated messages and possible causes.

Class Message CauseEmptyFieldFault Field is empty, no file to download. Field contains no file.FileSizeMismatchFault Size specified in request does not

match size of file received.Number of bytes written to disk by theserver doesn't match the number spe-cified in theUploadRequest.Metadata.FileSizeproperty.

FileTransferFault Request could not be authen-ticated.

Token supplied doesn't refer to alogged-in session

FileTransferFault Cannot download chunk index [X]for file, there are only [Z] chunkstotal.

An invalid chunk index was specifiedduring the download operation.

Page 214: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 214

Class Message CauseFileTransferFault Invalid sessionId. SessionId supplied during a transfer

operation doesn't refer to an existingtransfer session.

FileTransferFault Unable to parse sessionId. SessionId supplied during a transferoperation is in an invalid format.

InvalidFieldIdFault FieldId is invalid. The Target.FieldId property supplied is<= 0.

InvalidObjectArtifactIdFault ObjectArtifactId is invalid. The Target.ObjectArtifactId propertysupplied is <= 0.

InvalidWorkspaceIdFault WorkspaceId is invalid. The Target.WorkspaceId property sup-plied is <= 0.

MissingFileFieldFault No file field with id [X] could befound.

The Target.FieldId property supplieddoesn't refer to an existing field.

NoOverwriteFault Field with existing value not over-written.

The file field referred to by Tar-get.FieldId isn't empty butUploadRequest. Overwrite is set toFalse.

OperationInProgressFault An upload operation is in progressalready for the object with id [X] inthe workspace with id [Z].

An upload operation is currently in pro-gress on the specified field in the work-space.

7.1.4 Sample error handling codeUse the following guidelines when handling errors:

n Listen for the Failure event on the RSAPIClient class. See RSAPIClient.Failure Event in the Services APIclass library.

n Pull the exception thrown during a transfer operation from the FailureEventArgs.Exception property.n Inspect the type of the exception so you can take the appropriate action. All of the FaultException

errors thrown by the RSAPIClient service are caught, as well as any .NET framework exceptions. Theexception isn't always a FaultException<T>.

The following sample illustrates a basic approach to error handling in the Services API:

private void HandleFailureEvents(FalureEventArgs failureInfo){

Exception excepDetail = failureInfo.Exception;if (excepDetail is FaultException<OperationInProgressFault>) {

Interaction.MsgBox(excepDetail > Message, MsgBoxStyle.Critical,"Error!");

} else {Interaction.MsgBox("An error occurred!", MsgBoxStyle.Critical, "Error");}

}

Page 215: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 215

7.2 Mass processesThe Services API provides you with the ability to perform an operation on multiple items with a single API call.

7.2.0.1 Using Lists of Artifacts as input to CRUD methodsEach of the CRUD methods takes a List of Artifacts so you can perform these operations on multiple objects insingle call. Use the following guidelines when submitting ArtifactRequests for CRUD operations:

n You can pass ArtifactRequests of different types. For example, you could submit a list of Arti-factRequests to the Update() method that contains Artifacts for Documents and Dynamic Objects.

n You must pass all the parameters required by the CRUDmethod that you are using for each Arti-factRequest. For example, you must pass the ArtifactType and list of Fields for each ArtifactRequestwhen creating Artifacts.

n No transactional guarantee exists for themethod as a whole. The creation, update or deletion of eachArtifactRequest is handled individually. If the operation against a single ArtifactRequest fails, the Suc-cess flag on the Result object for the corresponding ArtifactRequest is set to False, and returned in theResultSet. The operations on the other ArtifactRequests will proceed.

7.2.0.2 MassCreate() and MassCreateWithDetails() methodsYou can use theMassCreate() and MassCreateWithDetails() methods to createmultiple Dynamic Objects.Both methods use a template to minimize the repetition of Field values that are common to all the Artifacts.TheMassCreateWithDetails() method also populates the Results property with success and failureinformation as part of the object creation process. This information is provided even when a partial failureoccurs.TheMassCreate() and MassCreateWithDetails() methods take the Fields specified for each Artifact included inthe List of Artifacts passed as a parameter.

View sample code for theMassCreate() method

public static bool Using_MassCreate(IRSAPIClient proxy){

// STEP 1: Create Artifact that serves as a template for the RDOs that youwant to create.ArtifactRequest artifactRequest = new ArtifactRequest("Employees");List<Field> templateFields = new List<Field>();

templateFields.Add(new Field("Name"));templateFields.Add(new Field("Last Name"));templateFields.Add(new Field("Employment Level", 1036226));artifactRequest.Fields = templateFields;

// STEP 2: Create a list of Artifacts of RDOs to create via MassCreate.List<ArtifactRequest> artifactRequestList = new List<ArtifactRequest>();

for (int i = 1; i <= 10; i++){

ArtifactRequest anotherArtifactRequest = new ArtifactRequest();

Page 216: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 216

List<Field> fields = new List<Field>();

fields.Add(new Field("Name", i.ToString()));fields.Add(new Field("Last Name", "Employee #:" + i.ToString()));

anotherArtifactRequest.Fields = fields;anotherArtifactRequest.ParentArtifactID = 1016204;

// The identifier 1016204 is the WorkspaceID.artifactRequestList.Add(anotherArtifactRequest);

}

// STEP 3: Call the Services API to MassCreate the Employees.MassCreateResult results = new MassCreateResult();

try{

results = proxy.MassCreate(proxy.APIOptions, artifactRequest,artifactRequestList);Console.WriteLine(string.Format("MassCreate Success Flag: {0}",results.Success));

}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

if (!results.Success){

Console.WriteLine(results.Message);

foreach (Result r in results.Results){

Console.WriteLine(r.Message);}return false;

}return true;

}

View sample code for theMassCreateWithDetails() method

public static bool Using_MassCreateWithDetails(IRSAPIClient proxy){

Page 217: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 217

// STEP 1: Create Artifact that serves as a template for the RDOs that youwant to create.ArtifactRequest artifactRequest = new ArtifactRequest("Employees");

List<Field> templateFields = new List<Field>();templateFields.Add(new Field("Name"));templateFields.Add(new Field("Last Name"));templateFields.Add(new Field("Employment Level", 1036226));

artifactRequest.Fields = templateFields;

// STEP 2: Create a list of Artifacts of the RDOs created via MassCreate.List<ArtifactRequest> artifactRequestList = new List<ArtifactRequest>();

for (int i = 1; i <= 10; i++) {ArtifactRequest anotherArtifactRequest = new ArtifactRequest();List<Field> fields = new List<Field>();

fields.Add(new Field("Name", i.ToString()));fields.Add(new Field("Last Name", "Employee #:" + i.ToString()));

anotherArtifactRequest.Fields = fields;anotherArtifactRequest.ParentArtifactID = 1016204;

// The identifier 1016204 is the WorkspaceID.artifactRequestList.Add(anotherArtifactRequest);

}

// STEP 3: Call the Services API to MassCreate the Employees.MassCreateResult results = new MassCreateResult();

try {results = proxy.MassCreateWithDetails(proxy.APIOptions, artifactRequest,artifactRequestList);Console.WriteLine(string.Format("MassCreate Success Flag: {0}",results.Success));

}catch (Exception ex) {

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

// The results objects contains the Artifact ID for each new Artifact.if (results.Success) {

Console.WriteLine("Total Artifacts Created: " + results.Count);

Page 218: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 218

foreach (Result result in results.Results){

Console.WriteLine("Created Artifact: " + result.ArtifactID);}

}else {

Console.WriteLine(results.Message);foreach (Result r in results.Results) {

Console.WriteLine(r.Message);}return false;

}

//Clean up.try {

artifactRequestList = new List<ArtifactRequest>();

for (int i = 1; i <= 10; i++) {ArtifactRequest anotherArtifactRequest =

newArtifactRequest("Employees", results.Results[i-1].ArtifactID);

artifactRequestList.Add(anotherArtifactRequest);}proxy.Delete(proxy.APIOptions, artifactRequestList);

}catch (Exception ex) {

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));

return false;}return true;

}

Themass createmethods are subject to the following restrictions:

n Only Dynamic Objects can be created with this method.n All Artifacts to be created must be of the same ArtifactType, and all Fields must be specified by Name.

Don't use the ArtifactID.n Each Field in the templatemust have a value, and be specified by Name. Don't use NULL values or spe-

cify Fields by ArtifactID.n All required Fields must have values.

Note: The Configuration Table contains theMaxNumberOfArtfactsToMassCreate setting, which controlsthe maximum number of Dynamic Objects that can be create with this method. The default value iscurrently 1,000,000.

Page 219: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 219

7.2.0.3 MassEdit() methodYou can use theMassEdit() method to apply the same set of Field updates to multiple Documents in a singlecall. This method uses a template Document as an ArtifactRequest, which determines how the call updatesother documents. It also takes a list of ArtifactIDs that identify the Documents for editing. You can onlyupdate Documents with this method, and updates aren't propagated to related documents as they are in theRelativity web UI.

Note: The Configuration Table contains theMaxNumberOfArtfactsToMassEdit setting, which controlsmaximum number of documents edited in a single call. The default value is 1,000,000. In addition, theMassEdit() method updates the documents in batches. MassEditBatchAmount is the configuration settingthat controls the number of documents in each batch, and it is also used by the Relativity web UI. Thedefault and recommended value is 1,000.

View sample code for theMassEdit() method

public static bool Using_MassEdit(IRSAPIClient proxy){

// STEP 1: Create Artifact that serves as a template for the Documents thatyou want to update.List<Field> fields = new List<Field>();fields.Add(new Field("MD5 Hash", "New Value"));

ArtifactRequest artifactRequest = new ArtifactRequest("Document");artifactRequest.Fields = fields;

// STEP 2: Create a list of ArtifactIDs of the Documents updated viaMassEdit.List<Int32> artifactIDsToUpdate = new List<Int32>() {1035607, 1035608};

//STEP 3: Call the Services API to MassEdit the Documents.MassEditResult resultSet;

try{

resultSet = proxy.MassEdit(proxy.APIOptions, artifactRequest,artifactIDsToUpdate);

}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}Console.WriteLine(string.Format("MassEdit Success Flag: {0}",resultSet.Success));

Page 220: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 220

// Check for success.if (!resultSet.Success){

Console.WriteLine(resultSet.Message);return false;

}return true;

}

7.2.0.4 ExecuteBatch() methodYou can use the ExecuteBatch() method to combinemultiple operations in a single database transaction. Forexample, you could create a set of Artifacts and update a set of Documents using a single round-trip to theServices API.

View sample code for the ExecuteBatch() method

public static bool Using_ExecuteBatch(IRSAPIClient proxy){

// STEP 1: Create RDOs used later to demonstrate the ExecuteBatch() method.ArtifactRequest artifactRequest1 = new ArtifactRequest();

artifactRequest1.ParentArtifactID = 1016204;artifactRequest1.ArtifactTypeName = "Employees";artifactRequest1.Fields = new List<Field>();

Field nameField1 = new Field("Name", "John");Field lastNameField1 = new Field("Last Name", "Doe");artifactRequest1.Fields.Add(nameField1);artifactRequest1.Fields.Add(lastNameField1);

ArtifactRequest artifactRequest2 = new ArtifactRequest();

artifactRequest2.ParentArtifactID = 1016204;artifactRequest2.ArtifactTypeName = "Employees";artifactRequest2.Fields = new List<Field>();

Field nameField2 = new Field("Name", "Jane");Field lastNameField2 = new Field("Last Name", "Smith");artifactRequest2.Fields.Add(nameField2);artifactRequest2.Fields.Add(lastNameField2);

List<ArtifactRequest> artifactRequestList = new List<ArtifactRequest>();artifactRequestList.Add(artifactRequest1);artifactRequestList.Add(artifactRequest2);ResultSet results = new ResultSet();

Page 221: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 221

// Attempt to create the new Users.try{

results = proxy.Create(proxy.APIOptions, artifactRequestList);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}List<ArtifactRequest> artifactRequestToReadList = new List<ArtifactRequest>();

foreach (Result result in results.Results){

ArtifactRequest artifactRequestToRead = new ArtifactRequest();artifactRequestToRead.ArtifactID = result.ArtifactID;artifactRequestToRead.ArtifactTypeID = 1000036;artifactRequestToReadList.Add(artifactRequestToRead);

}ReadResultSet readResultSet = new ReadResultSet();

//Read back the Users just created.try{

readResultSet = proxy.Read(proxy.APIOptions, artifactRequestToReadList);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}List<Artifact> sampleEmployees = new List<Artifact>();

foreach (ReadResult readResult in readResultSet.ReadResults){

sampleEmployees.Add(readResult.Artifact);}

ArtifactRequest john =new ArtifactRequest((Int32)sampleEmployees[0].ArtifactTypeID, (Int32)sampleEmployees[0].ArtifactID);

ArtifactRequest jane =

Page 222: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 222

new ArtifactRequest((Int32)sampleEmployees[1].ArtifactTypeID, (Int32)sampleEmployees[1].ArtifactID);

// STEP 2: Create an Update Command for one artifact.List<ArtifactRequest> artifactRequestsToUpdate = new List<ArtifactRequest>{ john };

Field lastNameField = sampleEmployees[0].Fields.FirstOrDefault(field =>field.Name == "Last Name");lastNameField.Value = "Doe - Updated";john.Fields.Add(lastNameField);

// Add a new skill to this employee by updating the Skills Inventorymultichoice field.Field skills = sampleEmployees[0].Fields.FirstOrDefault(field => field.Name== "Skills Inventory");

// Define the skill to be added as a MultiChoice Update Value that is'merged' with any existing skill values.MultiChoiceUpdateValue skillToBeAdded = new MultiChoiceUpdateValue();skillToBeAdded.Value = new List<Int32>();skillToBeAdded.Value.Add(1036219);skillToBeAdded.Behavior = MultiChoiceUpdateBehavior.Merge;

// Set the Skills field value to be that of the MultiChoiceUpdateValue.skills.Value = skillToBeAdded;john.Fields.Add(skills);Command anUpdateCommand = new UpdateCommand(artifactRequestsToUpdate);

//STEP 3: Create a Delete Command for an artifact.List<ArtifactRequest> artifactRequestsToDelete = new List<ArtifactRequest>();artifactRequestsToDelete.Add(jane);Command aDeleteCommand = new DeleteCommand(artifactRequestsToDelete);

// STEP 4: Bundle the Command objects into a list. The commands are executedin the order that they are provided.List<Command> commands = new List<Command>();commands.Add(anUpdateCommand);commands.Add(aDeleteCommand);ExecuteBatchResultSet executeBatchResults = new ExecuteBatchResultSet();

// STEP 5: Call the Services API to execute the batch of Commands.try{

Page 223: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 223

executeBatchResults = proxy.ExecuteBatch(proxy.APIOptions, commands,TransactionType.Batch);Console.WriteLine(string.Format("Batch Success Flag: {0}",results.Success));if (!results.Success){

foreach (ResultSet resultSetItem in executeBatchResults.ResultSets){

Console.WriteLine(resultSetItem.ResultSetType.ToString() + ": " +resultSetItem.Success.ToString());foreach (Result resultItem in resultSetItem.Results){

if (!resultItem.Success)Console.WriteLine(resultItem.Message);

}}return false;

}}catch (Exception ex){

Console.WriteLine("There was an error:" + ex.Message);}return true;

}

Use the following guidelines when calling this method:

n Input to the ExecuteBatch() method is a List of Command objects.n All operations execute within a database transaction. If an error occurs, the entire batch is rolled-back.n Executing a large number of create, update, and delete operations may take considerable time and res-

ult in table locking.

Note: The Configuration Table contains theMaxArtifactBatchSizeForExecuteBatch setting, which controlsthe number of Artifacts processed in a single method call. The default value is 2000, but you can update itas necessary. This setting has been implemented to limit the length of time that database transactionopened by ExecuteBatch() method holds locks on tables, preventing Relativity users from experiencingerrors.

7.2.1 Mass delete operationsUsing the Services API, you can perform mass delete operations on Documents and their associated files, aswell as on other object types. The account used to perform these operations must be a Relativityadministrator with Delete Object Dependencies permissions. See Security permissions on the Relativity 8.1Documentation site.

Page 224: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 224

Themethods, classes, and the enumeration used to perform mass delete operations are available in thekCura.Relativity.Client namespace.

Note: For the code samples provided on this page, you can assume that the APIOptions object on theproxy has the appropriate token and WorkspaceID.

7.2.1.1 MassDeleteOptions and DocumentMassDeleteOptions classesWhen calling themass deletemethods, you need to pass an instance of theMassDeleteOptions orDocumentMassDeleteOptions class. These classes provides information about how to delete objects.

DocumentMassDeleteOptions class

You pass an instance of the DocumentMassDeleteOptions class to theMassDeleteDocuments() orMassDeleteAllDocuments() methods. To indicate how to perform the deletion, you can set either or both ofthe following fields on the DocumentMassDeleteOptions class to true or false:

n Force Delete – removes the selected Documents even if they have redactions, annotations, links, ortags.

n Cascade Delete – removes the selected Documents, as well as deletes all child objects and unlinks asso-ciative objects.

In addition, you can use the DeleteType enumeration to specify the type of files associated with theDocuments that you want to delete:

n AllAssociatedFiles – indicates that you want to delete Documents and all dependent files, includingimages and native files. It also results in the deletion of field values.

n Images – indicates that you want to delete only the images associated with the selected Documents.n Natives – indicates that you want to delete only the native files associated with the selected Docu-

ments.n ImagesAndNatives – indicates that you want to delete only the images and native files associated with

the selected Documents. (The field values for the documents aren't deleted.)

MassDeleteOptions class

You pass an instance of theMassDeleteOptions class to theMassDelete() or MassDeleteAllObjects methods.It indicates the type of the object that you want to delete, as well as whether you want to delete alldependent objects by performing a cascade delete. You can set the Cascade Delete field to true when youwant to delete all child objects and unlink associative objects.

7.2.1.2 MassDeleteAllDocuments() methodYou can use theMassDeleteAllDocuments() to delete all Documents and their associated files in theWorkspace. This code sample illustrates how to set the CascadeDelete and ForceDelete fields on theDocumentMassDeleteOptions object when deleting all Documents and their associated files in a Workspace.

public static bool Using_MassDelete_ToCascadeAndForceDeleteAllDocumentsInWorkspace(IRSAPIClient proxy){

//STEP 1: Set up delete options.

Page 225: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 225

var deleteOptions = new DocumentMassDeleteOptions(DocumentMassDeleteOptions.DeleteType.AllAssociatedFiles);deleteOptions.CascadeDelete = true;deleteOptions.ForceDelete = true;

//STEP 2: Delete all documents.var result = proxy.MassDeleteAllDocuments(proxy.APIOptions, deleteOptions);

//STEP 3: Check for success.if (!result.Success){

Console.WriteLine(result.Message);return false;

}return true;

}

7.2.1.3 MassDeleteDocuments() methodYou can use theMassDeleteDocuments() method to delete all files , images, natives, or both the images andnatives associated with a Document. You must use a DeleteType enum to specify the file types that you wantto delete, and then list the ArtifactID of each Document.This code sample illustrates how to force delete images for the Documents with the specified ArtifactIDs. Aforce deletion removes even Documents containing redactions and annotations from theWorkspace.

public static bool Using_MassDelete_ToForceDeleteImagesForSpecificDocuments(IRSAPIClient proxy){

//STEP 1: Set up delete options.var deleteOptions = new DocumentMassDeleteOptions(DocumentMassDeleteOptions.DeleteType.Images);deleteOptions.ForceDelete = true;

//STEP 2: Call the mass delete method on the ArtifactIDs you want to delete.var result =

proxy.MassDeleteDocuments(proxy.APIOptions, deleteOptions, new List<int>{1033456, 1033457, 1033458});

//STEP 3: Check for success.if (!result.Success){

Console.WriteLine(result.Message);return false;

}return true;

}

Page 226: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 226

7.2.1.4 MassDelete() methodTheMassDelete() method removes a list of objects from theWorkspace. You must specify the ArtifactType ofthe objects, and then list the ArtifactID of each object to delete. This code sample illustrates how to perform acascade delete on the objects of the specified type.

public static bool Using_MassDelete_ToCascadeDeleteSpecificObjectsOfSpecificType(IRSAPIClient proxy){

//STEP 1: Set up delete options.var deleteOptions = new MassDeleteOptions(1033451);deleteOptions.CascadeDelete = true;

//STEP 2: Call mass delete on the ArtifactIDs you want to delete.var result =

proxy.MassDelete(proxy.APIOptions, deleteOptions, new List<int> {1033456,1033457, 1033458});

//STEP 3: Check for success.if (!result.Success){

Console.WriteLine(result.Message);return false;

}return true;

}

7.2.1.5 MassDeleteAllObjects() methodTheMassDeleteAllObjects() method removes all objects of the specified ArtifactType from theWorkspace.This code sample illustrates how to delete all objects of the specified type without using cascade delete, whichmeans that dependent objects aren't deleted.

public static bool Using_MassDelete_DeleteAllObjectsOfSpecificTypeInWorkspace(IRSAPIClient proxy){

//STEP 1: Set up delete options.var deleteOptions = new MassDeleteOptions(1033451);deleteOptions.CascadeDelete = false;

//STEP 2: Call mass delete on the object type.var result = proxy.MassDeleteAllObjects(proxy.APIOptions, deleteOptions);

//STEP 3: Check for success.if (!result.Success){

Console.WriteLine(result.Message);

Page 227: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 227

return false;}return true;

}

7.3 QueryingWith the Services API, you can perform searches using Query objects and the Query() method on theRSAPIClient class. The Query() method takes a Query object, which has Conditions that contain informationabout the search that you want to execute. In addition, you can combine Conditions with an operator tocreate compound queries.You can find code samples that illustrate how to query on a specific DTO. For more information, see DTOreference and code samples on page 81.

7.3.1 Using Query objectsYou can use the Query object to describe a search that you want execute. You must indicate the ArtifactTypefor the search by using the ArtifactTypeID, ArtifactTypeName, or ArtifactTypeGuid. You can use the Conditionproperty on a Query to provide an expression that describes the search criteria. A Condition specifies thename of a Field, a comparison operator (such as EqualTo or GreaterThan), and a value. The list of supportedcomparison operators varies by Field data type. You can use the Fields collection on the Query object tospecify Fields that you want returned for each item matching the search criteria.The Query() method returns a QueryResult object with those items that match the search Condition. TheQueryResult object has the following properties:

n QueryArtifacts - a collection of Artifacts that were found by the query.n QueryToken - when this property has a value, it indicates that the query returned more Artifacts than

number of results specified by the length parameter. See Paging on the next page.You can sort query results by specifying one or more Fields in the Sorts property on the Query object. Thisproperty is a collection of Sort objects, which takes a Field name, a sort direction (ascending/descending), anda sort precedence order. (The sort order gives a high precedence to lower numbers.)

Note: A query on multi-reflected Fields returns a list of the requested data type. For example, the value of amulti-reflected integer field returns a list of integers.

7.3.2 Available Conditions for QueryingYou can combine Conditions with the AND or OR operator to create complex queries. The Services APIprovides the following classes as condition types:

n BooleanConditionn CompositeConditionn DateTimeConditionn DecimalConditionn FileConditionn MultiChoiceCondition

Page 228: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 228

n NotConditionn ObjectConditionn ObjectsConditionn SavedSearchConditionn SingleChoiceConditionn TextConditionn UserConditionn ViewConditionn WholeNumberCondition

7.3.3 System Types supported by the Query() methodThe Query() method provides the following functionality:

n Searches for all Workspaces in Relativity, and all Fields in a specific Workspace. It supports queries forDocuments and Dynamic Objects based on specified search criteria.

n Searches on any Field in the Available Fields or the Selected Fields list available in the view for a systemtype. (The view is available through the Relativity web UI.)

This table summarizes the Relativity system types that the Services API supports.

System Types Query SupportApplication YesBatch YesBatch Sets YesChoice YesClient YesGroup YesMarkup Sets YesUser YesObject Type Yes (Artifact Type)Tab Yes (Only Workspace tab)Folder YesLayoutView YesWorkspace YesErrorField YesRelativity Scripts YesSaved Searches Yes

7.3.4 PagingIn the Services API, you can perform paging on query results that include Documents or Relativity DynamicObjects (RDOs). Paging provides the functionality used to return query results in small subsets.You can use paging in searches for Documents or RDOs by calling the Query() method and passing a lengthparameter, which determines the number of Artifacts returned by the initial page of results. You can set the

Page 229: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 229

length parameter on the QuerySubset() method to return Artifacts on subsequent pages. When the lengthparameter is set to 0, the Services API uses the default value defined for the PDVDefaultQueryCacheSizesetting on the Configuration Table. This value is set to 1000, but you can update it as necessary.The following sample code illustrates how to use paging.

var qry = new DTOs.Query<DTOs.Document>();qry.Fields = DTOs.FieldValue.AllFields;

var resultsFirst100 = Client.Repositories.Document.Query(qry, 100);string queryToken = resultsFirst100.QueryToken;

var resultsSecond100 = Client.Repositories.Document.QuerySubset(queryToken,101, 100);

7.3.4.1 Paging support for system objectsIn a Relativity workspace, all objects created by users are RDOs, so paging is supported for these objects. It isalso supported for Batch and Relativity Application, which are workspace system objects that are also RDOs.

Note: You can check the Boolean value assigned to the Dynamic property on an object to determinewhether it is a RDO.

7.3.5 Constraints on the Query() methodThe Query() method is subject to the following constraints:

n Queries are limited to only a single object type.n Conditions (that is search criteria) only support comparison against literal values, such as True/False,

"Hello World”, or 10.5. You can't compare one Field’s value against another.n The NOT Condition returns the set of all items that don't meet the negated criteria. This operator uses

set-based logic. For example, you might query for Documents using a numeric relational comparisonoperator, such as X < 5. The query for NOT X < 5 returns documents where X is Greater Than or EqualTo 5, and it also returns all documents where X is NULL (that isn't set).

n Search criteria are only applied against Fields of the object type being returned. For example, when yousearch for Documents, you can only query on Fields that are associated with the Document objecttype. You can't query against Fields on Dynamic Objects.

n The list of available comparison operators is limited and varies by Field type. This list will be expanded infuture releases.

7.3.6 SavedSearchConditionYou can use the SavedSearchCondition to execute a saved search so that you can review its results. Toexecute this query, you need the ArtifactID of the saved search stored in Relativity. You can then execute thequery by using the SavedSearchCondition on the Query() method. You can't combine any other Conditiontypes with a SavedSearchCondition.

Page 230: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 230

7.3.6.1 SelectedFields directiveYou can set the SelectedFields directive when you perform a query with SavedSearchCondition or aViewCondition. The SelectedFields directive returns only the Fields displayed on a saved search or view inRelativity. The following sample code illustrates how to use this directive.

query.Fields = Field.SelectedFields;

You aren't limited to the Fields defined by the saved search or viewwhen using a SavedSearchCondition or aViewCondition. Instead, you can specify particular Fields that you want to retrieve, or you can use the AllFieldsdirective to retrieve all Fields for an ArtifactType, such as View, User, or Document. See Field directives forDTOs on page 73.

7.3.6.2 Querying for the ArtifactID of a Saved SearchYou can query for the ArtifactID of a Saved Search. After the ArtifactID is returned, you can use it to run theSaved Search. The following code sample illustrates this process.

public static bool Query_For_Saved_SearchID(IRSAPIClient proxy){

// STEP 1: If you don't have the ArtifactID of a Saved Search, you can queryto find it.var query = new Query();query.ArtifactTypeID = (Int32)ArtifactType.Search;query.Condition = new TextCondition("Name", TextConditionEnum.Like, "BatchSearch");QueryResult result = null;

try{

result = proxy.Query(proxy.APIOptions, query);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

// STEP 2: Save the ArtifactID of the returned saved search.int searchArtifactID = result.QueryArtifacts[0].ArtifactID;

return true;}

7.3.6.3 Querying for a Document with a SavedSearchConditionAs illustrated in the following code sample, you can use the SavedSearchCondition to query for a Documentwith a saved search ID. A SavedSearchCondition can't be combined with any other Condition types.

Page 231: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 231

using System;using kCura.Relativity.Client;using kCura.Relativity.Client.DTOs;public class A{

public static void Query_Documents_By_Saved_Search_ID_Using_Repository(IRSAPIClient proxy){

//STEP 1: Create a Query to describe the search you want to run.DTOs.Query<DTOs.Document> query = new DTOs.Query<DTOs.Document>();

//STEP 2: Set Condition. For this example, Relativity contains a savedsearch with an ArtifactID of 1036604.query.Condition = new SavedSearchCondition(1036604);

//STEP 3: Set the SelectedFields directive to retrieve the fields definedby the Saved Search.query.Fields = DTOs.FieldValue.SelectedFields;

//STEP 4: Perform the query.DTOs.ResultSet<DTOs.Document> docResults =proxy.Repositories.Document.Query(query);

}}

7.3.7 Specialized queries with ConditionsYou can use Conditions when you want to perform specialized queries on Groups, Users, and Choices, as wellas to create compound queries.

7.3.7.1 Querying for Groups and UsersYou can query for Users by building a Condition against the Groups field that takes a list of Group ArtifactIDs.This Condition returns Users associated with those Groups. In addition, you can query for Groups by buildinga Condition against the Users field that takes a list of User ArtifactIDs. This Condition returns Groupsassociated with those Users.

7.3.7.2 Querying for Admin Choices by Choice TypeYou can use the Query() method to retrieve the Artifact IDs and Names of the Choices associated with aspecific Choice Type. The following Choice type field values are supported when querying by Choice, but theyaren't visible on the front end:

n Case Tabn Default Selected File Typen Document Skipn Group Statusn Passwordn Resource Server Status

Page 232: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 232

n Resource Server Typen Send new password ton Skip Default Preference

Note: Only text condition is supported on Choice Type field.

Sample Code

//STEP 1: Create a Query to describe the search you want to run.Query q = new Query();

//STEP 2: Set the ArtifactTypeName to tell Relativity the type of item you wantto search for.

q.ArtifactTypeID = 7;q.ArtifactTypeName = "Choice";

//STEP 3: Create a Fields list to indicate which fields you want returned.q.Fields.Add(new Field("Name"));q.Fields.Add(new Field("Artifact ID"));q.Condition = new TextCondition("Choice Type", TextConditionEnum.EqualTo,"Password");

7.3.7.3 Querying with complex compound conditional expressionsConditions may be combined into logical expressions using a CompositeCondition object. ACompositeCondition object can be initialized with two Conditions and an Operator (using And or Or). Inaddition, multiple CompositeConditions can be nested to create complex expressions, resulting in binary treeexpressions. Since the structure of the tree drives the precedence of operator evaluation, it may significantlyinfluence the outcome of the query. The following illustration shows how expression C1 AND C2OR C3may beevaluated.

Page 233: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 233

In the first example, the AND composite condition is the root of the Condition tree, while the OR conditionbetween C2 and C3 is given precedence. In the second example, the AND condition is given precedence and isevaluated before the OR condition at the root of the Condition tree. The following code sample illustrates howto use a CompositeCondition in a query.

//Create a TextCondition to specify the search criteria.TextCondition criteria1 = new TextCondition();criteria1.Field = "Control Number";criteria1.Operator = TextConditionEnum.In;TextCondition criteria2 = new TextCondition();criteria2.Field = "Group Identifier";criteria2.Operator = TextConditionEnum.EqualTo;criteria2.Value = "999";CompositeCondition composite = new CompositeCondition();composite.Operator = CompositeConditionEnum.And;composite.Condition1 = criteria1;composite.Condition2 = criteria2;

//Set the composite criteria as the Query's Condition.q.Condition = composite;

7.3.8 ViewConditionYou can use the ViewCondition to execute a view so that you can review its contents. To execute this query,you need the ArtifactID of the view stored in Relativity. You can then execute the query by using theViewCondition on the Query() method. You can't combine any other Condition types with a ViewCondition.

7.3.8.1 Supported Fields for ViewConditionThe Services API supports the following Fields that you can use when querying with Views:

Page 234: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 234

Fields supported for ViewConditionArtifact ID Indentation Method Relativity ApplicationsAvailable in Object Tab Last Modified By Render LinksCreated By Last Modified On SecurityCreated On Name View TypeDisplay Field Object Type VisibleGroup Definition Order Visualization TypeIndentation Definition Field Owner

7.3.8.2 SelectedFields directiveYou can set the SelectedFields directive when you perform a query with SavedSearchCondition or aViewCondition. The SelectedFields directive returns only the Fields displayed on a saved search or view inRelativity. The following sample code illustrates how to use this directive.

query.Fields = Field.SelectedFields;

You aren't limited to the Fields defined by the saved search or viewwhen using a SavedSearchCondition or aViewCondition. Instead, you can specify particular Fields that you want to retrieve, or you can use the AllFieldsdirective to retrieve all Fields for an ArtifactType, such as View, User, or Document. See Field directives forDTOs on page 73.

7.3.8.3 Querying for the ArtifactID of a ViewYou can query for the ArtifactID of a View and then set a the ViewCondition with it. When the query executes,it retrieves Fields from the View as illustrated in the following sample code.

public static bool Query_And_Execute_By_ViewID(IRSAPIClient proxy){

//STEP 1: If you don't have the ArtifactID of a View, you can query to findit.var query = new DTOs.Query<View>();query.Condition = new TextCondition(ViewFieldNames.Name,TextConditionEnum.EqualTo, "All Fields");DTOs.QueryResultSet<View> result = null;

try{

result = proxy.Repositories.View.Query(query);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

Page 235: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 235

//Save the ArtifactID of the returned view.var viewID = result.Results[0].Artifact.ArtifactID;

//STEP 2: Create a new Query to execute the View.var executeViewQuery = new Query<DTOs.Field>();

//STEP 3: Set a ViewCondition used to pass the ArtifactID of the View.executeViewQuery.Condition = new ViewCondition(viewID);executeViewQuery.Fields = FieldValue.AllFields;

//STEP 4: Call the Query method on the Field Repository.DTOs.QueryResultSet<DTOs.Field> executeViewResult = null;

try{

executeViewResult = proxy.Repositories.Field.Query(executeViewQuery, 5);}catch (Exception ex){

Console.WriteLine(string.Format("An error occurred: {0}", ex.Message));return false;

}

//Check for success.if (executeViewResult.Success){

Console.WriteLine("Retrieved first 5 fields from View 'All Fields':");

foreach (Result<DTOs.Field> field in executeViewResult.Results){

Console.WriteLine("Field Name: {0}. Object Type: {1}. Field Type:{2}.", field.Artifact.Name,

field.Artifact.ObjectType.DescriptorArtifactTypeID,field.Artifact.FieldTypeID);

}}else{

Console.WriteLine("Error retrieving fields.");}return true;

}

7.3.8.4 Searching for Fields with a ViewConditionAs illustrated in the following code sample, you can use the ViewCondition to search for Fields by their view ID.A ViewCondition can't be combined with any other Condition types.

Page 236: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 236

using System;using kCura.Relativity.Client;using kCura.Relativity.Client.DTOs;

public class A{

public static void Query_Fields_By_Field_View_ID_Using_Repository(IRSAPIClient proxy){

//STEP 1: Create a Query to describe the search you want to run.DTOs.Query<DTOs.Field> query = new DTOs.Query<DTOs.Field>();

//STEP 2: Set Condition. For this example, Relativity contains a viewwith an ArtifactID of 1003689.query.Condition = new ViewCondition(1003689);

//STEP 3: Set the SelectedFields directive to retrieve the fields definedby the view.query.Fields = DTOs.FieldValue.SelectedFields;

//STEP 4: Perform the query.DTOs.ResultSet<DTOs.Field> docResults = proxy.Repositories.Field.Query(query);

}}

8 Troubleshooting the Services APIYou can use the following information to identify the causes of Services API errors. It also provides samplecode for writing errors to a log file. For more information about capturing errors, seeWriting to the error logon page 112.

8.1 Common causes of Services API errorsIn the Services API, the following conditions result in an error:

n Required fields aren't included in a method calln Permission levels are inadequate for the specified operationn Values passed to methods aren't within a predefined range or object type

For many operations, a message indicating an error is returned in the ResultSet collection. Each object in thecollection has a Success/Status field of type Boolean and Message description field. When an error occurs, theSuccess/Status field is set to False, and an error description is added to theMessage field. The Services APIthrows an exception when a communication failure, timeout, or other serious error occurs, which istransmitted back to the client as a SOAP Fault that can be caught.

Page 237: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 237

8.2 Error occurs when machines in a workgroup attempt to loginIf you receive an error when machines that are part of a workgroup attempt to log in to the Services API, youneed to synchronize your client and server clocks. (Machines on the domain are already synchronized withthe server.) By default, clock synchronization has a 5minute range. For information about synchronizingclient and server clocks, see this Microsoft article (http://technet.microsoft.com/en-us/library/cc779145(WS.10).aspx).

Page 238: Relativity Services API Guide · Relativity|ServicesAPIGuide-4 5.3ClientProxy 59 5.3.1BackwardsCompatibility 59 5.4DeployingtheServicesAPI 60 5.4.1DeployingtheServicesAPI 60 5.4.2Transportprotocols

Relativity | Services API Guide - 238

Proprietary RightsThis documentation (“Documentation”) and the software to which it relates (“Software”) belongs to kCuraCorporation and/or kCura’s third party software vendors. kCura grants written license agreements whichcontain restrictions. All parties accessing the Documentation or Softwaremust: respect proprietary rights ofkCura and third parties; comply with your organization’s license agreement, including but not limited tolicense restrictions on use, copying, modifications, reverse engineering, and derivative products; and refrainfrom any misuse or misappropriation of this Documentation or Software in whole or in part. The Software andDocumentation is protected by the Copyright Act of 1976, as amended, and the Software code is protectedby the Illinois Trade Secrets Act. Violations can involve substantial civil liabilities, exemplary damages, andcriminal penalties, including fines and possible imprisonment.©2013. kCura Corporation. All rights reserved. Relativity® and kCura® are registered trademarks of kCuraCorporation.