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
EndSub
''' <summary>
''' 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
''' </summary>
PrivateSub Button2_Click(ByVal sender AsObject, ByVal e As System.EventArgs) Handles Button1.Click
Try
Connect()
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)
Catch fe As System.ServiceModel.FaultException(Of Exact.Services.Client.Data.EntityFault)
ShowError(fe)
Catch ex AsException
MsgBox(ex.Message)
EndTry
EndSub
''' <summary>
''' 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
EndIf
EndSub
''' <summary>
''' 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
''' </summary>
PrivateSub Button4_Click(ByVal sender AsObject, ByVal e As System.EventArgs) Handles Button2.Click
Try
IfString.IsNullOrWhiteSpace(AttachmentID) Then
MessageBox.Show("No atachment found")
Else
GetBinaryData(AttachmentID)
EndIf
Catch fe As System.ServiceModel.FaultException(Of Exact.Services.Client.Data.EntityFault)
ShowError(fe)
Catch ex AsException
MsgBox(ex.Message)
EndTry
EndSub
''' <summary>
''' 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
''' </summary>
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)
Try
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
Next
chunk = Nothing
Sequence = Sequence + 1
Data = PopulateERData(BinaryID, Sequence)
RetEntityData = entityClient.Retrieve(Data)
chunk = RetEntityData.Properties("Data").Value
EndWhile
Catch ex AsException
EndTry
EndSub
''' <summary>
''' 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
''' </summary>
PrivateSub GetBinaryData(ByVal BinaryID AsString)
Dim Data AsNew Exact.Services.Client.Data.EntityData
Dim Sequence AsInteger = 0
TextBox9.Text = "C:\" & TextBox8.Text
Data = PopulateERData(BinaryID, 0)
RetEntityData = entityClient.Retrieve(Data)
Dim fs AsNewFileStream(TextBox9.Text, FileMode.OpenOrCreate, FileAccess.Write)
Dim writer AsBinaryWriter = NewBinaryWriter(fs)
Try
Dim chunk AsByte()
chunk = RetEntityData.Properties("Data").Value
WhileNot IsNothing(chunk)
writer.Write(chunk, 0, chunk.Length)
writer.Flush()
chunk = Nothing
Sequence = Sequence + 1
Data = PopulateERData(BinaryID, Sequence)
RetEntityData = entityClient.Retrieve(Data)
chunk = RetEntityData.Properties("Data").Value
EndWhile
Catch ex AsException
Finally
writer.Close()
fs.Close()
MessageBox.Show("Download")
EndTry
EndSub
''' <summary>
''' Helper function to assign binary details to Binary EntityData
''' </summary>
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
''' <summary>
''' Helper function to assign text fields value to Document EntityData
''' </summary>
PrivateFunction GetFormData() As Exact.Services.Client.Data.EntityData
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})
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})
Data.Properties.Add(New Exact.Services.Client.Data.PropertyDataWith {.Name = "IsBinaryServiceEnabled", .Value = True})
Return Data
EndFunction
''' <summary>
''' Helper function to assign EntityData to Text fields
''' </summary>
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
EndSub
''' <summary>
''' To capture the error which return by entity services
''' </summary>
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
Next
EndIf
MessageBox.Show(sb.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
EndSub
PrivateSub Connect()
entityClient = New Exact.Services.Client.Entity.EntityClientEG(TextBox10.Text, TextBox1.Text, TextBox2.Text)
EndSub
''' <summary>
''' Helper function to trigger the chunking function
''' </summary>
PrivateSub ChunkService()
Dim Data AsNew Exact.Services.Client.Data.EntityData
Dim FilePathCollector AsNewCollection
Data.EntityName = BINARYENTITY
If TextBox4.Text <> ""Then
FilePathCollector.Add(TextBox4.Text, "Body")
ChunkImage(Data, FilePathCollector)
FilePathCollector.Clear()
EndIf
If TextBox5.Text <> ""Then
FilePathCollector.Add(TextBox5.Text, "Document")
ChunkImage(Data, FilePathCollector)
FilePathCollector.Clear()
EndIf
EndSub
''' <summary>
''' 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.
''' </summary>
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
Try
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
EndIf
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
Else
fileLength = iStream.Read(completePacketData, 0, chunkSize)
chunkPacketToWrite = completePacketData
EndIf
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
Else
'Count total packet
countPacket -= 1
EndIf
Application.DoEvents()
EndWhile
iStream.Close()
EndUsing
If FilePath.Contains("Body") Then BodyID = MsgID
If FilePath.Contains("Document") Then AttachmentID = MsgID
Application.DoEvents()
Next
If FilePath.Contains("Body") ThenFile.Delete(sTempFileName)
Catch ex AsException
MessageBox.Show(ex.Message)
Finally
Cursor = Cursors.Default
EndTry
Cursor = Cursors.Default
ReturnTrue
Else
ReturnFalse
EndIf
EndFunction
EndClass |