To carry out the Document Entity service, the software developers need to consume the Binary Entity service too. Both services work closely together. This document provides a step-by-step guide to do this using Microsoft Visual Studio 2012 as an example.
This example will do the following:
1. Retrieve document data based on the ID of the document.
2. Attachment of a retrieved document can be downloaded.
3. Create a document. Attachment can be uploaded if there is attachment selected.
Imports System.Xml
Imports System.IO
Imports System.Text
PublicClassForm1
PrivateConst BINARYENTITY AsString = "Binary"
PrivateConst DOCUMENTENTITY AsString = "Document"
Private entityClient As Exact.Services.Client.Entity.EntityClientEG
Private entityData As Exact.Services.Client.Data.EntityData
Private RetEntityData As Exact.Services.Client.Data.EntityData
Private fileName AsString
Private BodyID AsString
Private AttachmentID AsString
PrivateSub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlesMyBase.Load
Text = "Binary sample application"
Button4.Text = "Create" : Button1.Text = "Retrieve"
Button3.Text = "Browse" : Button2.Text = "Download"
Label1.Text = "URL:Port" : Label12.Text = "http://<server>:8010/Services"
Label3.Text = "Server" : Label4.Text = "Database"
Label9.Text = "Subject" : Label10.Text = "Body"
Label11.Text = "Attachment" : Label5.Text = "Document ID"
Label6.Text = "HID" : Label7.Text = "File name"
Label8.Text = "Download path"
GroupBox1.Text = "For retrieve"
GroupBox2.Text = "For create"
TextBox4.Multiline = True
TextBox10.Text = "http://change_me:8010/services"
TextBox1.Text = "change_me"
TextBox2.Text = "001"
EndSub
''' <summary>
''' To create a new record by using Entity Create function
''' 1. Fill in Subject, Body and select a File as to attach to the document.
''' 2. Call the Chunk function to convert data into binary and chunk it. Chunk function will upload the binaries.
''' 3. Create document using entity client.
''' 4 Fill up the screen with the return value from entity client.
''' 7. Use Try-Catch statement to catch the exception during Create operations
''' </summary>
PrivateSub Button1_Click(ByVal sender AsObject, ByVal e As System.EventArgs) Handles Button4.Click
Try
Connect()
BodyID = String.Empty
AttachmentID = String.Empty
ChunkService()
FillData(entityClient.Create(GetFormData()))
Catch fe As System.ServiceModel.FaultException(Of Exact.Services.Client.Data.EntityFault)
ShowError(fe)
Catch ex AsException
MsgBox(ex.Message)
EndTry
''' To retrieve an existing record by using Entity Retrieve function
''' 1. Assigning a Document ID (key value) and IsBinaryServiceEnabled to get binaries prepared for download.
''' 2. Retrieve Document ID using Entity client.
''' 3. Record will be retrieved and this inclusive of the Binary ID if there are any (i.e. Body and Document)
''' 4. Binary ID of Body will be returned, and populate on the body text box
''' 5. Use Try-Catch statement to catch the exception during Retrieve operations
PrivateSub Button2_Click(ByVal sender AsObject, ByVal e As System.EventArgs) Handles Button1.Click
Dim data AsNew Exact.Services.Client.Data.EntityData
data.EntityName = DOCUMENTENTITY
IfNotString.IsNullOrWhiteSpace(TextBox6.Text) Then Data.Properties.Add(New Exact.Services.Client.Data.PropertyDataWith {.Name = "ID", .Value = TextBox6.Text})
Data.Properties.Add(New Exact.Services.Client.Data.PropertyDataWith {.Name = "IsBinaryServiceEnabled", .Value = True})
FillData(entityClient.Retrieve(data))
IfNotString.IsNullOrWhiteSpace(BodyID) Then GetBodyData(BodyID)
''' Select a file as an attachment to attach to the document
''' </summary>'''
PrivateSub Button3_Click(ByVal sender AsObject, ByVal e As System.EventArgs) Handles Button3.Click
If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
If OpenFileDialog1.FileNames.Count > 0 Then
ForEach selectedFilenamePath AsStringIn OpenFileDialog1.FileNames
TextBox5.Text = selectedFilenamePath
fileName = OpenFileDialog1.SafeFileName
Next
Else
TextBox5.Text = OpenFileDialog1.FileName
EndIf
''' 1. This button will only be triggered after a Retrieve action is performed.
''' 2. The download button is to retrieve the attachment file
''' 3. The file will be stored in C drive
PrivateSub Button4_Click(ByVal sender AsObject, ByVal e As System.EventArgs) Handles Button2.Click
IfString.IsNullOrWhiteSpace(AttachmentID) Then
MessageBox.Show("No atachment found")
GetBinaryData(AttachmentID)
''' 1. Retrieve a body content from the Binary EntityData object
''' 2. Convert the content from a binary data to text format
''' 3. Merge the text and convert again if there are more than 1 packet of binary file
PrivateSub GetBodyData(ByVal BinaryID AsString)
Dim Data AsNew Exact.Services.Client.Data.EntityData
Dim Sequence AsInteger = 0
Dim uniEncoding AsEncoding = Encoding.ASCII
Dim BodyDetail AsString = ""
Data = PopulateERData(BinaryID, 0)
RetEntityData = entityClient.Retrieve(Data)
Dim chunk AsByte()
chunk = RetEntityData.Properties("Data").Value
WhileNot IsNothing(chunk)
For i AsInteger = LBound(chunk) To UBound(chunk)
BodyDetail = Chr(chunk(i))
BodyDetail = BodyDetail.Substring(0, 1)
TextBox4.Text = TextBox4.Text & BodyDetail
chunk = Nothing
Sequence = Sequence + 1
Data = PopulateERData(BinaryID, Sequence)
EndWhile
''' 1. Retrieve a document attachment from the Binary EntityData object
''' 2. Specify a location to store the file
''' 3. Get the binary data and merge it repetitively based on the number packet the attachment was chunked earlier
PrivateSub GetBinaryData(ByVal BinaryID AsString)
TextBox9.Text = "C:\" & TextBox8.Text
Dim fs AsNewFileStream(TextBox9.Text, FileMode.OpenOrCreate, FileAccess.Write)
Dim writer AsBinaryWriter = NewBinaryWriter(fs)
writer.Write(chunk, 0, chunk.Length)
writer.Flush()
Finally
writer.Close()
fs.Close()
MessageBox.Show("Download")
''' Helper function to assign binary details to Binary EntityData
PrivateFunction PopulateERData(ByVal BinaryID AsString, ByVal Sequence AsInteger) As Exact.Services.Client.Data.EntityData
Dim Data AsNew Exact.Services.Client.Data.EntityData()
Data.EntityName = BINARYENTITY
Data.Properties.Add(New Exact.Services.Client.Data.PropertyDataWith {.Name = "MessageID", .Value = BinaryID})
Data.Properties.Add(New Exact.Services.Client.Data.PropertyDataWith {.Name = "Sequence", .Value = Sequence})
Return Data
EndFunction
''' Helper function to assign text fields value to Document EntityData
PrivateFunction GetFormData() As Exact.Services.Client.Data.EntityData
Data.EntityName = DOCUMENTENTITY
IfNotString.IsNullOrWhiteSpace(BodyID) Then Data.Properties.Add(New Exact.Services.Client.Data.PropertyDataWith {.Name = "MessageIDBody", .Value = BodyID})
IfNotString.IsNullOrWhiteSpace(TextBox3.Text) Then Data.Properties.Add(New Exact.Services.Client.Data.PropertyDataWith {.Name = "Subject", .Value = TextBox3.Text})
IfNotString.IsNullOrWhiteSpace(fileName) Then Data.Properties.Add(New Exact.Services.Client.Data.PropertyDataWith {.Name = "FileName", .Value = fileName})
IfNotString.IsNullOrWhiteSpace(AttachmentID) Then Data.Properties.Add(New Exact.Services.Client.Data.PropertyDataWith {.Name = "MessageIDDocument", .Value = AttachmentID})
''' Helper function to assign EntityData to Text fields
PrivateSub FillData(ByVal Data As Exact.Services.Client.Data.EntityData)
BodyID = Data.Properties("MessageIDBody").Value
AttachmentID = Data.Properties("MessageIDDocument").Value
TextBox3.Text = Data.Properties("Subject").Value
TextBox4.Text = ""
TextBox6.Text = Data.Properties("ID").Value
TextBox7.Text = Data.Properties("HID").Value
TextBox8.Text = Data.Properties("FileName").Value
''' To capture the error which return by entity services
PrivateSub ShowError(ByVal fe As System.ServiceModel.FaultException(Of Exact.Services.Client.Data.EntityFault))
Dim sb AsNew System.Text.StringBuilder
sb.AppendLine("An error has occured!")
sb.AppendFormat("{0}: {1}" & vbCrLf, "Exception Type", fe.Reason.ToString)
sb.AppendFormat("{0}: {1}" & vbCrLf, "Exception Message", fe.Message)
sb.AppendLine("")
If fe.Detail.Exceptions.Count > 0 Then
ForEach info As Exact.Services.Client.Data.WSExceptionInfoIn fe.Detail.Exceptions
With sb
.AppendFormat("{0}: {1}" & vbCrLf, "Property", info.PropertyName)
.AppendFormat("{0}: {1}" & vbCrLf, "Message", info.Message)
.AppendLine("")
EndWith
MessageBox.Show(sb.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
PrivateSub Connect()
entityClient = New Exact.Services.Client.Entity.EntityClientEG(TextBox10.Text, TextBox1.Text, TextBox2.Text)
''' Helper function to trigger the chunking function
PrivateSub ChunkService()
Dim FilePathCollector AsNewCollection
If TextBox4.Text <> ""Then
FilePathCollector.Add(TextBox4.Text, "Body")
ChunkImage(Data, FilePathCollector)
FilePathCollector.Clear()
If TextBox5.Text <> ""Then
FilePathCollector.Add(TextBox5.Text, "Document")
''' To chunk data into smaller size.
''' 1. Read the body content and the attachment file
''' 2. Calculate the total size of the data and chunk it into smaller size. The default size is set to 50kb.
''' 3. For every chunk, the data will be passed to the Binary EntityData object.
''' 4. A unique ID or Message ID will be returned when the binary is saved successfully.
''' 5. The total number of chunk will be keep tracked in the metadata called Sequence.
''' 6. and the details will be stored in the metadata called Data.
PrivateFunction ChunkImage(ByVal entityName As Exact.Services.Client.Data.EntityData, ByVal FilePath AsCollection) AsBoolean
Dim Data AsNew Exact.Services.Client.Data.PropertyData
Dim i AsInteger = 0
Dim fileLength AsInteger
Dim sTempFileName AsString = Path.GetTempFileName()
Dim fsTemp AsNewFileStream(sTempFileName, FileMode.Create)
Dim uniEncoding AsEncoding = Encoding.UTF8
If FilePath.Count > 0 Then
Cursor = Cursors.WaitCursor
Dim fileInfo AsFileInfo
Dim chunkSize AsInteger = 50 * 1024 '50KB
Dim countLog AsInteger = 0
ForEach selectedFilenamePath AsStringIn FilePath
If FilePath.Contains("Body") Then
fsTemp.Write(uniEncoding.GetBytes(selectedFilenamePath), 0, uniEncoding.GetByteCount(selectedFilenamePath))
fsTemp.Close()
selectedFilenamePath = sTempFileName
fileInfo = NewFileInfo(selectedFilenamePath)
Dim fileSizeInBytes AsLong = fileInfo.Length
Dim MsgID AsString = "00000000-0000-0000-0000-000000000000"
Using iStream AsNewFileStream(selectedFilenamePath, FileMode.Open, FileAccess.Read, FileShare.Read)
Dim lastPacketDataSize AsLong = fileSizeInBytes Mod chunkSize
Dim totalChunkPackets AsInteger = Int((fileSizeInBytes / chunkSize)) + IIf(lastPacketDataSize > 0, 1, 0)
Dim completePacketData() AsByte = Nothing
completePacketData = NewByte(chunkSize - 1) {}
Dim countPacket AsInteger = 0
Dim chunkSequenceNumber AsInteger
Dim chunkPacketToWrite() AsByte
Dim dataToRead AsLong = iStream.Length
While dataToRead > 0
If countPacket = totalChunkPackets - 1 Then
Dim lastPacketData() AsByte = Nothing
lastPacketData = NewByte(lastPacketDataSize - 1) {}
fileLength = iStream.Read(lastPacketData, 0, lastPacketDataSize)
chunkPacketToWrite = lastPacketData
fileLength = iStream.Read(completePacketData, 0, chunkSize)
chunkPacketToWrite = completePacketData
entityName.Properties.Add(New Exact.Services.Client.Data.PropertyData() With {.Name = "MessageID", .Value = MsgID})
entityName.Properties.Add(New Exact.Services.Client.Data.PropertyData() With {.Name = "Sequence", .Value = countPacket})
Dim bImg AsByte()
bImg = chunkPacketToWrite
entityName.Properties.Add(New Exact.Services.Client.Data.PropertyData() With {.Name = "Data", .Value = bImg})
RetEntityData = entityClient.Create(entityName)
MsgID = RetEntityData.Properties("MessageID").Value
'Reset collection
entityName.Properties.Clear()
IfNotString.IsNullOrEmpty(chunkSequenceNumber) Then
dataToRead = dataToRead - fileLength
'Count total packet
countPacket += 1
countPacket -= 1
Application.DoEvents()
iStream.Close()
EndUsing
If FilePath.Contains("Body") Then BodyID = MsgID
If FilePath.Contains("Document") Then AttachmentID = MsgID
If FilePath.Contains("Body") ThenFile.Delete(sTempFileName)
MessageBox.Show(ex.Message)
Cursor = Cursors.Default
ReturnTrue
ReturnFalse
EndClass