> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Example of manual processing

> Walk through an ABBYY FlexiCapture API example that adds a custom service stage to review tasks, accept or reject documents, and attach a digital signature.

This example shows how to create an additional stage of manual data processing. For example, the security department of your company can use this stage to check and confirm the sending of documents that meet specific conditions for further processing, and to reject documents that do not meet these conditions.

Each confirmed document is accompanied by a set of bytes that imitate a digital signature.

## What the example does

The example performs the following steps:

* Configures the connection
* Starts working with the project
* Gets and processes the list of tasks
* Processes each task at the service stage
* Uploads the file to the server
* Closes the session

## Run the example

<Steps>
  <Step title="Open the solution in Visual Studio">
    Start `UserStageExample.sln` in Visual Studio 2013 or a newer version.
  </Step>

  <Step title="Enter the Application Server URL">
    Enter the URL of the Application Server.
  </Step>

  <Step title="Select an authentication type">
    Select an authentication type.
  </Step>

  <Step title="Log in">
    Click **Login**.
  </Step>
</Steps>

## Configure the connection

```csharp theme={null}
private const string FlexiHandlerPath = "/FlexiCapture12/Server/{0}API/v1/Soap"; // Path to FlexiCapture API
private const string FlexiCaptureAuthPart = "FCAuth/"; // Path to authenticate FlexiCapture
private const string UserStageProjectName = "UserStageExample"; // The name of the project used in this example
private const string UserStageName = "Service"; // The name of the service stage
// Creating new binding
var binding = new BasicHttpBinding();
// The size of a message it too small for FlexiCapture and we need to increase it
binding.MaxReceivedMessageSize = MessageSize;
// Selecting a new connection security mode depending on a protocol
binding.Security.Mode = serverUri.Scheme == Uri.UriSchemeHttps
   ? BasicHttpSecurityMode.Transport
   : BasicHttpSecurityMode.TransportCredentialOnly;
// Selecting the authentication method
binding.Security.Transport.ClientCredentialType = windowsAuth
   ? HttpClientCredentialType.Windows
   : HttpClientCredentialType.Basic;
// Selecting the path to API depending on the authentication method
var externalSuffix = windowsAuth ? string.Empty : FlexiCaptureAuthPart;
var remoteAddress = new EndpointAddress(new Uri(serverUri, string.Format(FlexiHandlerPath, externalSuffix)));
// Creating a SOAP client
_client = new FlexiCapture.FlexiCaptureWebServiceSoapClient(binding, remoteAddress);
// To authenticate FlexiCapture, specify a login and password
if (_client.ClientCredentials != null && !windowsAuth)
{
   _client.ClientCredentials.UserName.UserName = login;
   _client.ClientCredentials.UserName.Password = password;
}
```

## Start working with the project

```csharp theme={null}
// Open the session
_sessionId = _client.OpenSession(RoleType, WorkstationType);
var projectGuid = string.Empty;
// Find the required project
foreach (var project in _client.GetProjects())
{
   if (project.Name == UserStageProjectName)
   {
      projectGuid = project.Guid;
   }
}
if (string.IsNullOrEmpty(projectGuid))
{
   MessageBox.Show("The server does not contain the UserStageExample project which is needed for this example");
}
// Open the project
_projectId = _client.OpenProject(_sessionId, projectGuid);
// Find and save the service stage identifier
var stages = _client.GetProcessingStages(_projectId, 0, 0, UserStageName);
if (stages.Count != 1) throw new Exception("Invalid project");
   _serviceStageId = stages[0].Id;
// Find and save the external ID of the exceptions stage
stages = _client.GetProcessingStages(_projectId, 0, ExceptionStageType, string.Empty);
if (stages.Count != 1) throw new Exception("Invalid project");
   _exceptionsStageId = stages[0].ExternalId;
```

## Get and process tasks pending at the service stage

