Skip to main content
This example shows how to upload bank account applications to the server and capture the customers’ data.

What the example does

The example code performs the following steps:
  • Connects to the service
  • Opens a session
  • Opens the project
  • Creates a new batch
  • Adds images to the batch
  • Starts processing the batch
  • Gets the results and displays the captured data
  • Closes the session

Set up the example

1

Upload the project file to the server

Upload the UnattendedExample.fcproj project file to the server.
2

Open the solution in Visual Studio

Open UnattendedExample.sln in Visual Studio 2013 or later.

Connect to the service

// Create an instance of the web service client
var service = new FlexiCapture.FlexiCaptureWebServiceSoapClient();
// ======= BASIC AUTHENTICATION =======
// service.ClientCredentials.UserName.UserName = "username";
// service.ClientCredentials.UserName.Password = "password";

Open a session

// To secure your batches against unauthorized access, specify the current user
// First, get the name of the user visible to the system
var username = service.GetCurrentUserIdentity();
// Next, find yourself among the FlexiCapture users
var userId = service.FindUser(username.Name);
if (userId <= 0) throw new Exception("Current user not found");
// Open a new processing session
const int roleType = 12; //The operator role on the user's station
const int stationType = 10; //The user's station
var sessionId = service.OpenSession(roleType, stationType);
if (sessionId <= 0) throw new Exception("Couldn't open the session");

Open the project

// Get the projects
var projects = service.GetProjects();
var projectGuid = "";
if (projects != null && projects.Count > 0)
{
    foreach (var project in projects)
    {
        if (project.Name != "UnattendedExample") continue;
        projectGuid = project.Guid;
        break;
    }
}
if (string.IsNullOrEmpty(projectGuid))
{
    throw new Exception("Can't find the UnattendedExample project. You must upload this project to the server to be able to work with this example.");
}
// Open the first project named UnattendedExample
var projectId = service.OpenProject(sessionId, projectGuid);
if (projectId <= 0) throw new Exception("Couldn't open the project");

Create a new batch

// Specify a name for the new batch and keep the other properties unchanged
var batch = new FlexiCapture.Batch { Name = "Sample API Batch" };
var batchId = service.AddNewBatch(sessionId, projectId, batch, userId);
if (batchId <= 0) throw new Exception("Couldn't create the batch");

Add images to the batch

// Open the batch where to add images
service.OpenBatch(sessionId, batchId);

Upload files smaller than 256 KB

service.AddNewImage(sessionId, batchId, new FlexiCapture.File()
{
    Bytes = File.ReadAllBytes(filename),
    Name = filename
});

Upload larger files

Uploading files larger than 256 KB in their entirety in Base64 has the following drawbacks:
  • Network load increases by 33%.
  • Very large requests may be blocked by IIS or by the firewall.
  • If the connection is lost or there are network errors, you must resend the file.
Uploading files through the file service API is much more efficient:
var doc = new FlexiCapture.Document { BatchId = batchId };
var file = new FlexiCapture.File { Name = filename };
var documentId = service.AddNewDocument(sessionId, doc, file, false, 0);
UploadFile(service, sessionId, projectId, batchId, documentId, filename).Wait();

Upload a file to the server

The UploadFile method reads the file and sends it to the file service in 1 MB portions, then verifies the upload with a checksum:
private static async Task UploadFile(FlexiCapture.FlexiCaptureWebServiceSoapClient service, int sessionId, int projectId,
    int batchId, int documentId, string filename)
{
    const int objectType = 0;
    var crc = new Crc32();
    using (var fs = File.OpenRead(filename))
    {
        // Uploading file in portions of 1 MB
        var buffer = new byte[0x100000];
        var readed = fs.Read(buffer, 0, buffer.Length);
        var checksum = crc.Next(buffer, 0, readed);
        if (readed < buffer.Length)
        {
            // Uploading smaller files in their entirety
            var resp = await FileRequest(service, "Save", objectType, sessionId, projectId, batchId, 0, documentId, 0, filename, 0,
                new ByteArrayContent(buffer, 0, readed));
            if (resp.StatusCode != HttpStatusCode.OK) throw new Exception("Server error");
        }
        else
        {
            var offset = 0;
            while (readed > 0)
            {
                var action = offset == 0 ? "BeginSaveChunked" : "Append";
                await FileRequest(service, action, objectType, sessionId, projectId, batchId, 0, documentId, 0, filename,
                    offset, new ByteArrayContent(buffer, 0, readed));
                offset += readed;
                readed = fs.Read(buffer, 0, buffer.Length);
                checksum = crc.Next(buffer, 0, readed);
            }
            var resp = await FileRequest(service, "Commit", objectType, sessionId, projectId, batchId, 0, documentId, 0, filename);
            if (resp.StatusCode != HttpStatusCode.OK) throw new Exception("Server error");
        }
        var response = await FileRequest(service, "Checksum", objectType, sessionId, projectId, batchId, 0, documentId, 0, filename);
        var text = await response.Content.ReadAsStringAsync();
        if (uint.Parse(text, NumberStyles.HexNumber) != checksum)
        {
            throw new Exception("An error occurred when uploading the file");
        }
    }
}

