Working with Comments and Attachments
The Comments and Attachments feature allow users to add Comments and Attachments to a Process Instance at runtime. These Comments and Attachments can be used later on in the Process Instances. Apart from standard K2 tools that allow you to work with Comments and Attachments, you can also work with comments and attachments through the Workflow Client API.
Comments and Attachments are implemented as SmartObjects in K2, which means you can also use the SmartObject Client API and Services, if you wish. The Workflow.Client namespace also exposes classes for working directly with these SmartObjects from within the context of a Process Instance Object.
Workflow Attachment and Workflow Comment SmartObjects, located in the System Category
Sample Project
This sample project demonstrates how to work with comments and attachments with code:
K2Documentation.Samples.WorkflowClient.CommentsAttachments.The sample project is provided for demonstration purposes only. It is not supported by K2 product support and is not intended to be used as-is in production environments.
Classes and Properties that expose the Comments and Attachments
| Classes |
Methods/Properties |
Purpose and Notes |
|
| SourceCode.Workflow.Client.Connection |
AddAttachment()
|
Adds an attachment. Must provide the process instance ID, provide the attachment as a System.IO.Stream |
|
|
AddComment()
|
Adds a comment. Must provide the Process Instance ID
|
|
| GetAttachment() |
Retrieves a single attachment |
|
| GetAttachments() |
Retrieves all attachments for a given Process Instance |
|
| GetComments() |
Retrieves all comments for a given Process Instance |
|
| SourceCode.Workflow.Client.ProcessInstance |
AddAttachment()
|
Adds an attachment. Provide the attachment as a System.IO.Stream |
|
|
AddComment()
|
Adds a comment.
|
|
| Attachments |
Collection of attachments for the process instance |
|
| Comments |
Collection of comments for the process instance |
|
| SourceCode.Workflow.Client.WorklistItem |
AddAttachment()
|
Adds an attachment. Provide the attachment as a System.IO.Stream |
|
|
AddComment()
|
Adds a comment.
|
|
| Attachments |
Collection of attachments for the current activity instance |
|
| Comments |
Collection of comments for the current activity instance |
|
| SourceCode.Workflow.Client.WorkflowAttachment |
GetFile() |
Retrieves the File associated with the attachment |
|
| ActInstDestId |
Activity Instance Destination ID that the attachment is associated with (optional) |
|
| CreatedBy |
Account that added the attachment |
|
| CreatedDate |
Date that the attachment was added |
|
| FileName |
File Name of attachment |
|
| FileSize |
File Size of attachment |
|
| FQN |
Fully-Qualified name of the Account that added the attachment |
|
| Id |
Unique ID of the Attachment record |
|
| ParentId |
The ‘ParentId’ property will be used for ‘Replies’
|
|
| ProcInstId |
ID of the Process Instance that the attachment is associated with |
|
| SourceCode.Workflow.Client.WorkflowComment |
ActInstDestId |
Activity Instance Destination ID that the comment is associated with (optional) |
|
| CreatedBy |
Account that added the comment |
|
| CreatedDate |
Date that the comment was added |
|
| FQN |
Fully-Qualified name of the Account that added the comment |
|
| Id |
Unique ID of the comment record |
|
| Message |
The comment text |
|
| ParentId |
The ‘ParentId’ property will be used for ‘Replies’
|
|
| ProcInstId |
ID of the Process Instance that the comment is associated with |
|
Code Samples
Adding a Comment
using (SourceCode.Workflow.Client.Connection K2Conn = new Connection()) {
K2Conn.Open("localhost");
WorklistItem _worklistItem = K2Conn.OpenWorklistItem("[SerialNumber]");
IWorkflowComment comment = K2Conn.AddComment(_worklistItem.ProcessInstance.ID, "Hello World");
IWorkflowComment comment2 = K2Conn.AddComment("[SerialNumber]", "Hello World");
IWorkflowComment comment3 = K2Conn.AddComment(_worklistItem.ProcessInstance.ID, _worklistItem.ActivityInstanceDestination.ID, "Hello World");
IWorkflowComment procInstComment = _worklistItem.ProcessInstance.AddComment("Hello World");
IWorkflowComment WLItemComment = _worklistItem.AddComment("Hello World");
}
Retrieving Comments
using (SourceCode.Workflow.Client.Connection K2Conn = new Connection()) {
K2Conn.Open("localhost");
WorklistItem _worklistItem = K2Conn.OpenWorklistItem("[SerialNumber]");
IEnumerable < IWorkflowComment > comments1 = K2Conn.GetComments(_worklistItem.ProcessInstance.ID);
IEnumerable < IWorkflowComment > comments2 = K2Conn.GetComments("[SerialNumber]");
IEnumerable < IWorkflowComment > comments3 = K2Conn.GetComments(_worklistItem.ProcessInstance.ID, _worklistItem.ActivityInstanceDestination.ID);
IEnumerable < IWorkflowComment > procInstComments = _worklistItem.ProcessInstance.Comments;
foreach(IWorkflowComment procInstComment in procInstComments) {
string comment = procInstComment.Message;
}
IEnumerable < IWorkflowComment > wlItemComments = _worklistItem.Comments;
foreach(IWorkflowComment wlItemComment in wlItemComments) {
string comment = wlItemComment.Message;
}
}
Adding Attachments
using (SourceCode.Workflow.Client.Connection K2Conn = new Connection()) {
K2Conn.Open("localhost");
System.IO.Stream _fileStream = null;
string _fileName = "[FileName.doc]";
string fullPath = string.Format(@ "C:\Temp\{0}", _fileName);
if (File.Exists(fullPath)) {
_fileStream = File.OpenRead(fullPath);
}
WorklistItem _worklistItem = K2Conn.OpenWorklistItem("[SerialNumber]");
IWorkflowAttachment attachment1 = K2Conn.AddAttachment(_worklistItem.ProcessInstance.ID, _fileName, _fileStream);
IWorkflowAttachment attachment2 = K2Conn.AddAttachment("[SerialNumber]", _fileName, _fileStream);
IWorkflowAttachment attachment3 = K2Conn.AddAttachment(_worklistItem.ProcessInstance.ID, _worklistItem.ActivityInstanceDestination.ID, _fileName, _fileStream);
IWorkflowAttachment ProcInstAttachment = _worklistItem.ProcessInstance.AddAttachment(_fileName, _fileStream);
IWorkflowAttachment WLItemAttachment = _worklistItem.AddAttachment(_fileName, _fileStream);
}
Adding Attachments (Async)
You may want to add attachment in an asynchronous fashion, in other words create the attachment object but do not upload the actual file content until you specifically want to do so. This code sample demonstrates this approach.
using (SourceCode.Workflow.Client.Connection K2Conn = new Connection()) {
K2Conn.Open("localhost");
System.IO.Stream _fileStream = null;
string _fileName = "[FileName.doc]";
string fullPath = string.Format(@ "C:\Temp\{0}", _fileName);
if (File.Exists(fullPath)) {
_fileStream = File.OpenRead(fullPath);
}
WorklistItem _worklistItem = K2Conn.OpenWorklistItem("[SerialNumber]");
IWorkflowAttachment attachmentWithoutContent = K2Conn.AddAttachment(_worklistItem.ProcessInstance.ID, _fileName, null);
IAttachment attachmentWithContent = K2Conn.UploadAttachmentContent(attachmentWithoutContent.Id, _fileStream);
}
Retrieving Attachments
using (SourceCode.Workflow.Client.Connection K2Conn = new Connection()) {
K2Conn.Open("localhost");
WorklistItem _worklistItem = K2Conn.OpenWorklistItem("[SerialNumber]");
IEnumerable < IWorkflowAttachment > attachments1 = K2Conn.GetAttachments(_worklistItem.ProcessInstance.ID);
IEnumerable < IWorkflowAttachment > attachments2 = K2Conn.GetAttachments("[SerialNumber]");
IEnumerable < IWorkflowAttachment > attachments3 = K2Conn.GetAttachments(_worklistItem.ProcessInstance.ID, _worklistItem.ActivityInstanceDestination.ID);
IEnumerable < IWorkflowAttachment > procInstAttachments = _worklistItem.ProcessInstance.Attachments;
_worklistItem = K2Conn.OpenWorklistItem("[SerialNumber]");
IEnumerable < IWorkflowAttachment > wlitemAttachments = _worklistItem.Attachments;
foreach(IWorkflowAttachment attachment in wlitemAttachments) {
string filename = attachment.FileName;
}
}
Retrieving Attachments – excluding the files
By default, the content of the file attachments will be returned unless you specifically state that you do not want the contents returned. For example, you may want to "get" the attachments for a process instance, but only list the file names. At a alter point, you will selectively download the actual content of the attachment file. This code sample demonstrates how to achieve this "async" on on-demand style of loading the attachment content.
using (SourceCode.Workflow.Client.Connection K2Conn = new Connection()) {
K2Conn.Open("localhost");
WorklistItem _worklistItem = K2Conn.OpenWorklistItem("[SerialNumber]");
IEnumerable < IWorkflowAttachment > attachments1 = K2Conn.GetAttachments(_worklistItem.ProcessInstance.ID, false);
IEnumerable < IWorkflowAttachment > attachments2 = K2Conn.GetAttachments("[SerialNumber]", false);
IEnumerable < IWorkflowAttachment > attachments3 = K2Conn.GetAttachments(_worklistItem.ProcessInstance.ID, _worklistItem.ActivityInstanceDestination.ID, false);
foreach(IWorkflowAttachment attachment in attachments3) {
string filename = attachment.FileName;
using(System.IO.Stream downloadStream = attachment.GetFile()) {
}
}
}
Retrieving Attachment
You can retrieve a specific attachment directly, if you know the attachment ID.
using (SourceCode.Workflow.Client.Connection K2Conn = new Connection()) {
K2Conn.Open("localhost");
int _attachmentID = 1;
IWorkflowAttachment attachment = K2Conn.GetAttachment(_attachmentID);
IWorkflowAttachment attachmentNoFile = K2Conn.GetAttachment(_attachmentID, false);
System.IO.Stream _fileStream = attachmentNoFile.GetFile();
}