```csharp theme={null}
// Getting the list of tasks
var tasks = _client.GetAvailableTasksByStageId(_sessionId, _projectId,
new FlexiCapture.stageIds() { _serviceStageId }, false);
var result = new Dictionary<int, Task>();
if (tasks == null || tasks.Count == 0) return result;
foreach (var task in tasks)
{
   // For each task an object of the Task type is created
   var item = new Task
   {
      Id = task.Id,
      BatchId = task.BatchId
   };
   // Getting the list of documents of the task
   var documents = _client.GetTaskDocuments(task.Id);
   if (documents == null || documents.Count == 0) continue;
   foreach (var document in documents)
   {
      // Loading the XML of the task
      var file = _client.LoadDocumentResult(_sessionId, document.BatchId, document.Id, "DocumentBody"); // "DocumentBody" - the name of the file that contains recognized data
      if (file == null || file.Bytes == null) continue;
      // Disassembling XML
      var doc = new Document(document.Id, XDocument.Load(new MemoryStream(file.Bytes)));
      // Saving the disassembled list of documents
      item.Documents.Add(document.Id, doc);
   }
   result.Add(item.Id, item);
}
```

## Send the task for further processing

```csharp theme={null}
var ids = new FlexiCapture.docIds();
foreach (var rejectedDocument in rejectedDocuments)
{
   ids.Add(rejectedDocument.Id);
}
if (ids.Count > 0)
{
   _client.CreateTask(_sessionId, batchId, _exceptionsStageId, 0, "Rejection reason", 0, ids, false);
}
_client.OpenBatch(_sessionId, batchId);
var hasDocuments = false;
try
{
   var uri = _client.Endpoint.Address.Uri.OriginalString.Replace("/API/v1/Soap", "/FileService/v1");
   foreach (var document in acceptedDocuments)
   {
      hasDocuments = true;
      var buffer = new byte[SignatureSize]; // The size of the digital signature added to documents: 1024
      _rng.GetBytes(buffer);
      //DocumentAttachment: The attachment type (9 - document attachment)
      _client.SaveAttachment(_sessionId, DocumentAttachment, document.Id, batchId, _projectId, new FlexiCapture.File
      {
         Bytes = buffer,
         Name = "Signature.dat"
      });
      document.CreateStamp();
      UploadTextFileToServer(new Uri(uri),
         _client.ClientCredentials.UserName.UserName,
         _client.ClientCredentials.UserName.Password,
         document.GetXml(), 0, _sessionId, _projectId,
         batchId, 0, document.Id, 0, "DocumentBody"
      ).Wait();
   }
};
```

## Upload the file to the server

```csharp theme={null}
private static async Task<string> UploadTextFileToServer(Uri server, string login, string password,
        string stream, int objectType, int sessionId, int projectId, int batchId, int parentId,
        int objectId, int version, string streamName)
{
        var creds = CredentialCache.DefaultNetworkCredentials;
        if (!string.IsNullOrEmpty(login)) creds = new NetworkCredential(login, password);
        using (var handler = new HttpClientHandler { Credentials = creds })
        using (var client = new HttpClient(handler))
        {
                var encodedStreamName = Convert.ToBase64String(Encoding.Unicode.GetBytes(streamName));
                var content = new MultipartFormDataContent
                {
                        {new StringContent("Save"), "Action"},
                        {new StringContent(objectType.ToString()), "objectType"},
                        {new StringContent(sessionId.ToString()), "sessionId"},
                        {new StringContent(projectId.ToString()), "projectId"},
                        {new StringContent(batchId.ToString()), "batchId"},
                        {new StringContent(parentId.ToString()), "parentId"},
                        {new StringContent(objectId.ToString()), "objectId"},
                        {new StringContent(version.ToString()), "version"},
                        {new StringContent(encodedStreamName), "streamName"},
                        {new ByteArrayContent(Encoding.Unicode.GetBytes(stream)), "blob", "data.txt"}
                };
                var msg = client.PostAsync(server, content).Result;
                return await msg.Content.ReadAsStringAsync();
        }
}
```

## Close the session

```csharp theme={null}
_client.CloseProject(_sessionId, _projectId);
   _client.CloseSession(_sessionId);
```