Send a file request with file content

The FileRequest method has two overloads that send an action to the file service. The first sends the file content as multipart form data:
private static async Task<HttpResponseMessage> FileRequest(FlexiCapture.FlexiCaptureWebServiceSoapClient service, string action,
    int objectType, int sessionId, int projectId, int batchId, int parentId, int objectId, int version, string streamName, int offset, HttpContent file)
{
    var creds = CredentialCache.DefaultNetworkCredentials;
    if (!string.IsNullOrEmpty(service.ClientCredentials.UserName.UserName))
        creds = new NetworkCredential(service.ClientCredentials.UserName.UserName, service.ClientCredentials.UserName.Password);
    using (var handler = new HttpClientHandler { Credentials = creds })
    using (var client = new HttpClient(handler))
    {
        var uri = service.Endpoint.Address.Uri;
        var content = new MultipartFormDataContent
        {
            {new StringContent(action), "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(Convert.ToBase64String(Encoding.Unicode.GetBytes(streamName))), "streamName"},
        };
        if (offset > 0)
        {
            content.Add(new StringContent(offset.ToString()), "offset");
        }
        content.Add(file, "blob", "data.txt");
        return await client.PostAsync(uri.OriginalString.Replace("/API/v1/Soap", "/FileService/v1"), content);
    }
}

Send a file request without file content

The second overload sends a request without file content, using form URL encoding:
private static async Task<HttpResponseMessage> FileRequest(FlexiCapture.FlexiCaptureWebServiceSoapClient service, string action,
    int objectType, int sessionId, int projectId, int batchId, int parentId, int objectId, int version, string streamName)
{
    var creds = CredentialCache.DefaultNetworkCredentials;
    if (!string.IsNullOrEmpty(service.ClientCredentials.UserName.UserName))
        creds = new NetworkCredential(service.ClientCredentials.UserName.UserName, service.ClientCredentials.UserName.Password);
    using (var handler = new HttpClientHandler { Credentials = creds })
    using (var client = new HttpClient(handler))
    {
        var uri = service.Endpoint.Address.Uri;
        var content = new FormUrlEncodedContent(new Dictionary<string, string>
        {
            {"Action", action},
            {"objectType", objectType.ToString()},
            {"sessionId", sessionId.ToString()},
            {"projectId", projectId.ToString()},
            {"batchId", batchId.ToString()},
            {"parentId", parentId.ToString()},
            {"objectId", objectId.ToString()},
            {"version", version.ToString()},
            {"streamName", streamName},
        });
        return await client.PostAsync(uri.OriginalString.Replace("/API/v1/Soap", "/FileService/v1"), content);
    }
}

Start and end batch processing

// Star processing the batch
service.ProcessBatch(sessionId, batchId);
Console.WriteLine("recognition task created, waiting ");
// Wait for the processing to complete
var percentCompleted = 0;
while (percentCompleted < 100)
{
    Console.CursorLeft = 0;
    Console.Write(percentCompleted + "%");
    percentCompleted = service.GetBatchPercentCompleted(batchId);
    System.Threading.Thread.Sleep(500);
}
Console.CursorLeft = 0;
Console.WriteLine("complete...");

Get the results and display the captured data

From each document, only three fields are displayed:
  • Addressing
  • First Name
  • Last Name
// Get the results
var documents = service.GetDocuments(sessionId, batchId);
if (documents == null) return;
// XML names required for parsing the XML results
var docs = XName.Get("Documents", "https://www.abbyy.com/FlexiCapture/Schemas/Export/FormData.xsd");
var banking = XName.Get("_Banking_eng", "https://www.abbyy.com/FlexiCapture/Schemas/Export/Banking_eng.xsd");
// Iterate all the results and display the on the screen
foreach (var document in documents)
{
    if (document.Id == 0) continue;
    // Get the XML file with the recognized data
    var attachedFile = service.LoadDocumentResult(sessionId, batchId, document.Id, "Result.xml");
    if (attachedFile.Bytes == null) continue;
    // Open the results in XML
    var xml = XDocument.Load(new MemoryStream(attachedFile.Bytes));
    var docsElement = xml.Element(docs); // Container for recognized data
    if (docsElement == null) continue;
    var result = docsElement.Element(banking);
    if (result == null) continue;
    // Get the required data
    var addressing = result.Element("_Addressing");
    var surname = result.Element("_Last_Name");
    var name = result.Element("_First_Name");
    // Display the data
    Console.WriteLine("- " +
        (addressing == null ? "" : addressing.Value) + " " +
        (name == null ? "" : name.Value) + " " +
        (surname == null ? "" : surname.Value)
    );
}

Close the session

service.DeleteBatch(sessionId, batchId);
service.CloseProject(sessionId, projectId);
service.CloseSession(sessionId);