Introduction

In some instances, it may be necessary to use and persist a strongly typed object within a K2.net 2003 Process. This is easily achieved by creating a Data Field of type Binary and then serializing the object to a byte array using a binary formatter. The serialization can then be reversed to recreate the object from the byte array when the object is required.

Important: It is strongly reccomended that only persons familiar with the following products, concepts and / or skills utilize the contents of this Knowledge Base article in their processes. The reader is assumed to be familiar with:
  • K2.net 2003 Server
  • K2.net 2003 Studio
  • Fundamentals of how to create, export and manage a K2.net 2003 Process
  • K2.net 2003 Server Events and writing custom code within a K2.net 2003 Default Server Event
  • K2ROM

Overview

Depending on where the object needs to be stored and accessed, create an Activity or Process level Data Field and set its data type to Binary. Ensure to clear the check box for "Keep Audit Trail" unless you need to keep track of changes made to the object. Disabling the option will preevent large objects from utilising excessive amounts of storage space resources in the K2 databases. Once the Data Field is created, it may be accessed via the K2ROM.

A Data Fields' data is stored in the K2 Log database in an ntext column which allows ample space for storing objects. As a performance consideration, try to keep the objects to be stored in the Process small since storing, retrieving, serializing and de-serializing the object will have an impact on the Process' performance.

The next step is to import the required namespaces. Go to the Project properties and add imports for the following namespaces:

  • System.IO
  • System.Runtime.Serialization.Formatters.Binary

At each Event where the object needs to be read, add the following method to convert the byte array back into an object:

VB.NET

Public Function ByteArrayToObject(ByVal buffer() As Byte) As Object

Dim formatter As BinaryFormatter = New BinaryFormatter()
Dim ms As MemoryStream = New MemoryStream(buffer)

Try
  Return formatter.Deserialize(ms)
Catch ex As Exception
 Throw ex
Finally
 ms.Close()
End Try

End Function

C#

public object ByteArrayToObject(byte[] buffer)
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream ms = new MemoryStream(buffer);
try
 {
 return formatter.Deserialize(ms);
 }
catch (Exception ex)
 {
 throw ex;
 }
finally
 {
 ms.Close();
 }
}

If the code is going to be used in a number of events, it is more efficient to create a separate helper class and reference the helper class at project level. Below is an example which uses one Default Server Event to write a named value collection to a Binary Data Field called "Test" and then retrieves it in a separate Default Server Event.

VB.NET

'Write NVC to Data Field.
Public Sub Main(ByVal K2 As ServerEventContext)
K2.Synchronous = True
Dim df As DataField = K2.ProcessInstance.DataFields("Test")
Dim nvc As NameValueCollection = New NameValueCollection()

nvc.Add("1", "x")
nvc.Add("2", "y")
nvc.Add("3", "z")

df.Value = ObjectToByteArray(nvc)
End Sub

Function ObjectToByteArray(ByVal obj As Object) As Byte()

Dim ms As MemoryStream = New MemoryStream()
Dim formatter As BinaryFormatter = New BinaryFormatter()

Try
  formatter.Serialize(ms, obj)
  Return ms.ToArray()
Catch ex As Exception
  Throw ex
Finally
  ms.Close()
End Try

End Function

'Get NVC from Data Field.

Public Sub Main(ByVal K2 As ServerEventContext)
K2.Synchronous = True

Dim df As DataField = K2.ProcessInstance.DataFields("Test")
Dim nvc As NameValueCollection = CType(ByteArrayToObject(CType(df.Value, Byte())), NameValueCollection)
End Sub

Public Function ByteArrayToObject(ByVal buffer() As Byte) As Object
Dim formatter As BinaryFormatter = New BinaryFormatter()
Dim ms As MemoryStream = New MemoryStream(buffer)

Try
  Return formatter.Deserialize(ms)
Catch ex As Exception
  Throw ex
Finally
  ms.Close()
End Try

End Function

C#

// Write NVC to Data Field.
public void Main(ServerEventContext K2)
{
 K2.Synchronous = true;

DataField df = K2.ProcessInstance.DataFields["Test"];
NameValueCollection nvc = new NameValueCollection();
 nvc.Add("1", "x");
 nvc.Add("2", "y");
 nvc.Add("3", "z");

 df.Value = ObjectToByteArray(nvc);
}

public byte[] ObjectToByteArray(object obj)
{
 MemoryStream ms = new MemoryStream();
 BinaryFormatter formatter = new BinaryFormatter();
 try
  {
  formatter.Serialize(ms, obj);
  return ms.ToArray();
 }
catch (Exception ex)
 {
  throw ex;
 }
finally
 {
  ms.Close();
 }
}

// Get NVC from Data Field.

public void Main(ServerEventContext K2)
{
 K2.Synchronous = true;

 DataField df = K2.ProcessInstance.DataFields["Test"];
 NameValueCollection nvc = (NameValueCollection) ByteArrayToObject((byte[])  df.Value);
}

public object ByteArrayToObject(byte[] buffer)
{
 BinaryFormatter formatter = new BinaryFormatter();
 MemoryStream ms = new MemoryStream(buffer);
 try
 {
  return formatter.Deserialize(ms);
 }
 catch (Exception ex)
  {
  throw ex;
  }
 finally
  {
  ms.Close();
  }
}