Keeping track of Emails with EWS and K2

I haven’t posted anything in a while as I have been working on another project, which I am hoping to unveil sometime very soon. In the meantime though  I wanted to talk about K2 and Exchange. Now we all know that K2 can talk to exchange and send emails and receive replies back in the form of SmartActions out of the box.

But what if we wanted to keep track of the emails sent from a K2 app then this gets a bit tricky. We could save the message in a database using  a SmartObject Event and then use the email Event to send the email. Which is an ok approach, but I think something could be done better, where we don’t need to have this two step/event approach.

So lets have a think about about what i want the assembly to do?

  1. Send an email
  2. View the mailbox
  3. View an email

We could modify the existing email event to do what I am suggesting below, but that would be a pain as we would need to do it every time we use the email event and would also require the person building the workflow to be able to write code.  With the approach  I am going to go through, it  will allow anyone to be able to build a workflow where it would track what emails are being sent without having to write code and more importantly every app will be able to see it’s own emails it has sent out.

We are going to create a Email Endpoint Assembly that will allow a workflow to send an email and reference a primary key , SN, Process Instance Id or  application type (see framework) and view it’s mailbox by same type of information.

Getting Started

We will need the following

  1. Visual Studio 2015+
  2. Microsoft exchange web service (EWS URL)
  3. Exchange version
  4. UserAccount specifically setup just to be used for K2 mailbox (I normally create a service account, that just has a mailbox)
  5. User Account Email Address
  6. Microsoft.Exchange.Webservices.dll

To do this i need use the assembly Microsoft.Exchange.Webservices.dll which you can get from here .

Once we have the above we can start building the new email endpoint assembly.

EWS Code

To setup the connection to exchange server,  it is important to identify which version of exchange we are talking too.

ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);

When we have created an instance of the exchange service, we then give the instance the exchange web service url.

service.Url = new Uri(“Web service”);

ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
service.Credentials = new WebCredentials("Username", "Password");

service.Url = new Uri("Web service");
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "Email Address");

We have now got a connection to exchange server via it’s web service and we can do a number of different things such as

  1. Send Email
  2. View mailbox contents , such as the inbox or sent items
  3. View an email
  4. We can also do things such as create meeting requests

We will look at the basic code for sending an email

Sending an Email

To send an email we need to create an instance of the EmailMessage object and pass in the Exchange Service Object.

EmailMessage email = new EmailMessage(service);

Once we have done that we can access the properties and methods of EmailMessage object.

So we can give are email a subject email.Subject = “Subject”;

We can also give the email body and decide whether we want to send a plain text or a HTML message.

email.Body = new MessageBody(BodyType.HTML, Body);

EmailMessage email = new EmailMessage(service);
email.Subject = "Subject";
email.Body = new MessageBody(BodyType.HTML, Body);

To add recipients (To, Cc, Bcc) we just need to add the following code

  • email.ToRecipients.Add(“address”);
  • email.CcRecipients.Add(“address”);
  • email.BccRecipients.Add(“address”);

If you have more than one email address for ‘To’ or ‘Cc’ or the ‘Bcc’ then we can simply loop through the correct address method parameter. Like in the example below.

 if (To.Contains(";"))
 {
 String[] to = To.Split(';');
 foreach (var address in to)
 {
 email.ToRecipients.Add(address);
 }
 }
 else
 {
 email.ToRecipients.Add(To);
 }

To send the email we simply use .Send(); method

 email.SendAndSaveCopy();

Now we can send a basic email. So let us have a look how we can now extend this email so it can contain some additional properties that relate to the workflow it is being sent from.

The EmailMessage object allows us to add properties called extend properties and they are really simple to create. The only thing you need to remember is that the GUID used to identify the property must be the same every time we an email is sent and needs to be the same for when when we retrieve the mailbox.

So in this example i am going to bind the process instance id to the email message. We will then be able to search the sent items mailbox and retrieve all the messages that relates to that process instance id.

Creating extend properties.

This is the most important part , extend properties is what allows the ability to be able to group emails by the process Instance I’d, business key etc.. 

Create a Guid called ‘ProcessInstanceId’ and assign it a GUID.

Guid ProcessInstanceId_PropertySetId = Guid.Parse("fc0a27be-f463-472e-bea8-648e62d1d7dc")

We then have to define the extend property by giving the property a name in this case the property is called ‘ProcessInstanceId’ and we define the data type of the property as a ‘String’.

 ExtendedPropertyDefinition ProcessInstanceId_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(ProcessInstanceId_PropertySetId, "ProcessInstanceId", MapiPropertyType.String);

 

Now that we have defined the property , we can now populate the email with the process instance id. In code example below I am checking to see if the ‘ProcessInstanceId’ is greater than 0 or is not null and if true it will assign the property the value of the ‘ProcessInstanceId’ and if it is false it will assign the property a 0.

email.SetExtendedProperty(ProcessInstanceId_ExtendedPropertyDefinition, (ProcessInstanceId > 0 | ProcessInstanceId != null ? ProcessInstanceId : 0));

 

Now every time we send an email, it will now contain the process instance id.  In the complete code example of the ‘Send Emall’ method below I have also added some additional properties to contain the following

  1. Primary Key of the main business data
  2. ProcessTypeId (framework see here)
  3. Foilo of the process instance
  4. MessageId, so we can identify each email
public static string SendEmail(string Subject,string Body, string To, string Cc,string Bcc,int importance, string sn,string Folio, int? ProcessInstanceId, string ProcessTypeId, string BusinessKey)
 {
 string result = string.Empty;
 ExchangeService service = ConnectToExchange();
 try
 {
 if (To != null || To.Length != 0)
 {
 EmailMessage email = new EmailMessage(service);
 email.Subject = Subject;
 email.Body = new MessageBody(BodyType.HTML, Body);

Guid SN_PropertySetId = Guid.Parse("fc0a27be-f463-472e-bea8-648e62d1d7dc");
 ExtendedPropertyDefinition SN_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(SN_PropertySetId, "SN", MapiPropertyType.String);
 email.SetExtendedProperty(SN_ExtendedPropertyDefinition, (!String.IsNullOrEmpty(sn) ? sn : "0_0"));

Guid Folio_PropertySetId = Guid.Parse("fc0a27be-f463-472e-bea8-648e62d1d7dc");
ExtendedPropertyDefinition Folio_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(Folio_PropertySetId, "Folio", MapiPropertyType.String);
 email.SetExtendedProperty(Folio_ExtendedPropertyDefinition, (!String.IsNullOrEmpty(Folio) ? Folio : "Email Message"));

Guid ProcessInstanceId_PropertySetId = Guid.Parse("fc0a27be-f463-472e-bea8-648e62d1d7dc");
 ExtendedPropertyDefinition ProcessInstanceId_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(ProcessInstanceId_PropertySetId, "ProcessInstanceId", MapiPropertyType.String);
 email.SetExtendedProperty(ProcessInstanceId_ExtendedPropertyDefinition, (ProcessInstanceId > 0 | ProcessInstanceId != null ? ProcessInstanceId : 0));

Guid BusinessKey_PropertySetId = Guid.Parse("fc0a27be-f463-472e-bea8-648e62d1d7dc");
 ExtendedPropertyDefinition BusinessKey_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(BusinessKey_PropertySetId, "BusinessKey", MapiPropertyType.String);
 email.SetExtendedProperty(BusinessKey_ExtendedPropertyDefinition, (!String.IsNullOrEmpty(BusinessKey) ? BusinessKey : "0"));

Guid ProcessTypeId_PropertySetId = Guid.Parse("d6520129-3c59-4191-b9d7-4f5160329e4f");ExtendedPropertyDefinition ProcessTypeId_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(ProcessTypeId_PropertySetId, "ProcessTypeId", MapiPropertyType.String);
 email.SetExtendedProperty(ProcessTypeId_ExtendedPropertyDefinition, (!String.IsNullOrEmpty(ProcessTypeId) ? ProcessTypeId : "00000000-0000-0000-0000-000000000000"));

Guid MessageId_PropertySetId = Guid.Parse("6e997d14-d9b3-4516-8d14-0a10b0aa74aa");
 string MessageId = Guid.NewGuid().ToString();
 ExtendedPropertyDefinition MessageId_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(MessageId_PropertySetId, "ProcessTypeId", MapiPropertyType.String);
 email.SetExtendedProperty(MessageId_ExtendedPropertyDefinition, MessageId);



if (To.Contains(";"))
 {
 String[] to = To.Split(';');
 foreach (var address in to)
 {
 email.ToRecipients.Add(address);
 }
 }
 else
 {
 email.ToRecipients.Add(To);
 }



if (!string.IsNullOrEmpty(Cc))
 {
 if (Cc.Contains(";"))
 {
 String[] to = Cc.Split(';');
 foreach( var address in to)
 {
 email.CcRecipients.Add(address);
 }
 }
 else
 {
 email.CcRecipients.Add(Cc);

}
 }

if (!string.IsNullOrEmpty(Bcc))
 {
 if (Bcc.Contains(";"))
 {
 String[] to = Bcc.Split(';');
 foreach (var address in to)
 {
 email.BccRecipients.Add(address);
 }
 }
 else
 {
 email.BccRecipients.Add(Cc);

}
 }

if (importance > 0)
 {
 email.Importance = (importance == 1 ? Microsoft.Exchange.WebServices.Data.Importance.Normal : Importance.High);
 }

email.SendAndSaveCopy();

result = email.Id.ToString();
 }
 }
 catch(Exception ex)
 {
 result = "Error: " + ex.Message.ToString(); 
 }
 finally
 {

}
 return result;
 }

Retrieving an Exchange Mailbox

Now that we can send emails with K2 related data we now need to be able to retrieve those emails. So we can then view them in a SmartForm.

The first thing we need

public static List<EmailBox> GetMailBox(string MailBoxType,int PageSize)
 {
 ItemView view = new ItemView(PageSize);
 List<EmailBox> list = new List<EmailBox>();

Guid SN_PropertySetId = Guid.Parse("fc0a27be-f463-472e-bea8-648e62d1d7dc");
 ExtendedPropertyDefinition SN_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(SN_PropertySetId, "SN", MapiPropertyType.String);

Guid Folio_PropertySetId = Guid.Parse("fc0a27be-f463-472e-bea8-648e62d1d7dc");
 ExtendedPropertyDefinition Folio_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(Folio_PropertySetId, "Folio", MapiPropertyType.String);

Guid ProcessInstanceId_PropertySetId = Guid.Parse("fc0a27be-f463-472e-bea8-648e62d1d7dc");
 ExtendedPropertyDefinition ProcessInstanceId_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(ProcessInstanceId_PropertySetId, "ProcessInstanceId", MapiPropertyType.String);

Guid BusinessKey_PropertySetId = Guid.Parse("fc0a27be-f463-472e-bea8-648e62d1d7dc");
 ExtendedPropertyDefinition BusinessKey_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(BusinessKey_PropertySetId, "BusinessKey", MapiPropertyType.String);

Guid ProcessTypeId_PropertySetId = Guid.Parse("d6520129-3c59-4191-b9d7-4f5160329e4f");
 ExtendedPropertyDefinition ProcessTypeId_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(ProcessTypeId_PropertySetId, "ProcessTypeId", MapiPropertyType.String);

Guid MessageId_PropertySetId = Guid.Parse("6e997d14-d9b3-4516-8d14-0a10b0aa74aa");
 ExtendedPropertyDefinition MessageId_ExtendedPropertyDefinition = new ExtendedPropertyDefinition(MessageId_PropertySetId, "ProcessTypeId", MapiPropertyType.String);

ExchangeService service = ConnectToExchange();
 view.PropertySet = new PropertySet(BasePropertySet.IdOnly, ItemSchema.Subject, SN_ExtendedPropertyDefinition, Folio_ExtendedPropertyDefinition, ProcessInstanceId_ExtendedPropertyDefinition, BusinessKey_ExtendedPropertyDefinition, ProcessTypeId_ExtendedPropertyDefinition, MessageId_ExtendedPropertyDefinition);

FindItemsResults<Item> findResults = service.FindItems((MailBoxType == "Sent" ? WellKnownFolderName.SentItems : WellKnownFolderName.Inbox), view);
 foreach(Item email in findResults.Items)
 {
 Item mail = Item.Bind(service, email.Id);
 list.Add(new EmailBox
 {
 MailBoxType = MailBoxType,
 Subject = mail.Subject,
 Body = mail.Body,
 Importance = mail.Importance.ToString(),
 Id = mail.Id.ToString(),
 Categories = mail.Categories.ToString(),
 DateTimeCreated = mail.DateTimeCreated,
 DateTimeReceived = mail.DateTimeReceived,
 DateTimeSent = mail.DateTimeSent,
 Cc = mail.DisplayCc,
 To = mail.DisplayTo,
 SN = (email.ExtendedProperties.Count > 0 ? email.ExtendedProperties[0].Value.ToString():string.Empty),
 Folio = (email.ExtendedProperties.Count > 0 ? email.ExtendedProperties[1].Value.ToString(): string.Empty),
 ProcessInstanceId = (email.ExtendedProperties.Count > 0 ? email.ExtendedProperties[2].Value.ToString(): string.Empty),
 BusinessKey = (email.ExtendedProperties.Count > 0 ? email.ExtendedProperties[3].Value.ToString(): string.Empty),
 ProcessTypeId = (email.ExtendedProperties.Count > 0 ? email.ExtendedProperties[4].Value.ToString(): string.Empty),
 MessageId = (email.ExtendedProperties.Count > 0 ? email.ExtendedProperties[5].Value.ToString(): string.Empty)

});

}
 return list;

}

d

de

Retrieve an Email

Now that we can retrieve a list of emails from a mailbox we now need to be able to retrieve a single email.

We can do this.ww

public static EmailBox GetEmail(string Id)
 {
 EmailBox email = new EmailBox();
 ExchangeService service = ConnectToExchange();

try
 {
 Item mail = Item.Bind(service, (ItemId)Id);
 {
 email.Subject = mail.Subject;
 email.Body = mail.Body;
 email.Importance = mail.Importance.ToString();
 email.Id = mail.Id.ToString();
 email.Categories = mail.Categories.ToString() ;
 email.DateTimeCreated = mail.DateTimeCreated;
 email.DateTimeReceived = mail.DateTimeReceived;
 email.DateTimeSent = mail.DateTimeSent;
 email.Cc = mail.DisplayCc;
 email.To = mail.DisplayTo;
 email.SN = (mail.ExtendedProperties.Count > 0 ? mail.ExtendedProperties[0].Value.ToString(): string.Empty);
 email.Folio = (mail.ExtendedProperties.Count > 0 ? mail.ExtendedProperties[1].Value.ToString(): string.Empty);
 email.ProcessInstanceId = (mail.ExtendedProperties.Count > 0 ? mail.ExtendedProperties[2].Value.ToString(): string.Empty);
 email.BusinessKey = (mail.ExtendedProperties.Count > 0 ? mail.ExtendedProperties[3].Value.ToString(): string.Empty);
 email.ProcessTypeId = (mail.ExtendedProperties.Count > 0 ? mail.ExtendedProperties[4].Value.ToString(): string.Empty);
 email.MessageId = (mail.ExtendedProperties.Count > 0 ? mail.ExtendedProperties[5].Value.ToString(): string.Empty);
}
}
 catch(Exception ex)
 { }
 finally
 {

}
 return email;
 }

 

Now that we have these methods to send an email, retrieve a mailbox and to retrieve an email. We can now register the library as an endpoint assembly. 

We could extend this to be able to add attachments and we could also look at the calendar meeting requests and doing the same with those and extend their properties 

We can then build a SmartObject around it and then we can use it within are workflows and Smartforms. To make it even easier for people to use the new email SmartObject, we could wrap a SmartWizard around the methods.

The full solution can be downloaded from here 

 

Building a K2 Smartform spider part 6

So we have looked at the API and we have made the endpoint assembly and this into a couple of SmartObjects. Now that we have these  we can now  build some View and Smartforms to show the data on the Smartforms.

SmartObject ReCap

So we have two SmartObjects one for the Views and one for the Smartforms.

Spider.smo.Views

Looks at details of the view from it’s basic details to it’s rules

View.smo

Spider.smo.Smartform

Looks at details of the view from it’s basic details to it’s rules

form.smo

 

The views of FormSpider

VIEWSPIDER

Now we can build some views so we can interact with the SmartObjects. Majority of the views will be list views as the methods return back multiple rows of data. The only two that are not going to be list views will be the two forms that allow us to search for a specific Smartform or view.

 

Each of the items views contains the following fields

  1. Artifact name (picker control)
  2. Description (data label)
  3. Version (data label)

view

formheader

Each of the item views has the same rule, which is when the picker control is changed we then transfer the description, version etc.. from the selected row into the view data labels.

pickerchanged

List Views

Parameters

Each of the list views will have the parameter of ‘ViewName’ or ‘FormName’ depending on whether it’s a form view or view view. This allows us to pass in a form name or view name and then load up the parameters for that arifact.

parameters

Properties

We also have view to show all the properties of the artifact

properties

Views in a form and forms that have a certain view in

viewsinform

Controls

The control views shows all the controls on the artifact, whether they are hidden controls such table properties and user controls.

formcontrols

By clicking on a control in the list,  there will be a pop up that show’s all the properties of that control.

CONTROLPROP

Rules

There is also a view to show all the events on the artifact

rules

By clicking on an event,  we are then shown  all the conditions, actions for that event

viewrules

 

SmartObjects

Using the Form Spider assembly, we can also access the details of the SmartObjects, such as its properties, methods and the views the being used by that SmartObject.

SmartObjectsSpider

We could take this even further by getting the details of the service object, but for this version I have just kept it with the basic details

Workflow

Like with the SmartObjects we can also use Form spider to have a look at the workflows on the K2 server as well.

The current version will show the basic details about the workflow such as its description, number of versions etc..

It also shows the process data fields and XML data fields, the activities that make yo the workflow and also  what Smartforms and Views are linked to that particular workflow.

workflowspider

Also by clicking on activity we also get to see the events that make up that activity as well.

workflowevents

Below is a video that goes through the  a demo of Form Spider

Building a K2 Smartform spider part 5

In parts 1 to 4 we looked at some of the different classes and methods that are available in the Smartform API. In part 5 we will be taking these methods and building a complete assembly for us to use.

Smartform spider library

The Smartform spider library is what we will use to create an endpoint assembly so we can create SmartObjects from it and then eventually Smartforms.

Getting Started

1. Open up Visual studio and create a class library project

2.Add the following references to the library

using SourceCode.Forms.Management;
using SourceCode.Forms.Deployment;
using SourceCode.Forms;
using SourceCode.Forms.Authoring;

 

3.Create a class called ‘Common.cs’, this will contain all the common classes to hold the form and view data.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CloudFish.FormSpider
{
public class SmartFormViewSml
{
public string name
{
get;
set;
}
public string displayname
{
get;
set;
}

public string description
{
get;
set;
}

public Guid guid
{
get;
set;
}
public int version
{
get;
set;
}
}

public class SmartFormView
{
public string name
{
get;
set;
}
public string displayname
{
get;
set;
}

public string description
{
get;
set;
}

public Guid guid
{
get;
set;
}
public int version
{
get;
set;
}

public string theme
{
get;
set;
}

}

public class SmartFormViewProperties
{
public string name
{

get;
set;
}

public string value
{

get;
set;
}
}
public class SmartFormViewControls
{
public string name
{
get;
set;
}

public string type
{
get;
set;
}

public Guid guid
{
get;
set;
}

}

public class SmartFormViewParameters
{
public string name
{
get;
set;
}

public string type
{
get;
set;
}

public string defaultvalue
{
get;
set;
}
}

public class SmartFormViewEvents
{
public string name
{
get;
set;
}

public string type
{
get;
set;
}

public Guid GUID
{
get;
set;
}
}
public class SmartFromViewHandlers
{

public string Name
{

get;
set;
}

public Guid GUID
{

get;
set;
}

 

public Guid GUID
{

get;
set;
}

}

public class SmartFormViewActions
{
public Guid GUID
{

get;
set;
}

public Guid viewguid
{
get;
set;
}

public Guid formguid
{
get;
set;
}

public string method
{
get;
set;
}

public string executiontype
{
get;
set;
}

public Guid controlguid
{
get;
set;
}

public string actiontype
{
get;
set;
}
}
public class SmartFormViewActionParameters
{

 

public string targettype
{

get;
set;
}
public string targetpath
{

get;
set;
}
public string targetid
{

get;
set;
}

public string sourcevalue
{

get;
set;
}

public string sourcetype
{

get;
set;
}
public string sourcepath
{

get;
set;
}

public string sourceid
{

get;
set;
}
}
public class SmartFormViewActionValidation
{

public string status
{
get;
set;
}
}

public class SmartFormViewActionValidationMessage
{

public string message { get; set; }
}

}

 

4.Create another class called ‘properties.cs’, this will contain a generic method to get the properties of an item.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CloudFish.FormSpider
{
class Properties
{

public List<SmartFormViewProperties> ArtefactProperties(SourceCode.Forms.Authoring.PropertyCollection properties)
{
List<SmartFormViewProperties> list = new List<SmartFormViewProperties>();
foreach (SourceCode.Forms.Authoring.Property prop in properties)
{
list.Add(new SmartFormViewProperties
{
name = prop.Name,
value = prop.Value,

});

}
return list;
}
}
}

SmartObject Object

5.Now lets create a class called ‘Smartform.cs’ this class will contain all the public static methods for accessing key information from a Smartform and is the object that will be used as a Service Object by K2.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SourceCode.Forms.Management;
using SourceCode.Forms.Deployment;
using SourceCode.Forms;
using SourceCode.Forms.Authoring;

/// <summary>
/// Explores the content of the SmartForm
/// </summary>
namespace CloudFish.FormSpider
{
public class Smartform
{

/// <summary>
/// Gets the details of the form
/// </summary>
/// <param name=”FormName”></param>
public static SmartFormView LoadForm(string formname)
{

FormsManager frm = new FormsManager(“dlx”, 5555);
FormInfo forminfo = frm.GetForm(formname);
SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetViewDefinition(formname));

SmartFormView sf = new SmartFormView();
sf.guid = form.Guid;
sf.description = form.Description;

sf.displayname = form.DisplayName;
sf.name = form.Name;
sf.guid = form.Guid;
sf.theme = form.Theme;

return sf;
}
/// <summary>
/// Get a list of all the forms
/// </summary>
/// <returns></returns>
public static List<SmartFormView> GetAllForms()
{
List<SmartFormView> list = new List<SmartFormView>();
FormsManager frm = new FormsManager(“dlx”, 5555);
FormExplorer formexplorer = frm.GetForms();
foreach (SourceCode.Forms.Management.FormInfo forminfo in formexplorer.Forms)
{

SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(forminfo.Name));

list.Add(new SmartFormView
{
name = forminfo.Name,
displayname = forminfo.DisplayName,
description = forminfo.Description,
guid = forminfo.Guid,
version = forminfo.Version

});

}
return list;
}
/// <summary>
/// Get a list of all the forms that contain a certain view
/// </summary>
/// <param name=”ViewName”></param>
/// <returns></returns>
public static List<SmartFormView> GetAllFormsbyView(string ViewName)
{
List<SmartFormView> list = new List<SmartFormView>();
FormsManager frm = new FormsManager(“dlx”, 5555);
FormExplorer formexplorer = frm.GetFormsForView(ViewName);
foreach (SourceCode.Forms.Management.FormInfo forminfo in formexplorer.Forms)
{
SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetViewDefinition(forminfo.Name));

list.Add(new SmartFormView
{
name = forminfo.Name,
displayname = forminfo.DisplayName,
description = forminfo.Description,
guid = forminfo.Guid,
version = forminfo.Version

});

}
return list;
}
/// <summary>
/// List of form properties
/// </summary>
/// <param name=”FormName”></param>
/// <returns></returns>
public static List<SmartFormViewProperties> GetFormProperties(string FormName)
{
List<SmartFormView> list = new List<SmartFormView>();
FormsManager frm = new FormsManager(“dlx”, 5555);

SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(FormName));
Properties prop = new Properties();
return prop.ArtefactProperties( form.Properties);

}
/// <summary>
/// Gets a list of the form parameters
/// </summary>
/// <param name=”FormName”></param>
/// <returns></returns>
public static List<SmartFormViewParameters> FormParameters(string FormName)
{
List<SmartFormViewParameters> list = new List<SmartFormViewParameters>();
FormsManager frm = new FormsManager(“dlx”, 5555);
SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(FormName));

foreach (SourceCode.Forms.Authoring.FormParameter parameter in form.Parameters)
{
list.Add(new SmartFormViewParameters
{
name = parameter.Name,
type = parameter.DataType.ToString(),
defaultvalue = parameter.DefaultValue
});
}

return list;

}

/// <summary>
/// Form Controls
/// </summary>
/// <param name=”FormName”></param>
/// <returns></returns>
public static List<SmartFormViewControls> FormControls(string FormName)
{
List<SmartFormViewControls> list = new List<SmartFormViewControls>();
FormsManager frm = new FormsManager(“dlx”, 5555);
SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(FormName));

foreach (SourceCode.Forms.Authoring.Control control in form.Controls)
{
list.Add(new SmartFormViewControls
{
name = control.Name,
type = control.Type,
guid = control.Guid,

});

}
return list;
}
/// <summary>
/// Form Events
/// </summary>
/// <param name=”FormName”></param>
/// <returns></returns>
public static List<SmartFormViewEvents> FormEventsEvents(string FormName)
{
List<SmartFormViewEvents> list = new List<SmartFormViewEvents>();
FormsManager frm = new FormsManager(“dlx”, 5555);
SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(FormName));

foreach (SourceCode.Forms.Authoring.Eventing.Event ev in form.Events)
{

if (ev.SourceType == SourceCode.Forms.Authoring.Eventing.EventSourceType.Rule)
{
list.Add(new SmartFormViewEvents
{
name = ev.Name,
type = ev.EventType.ToString(),
GUID = ev.Guid

});

}
}

return list;
}

/// <summary>
/// Event Handlers
/// </summary>
/// <param name=”EventGUID”></param>
/// <returns></returns>
public static List<SmartFromViewHandlers> FormHandlers(String FormName,Guid EventGUID)
{
List<SmartFromViewHandlers> list = new List<SmartFromViewHandlers>();
FormsManager frm = new FormsManager(“dlx”, 5555);
SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(FormName));
var ev = form.Events[EventGUID];

SourceCode.Forms.Authoring.Eventing.Event e = form.Events[EventGUID];

foreach (SourceCode.Forms.Authoring.Eventing.Handler handle in e.Handlers)
{
list.Add(new SmartFromViewHandlers
{

Name = handle.HandlerType.ToString(),
GUID = handle.Guid
});

}
return list;

}

/// <summary>
/// Conditions
/// </summary>
/// <param name=”FormName”></param>
/// <param name=”EventGUID”></param>
/// <param name=”HandleGUID”></param>
/// <returns></returns>
public static List<SmartFormViewConditions> ArtefactConditions(String FormName,Guid EventGUID,Guid HandleGUID)
{
List<SmartFormViewConditions> list = new List<SmartFormViewConditions>();
FormsManager frm = new FormsManager(“dlx”, 5555);
SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(FormName));
var ev = form.Events[EventGUID].Handlers[HandleGUID];
SourceCode.Forms.Authoring.Eventing.Handler e = form.Events[EventGUID].Handlers[HandleGUID];

foreach (SourceCode.Forms.Authoring.Eventing.Condition condition in e.Conditions)
{

list.Add(new SmartFormViewConditions
{
GUID = condition.Guid,

});
}

return list;
}
/// <summary>
/// Actions
/// </summary>
/// <param name=”HandleGUID”></param>
/// <returns></returns>
public static List<SmartFormViewActions> ArtefactActionss(String FormName, Guid EventGUID, Guid HandleGUID)
{
List<SmartFormViewActions> list = new List<SmartFormViewActions>();
FormsManager frm = new FormsManager(“dlx”, 5555);

SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(FormName));
var ev = form.Events[EventGUID].Handlers[HandleGUID];
SourceCode.Forms.Authoring.Eventing.Handler e = form.Events[EventGUID].Handlers[HandleGUID];

foreach (SourceCode.Forms.Authoring.Eventing.Action action in e.Actions)
{
list.Add(new SmartFormViewActions
{
GUID = action.Guid,

viewguid = action.ViewGuid,
method = action.Method,
formguid = action.FormGuid,
executiontype = action.ExecutionType.ToString(),
controlguid = action.ControlGuid,
actiontype = action.ActionType.ToString()
});
}
return list;
}
/// <summary>
/// Actions Parameters
/// </summary>
/// <param name=”FormName”></param>
/// <param name=”EventGUID”></param>
/// <param name=”HandleGUID”></param>
/// <param name=”ActionGUID”></param>
/// <returns></returns>
public static List<SmartFormViewActionParameters> SmartFormViewActionParameters(String FormName, Guid EventGUID, Guid HandleGUID,Guid ActionGUID)
{
List<SmartFormViewActionParameters> list = new List<SmartFormViewActionParameters>();
FormsManager frm = new FormsManager(“dlx”, 5555);

SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(FormName));
SourceCode.Forms.Authoring.Eventing.Action e = form.Events[EventGUID].Handlers[HandleGUID].Actions[ActionGUID];

foreach (SourceCode.Forms.Authoring.Eventing.Mapping map in e.Parameters)
{

list.Add(new SmartFormViewActionParameters
{
targettype = map.TargetType.ToString(),
targetpath = map.TargetPath,
targetid = map.TargetID,
sourcevalue = map.SourceValue,
sourcetype = map.SourceType.ToString(),
sourcepath = map.SourcePath,
sourceid = map.SourceID

});
}

return list;
}
/// <summary>
/// Actions Results
/// </summary>
/// <param name=”FormName”></param>
/// <param name=”EventGUID”></param>
/// <param name=”HandleGUID”></param>
/// <param name=”ActionGUID”></param>
/// <returns></returns>
public static List<SmartFormViewActionParameters> SmartFormViewActionResults(String FormName, Guid EventGUID, Guid HandleGUID, Guid ActionGUID)
{
List<SmartFormViewActionParameters> list = new List<SmartFormViewActionParameters>();
FormsManager frm = new FormsManager(“dlx”, 5555);

SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(FormName));
SourceCode.Forms.Authoring.Eventing.Action e = form.Events[EventGUID].Handlers[HandleGUID].Actions[ActionGUID];

foreach (SourceCode.Forms.Authoring.Eventing.Mapping map in e.Results)
{

list.Add(new SmartFormViewActionParameters
{
targettype = map.TargetType.ToString(),
targetpath = map.TargetPath,
targetid = map.TargetID,
sourcevalue = map.SourceValue,
sourcetype = map.SourceType.ToString(),
sourcepath = map.SourcePath,
sourceid = map.SourceID

});
}

return list;
}
/// <summary>
/// Validation Messages
/// </summary>
/// <param name=”FormName”></param>
/// <param name=”EventGUID”></param>
/// <param name=”HandleGUID”></param>
/// <param name=”ActionGUID”></param>
/// <returns></returns>
public static List<SmartFormViewActionValidationMessage> SmartFormViewActionValidation(String FormName, Guid EventGUID, Guid HandleGUID, Guid ActionGUID)
{
List<SmartFormViewActionValidationMessage> list = new List<SmartFormViewActionValidationMessage>();
FormsManager frm = new FormsManager(“dlx”, 5555);

SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(FormName));
SourceCode.Forms.Authoring.Eventing.Action e = form.Events[EventGUID].Handlers[HandleGUID].Actions[ActionGUID];

foreach (SourceCode.Forms.Authoring.ValidationMessage val in e.Validation.Messages)
{

list.Add(new SmartFormViewActionValidationMessage
{
message = val.Message
});
}

return list;
}

}
}

View Object

6.Create a class called ‘View.cs’, like ‘Smartform.cs’ this class will contain all the methods for accessing information about views  on the K2 environment

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SourceCode.Forms.Management;
using SourceCode.Forms.Deployment;
using SourceCode.Forms;
using SourceCode.Forms.Authoring;

namespace CloudFish.FormSpider
{
public class Views
{

/// <summary>
/// Gets all the views on the environment
/// </summary>
/// <returns></returns>
public static List<SmartFormView> GetAllViews()
{
List<SmartFormView> list = new List<SmartFormView>();
FormsManager frm = new FormsManager(“dlx”, 5555);
ViewExplorer formexplorer = frm.GetViews();
foreach (SourceCode.Forms.Management.ViewInfo viewinfo in formexplorer.Views)
{

SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(viewinfo.Name));

list.Add(new SmartFormView
{
name = viewinfo.Name,
displayname = viewinfo.DisplayName,
description = viewinfo.Description,
guid = viewinfo.Guid,
version = viewinfo.Version,
});

}
return list;
}

/// <summary>
/// Gets all the views that are attached to a form
/// </summary>
/// <param name=”formname”></param>
/// <returns></returns>
public static List<SmartFormView> GetAllViews(string formname)
{
List<SmartFormView> list = new List<SmartFormView>();
FormsManager frm = new FormsManager(“dlx”, 5555);
ViewExplorer formexplorer = frm.GetViewsForForm(formname);
foreach (SourceCode.Forms.Management.ViewInfo viewinfo in formexplorer.Views)
{

SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(viewinfo.Name));

list.Add(new SmartFormView
{
name = viewinfo.Name,
displayname = viewinfo.DisplayName,
description = viewinfo.Description,
guid = viewinfo.Guid,
version = viewinfo.Version,

});

}
return list;
}
/// <summary>
/// List of view properties
/// </summary>
/// <param name=”ViewName”></param>
/// <returns></returns>
public static List<SmartFormViewProperties> GetViewProperties(string ViewName)
{
List<SmartFormView> list = new List<SmartFormView>();
FormsManager frm = new FormsManager(“dlx”, 5555);
SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(ViewName));
Properties prop = new Properties();
return prop.ArtefactProperties(view.Properties);

}
/// <summary>
/// Gets a list of the view parameters
/// </summary>
/// <param name=”ViewName”></param>
/// <returns></returns>
public static List<SmartFormViewParameters> ViewParameters(string ViewName)
{
List<SmartFormViewParameters> list = new List<SmartFormViewParameters>();
FormsManager frm = new FormsManager(“dlx”, 5555);
SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(ViewName));

foreach (SourceCode.Forms.Authoring.ViewParameter parameter in view.Parameters)
{
list.Add(new SmartFormViewParameters
{
name = parameter.Name,
type = parameter.DataType.ToString(),
defaultvalue = parameter.DefaultValue
});
}

return list;

}

/// <summary>
/// View Controls
/// </summary>
/// <param name=”ViewName”></param>
/// <returns></returns>
public static List<SmartFormViewControls> ViewControls(string ViewName)
{
List<SmartFormViewControls> list = new List<SmartFormViewControls>();
FormsManager frm = new FormsManager(“dlx”, 5555);
SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(ViewName));

foreach (SourceCode.Forms.Authoring.Control control in view.Controls)
{
list.Add(new SmartFormViewControls
{
name = control.Name,
type = control.Type,
guid = control.Guid,

});

}
return list;
}
/// <summary>
/// View Events
/// </summary>
/// <param name=”ViewName”></param>
/// <returns></returns>
public static List<SmartFormViewEvents> ViewEventsEvents(string ViewName)
{
List<SmartFormViewEvents> list = new List<SmartFormViewEvents>();
FormsManager frm = new FormsManager(“dlx”, 5555);
SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(ViewName));

foreach (SourceCode.Forms.Authoring.Eventing.Event ev in view.Events)
{
if (ev.SourceType == SourceCode.Forms.Authoring.Eventing.EventSourceType.Rule)
{
list.Add(new SmartFormViewEvents
{
name = ev.Name,
type = ev.EventType.ToString(),
GUID = ev.Guid

});

}
}

return list;
}

/// <summary>
/// Event Handlers
/// </summary>

/// <param name=”ViewName”></param>
/// <param name=”EventGUID”></param>
/// <returns></returns>
public static List<SmartFromViewHandlers> ViewHandlers(String ViewName, Guid EventGUID)
{
List<SmartFromViewHandlers> list = new List<SmartFromViewHandlers>();
FormsManager frm = new FormsManager(“dlx”, 5555);
SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(ViewName));
var ev = view.Events[EventGUID];

SourceCode.Forms.Authoring.Eventing.Event e = view.Events[EventGUID];

foreach (SourceCode.Forms.Authoring.Eventing.Handler handle in e.Handlers)
{
list.Add(new SmartFromViewHandlers
{

Name = handle.HandlerType.ToString(),
GUID = handle.Guid
});

}
return list;

}

/// <summary>
/// Conditions
/// </summary>
/// <param name=”ViewName”></param>
/// <param name=”EventGUID”></param>
/// <param name=”HandleGUID”></param>
/// <returns></returns>
public static List<SmartFormViewConditions> ArtefactConditions(String ViewName, Guid EventGUID, Guid HandleGUID)
{
List<SmartFormViewConditions> list = new List<SmartFormViewConditions>();
FormsManager frm = new FormsManager(“dlx”, 5555);
SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(ViewName));
var ev = view.Events[EventGUID].Handlers[HandleGUID];
SourceCode.Forms.Authoring.Eventing.Handler e = view.Events[EventGUID].Handlers[HandleGUID];

foreach (SourceCode.Forms.Authoring.Eventing.Condition condition in e.Conditions)
{

list.Add(new SmartFormViewConditions
{
GUID = condition.Guid

});
}

return list;
}
/// <summary>
/// Actions
/// </summary>
/// <param name=”HandleGUID”></param>
/// <returns></returns>
public static List<SmartFormViewActions> ArtefactActionss(String ViewName, Guid EventGUID, Guid HandleGUID)
{
List<SmartFormViewActions> list = new List<SmartFormViewActions>();
FormsManager frm = new FormsManager(“dlx”, 5555);

SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(ViewName));
var ev = view.Events[EventGUID].Handlers[HandleGUID];
SourceCode.Forms.Authoring.Eventing.Handler e = view.Events[EventGUID].Handlers[HandleGUID];

foreach (SourceCode.Forms.Authoring.Eventing.Action action in e.Actions)
{
list.Add(new SmartFormViewActions
{
GUID = action.Guid,

viewguid = action.ViewGuid,
method = action.Method,
formguid = action.FormGuid,
executiontype = action.ExecutionType.ToString(),
controlguid = action.ControlGuid,
actiontype = action.ActionType.ToString()
});
}
return list;
}
/// <summary>
/// Actions Parameters
/// </summary>
/// <param name=”ViewName”></param>
/// <param name=”EventGUID”></param>
/// <param name=”HandleGUID”></param>
/// <param name=”ActionGUID”></param>
/// <returns></returns>
public static List<SmartFormViewActionParameters> ViewActionParameters(String ViewName, Guid EventGUID, Guid HandleGUID, Guid ActionGUID)
{
List<SmartFormViewActionParameters> list = new List<SmartFormViewActionParameters>();
FormsManager frm = new FormsManager(“dlx”, 5555);

SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(ViewName));
SourceCode.Forms.Authoring.Eventing.Action e = view.Events[EventGUID].Handlers[HandleGUID].Actions[ActionGUID];

foreach (SourceCode.Forms.Authoring.Eventing.Mapping map in e.Parameters)
{

list.Add(new SmartFormViewActionParameters
{
targettype = map.TargetType.ToString(),
targetpath = map.TargetPath,
targetid = map.TargetID,
sourcevalue = map.SourceValue,
sourcetype = map.SourceType.ToString(),
sourcepath = map.SourcePath,
sourceid = map.SourceID

});
}

return list;
}
/// <summary>
/// Actions Results
/// </summary>
/// <param name=”ViewName”></param>
/// <param name=”EventGUID”></param>
/// <param name=”HandleGUID”></param>
/// <param name=”ActionGUID”></param>
/// <returns></returns>
public static List<SmartFormViewActionParameters> ViewActionResults(String ViewName, Guid EventGUID, Guid HandleGUID, Guid ActionGUID)
{
List<SmartFormViewActionParameters> list = new List<SmartFormViewActionParameters>();
FormsManager frm = new FormsManager(“dlx”, 5555);

SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(ViewName));
SourceCode.Forms.Authoring.Eventing.Action e = view.Events[EventGUID].Handlers[HandleGUID].Actions[ActionGUID];

foreach (SourceCode.Forms.Authoring.Eventing.Mapping map in e.Results)
{

list.Add(new SmartFormViewActionParameters
{
targettype = map.TargetType.ToString(),
targetpath = map.TargetPath,
targetid = map.TargetID,
sourcevalue = map.SourceValue,
sourcetype = map.SourceType.ToString(),
sourcepath = map.SourcePath,
sourceid = map.SourceID

});
}

return list;
}
/// <summary>
/// Validation Messages
/// </summary>
/// <param name=”ViewName”></param>
/// <param name=”EventGUID”></param>
/// <param name=”HandleGUID”></param>
/// <param name=”ActionGUID”></param>
/// <returns></returns>
public static List<SmartFormViewActionValidationMessage> ViewActionValidation(String ViewName, Guid EventGUID, Guid HandleGUID, Guid ActionGUID)
{
List<SmartFormViewActionValidationMessage> list = new List<SmartFormViewActionValidationMessage>();
FormsManager frm = new FormsManager(“dlx”, 5555);

SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(ViewName));
SourceCode.Forms.Authoring.Eventing.Action e = view.Events[EventGUID].Handlers[HandleGUID].Actions[ActionGUID];

foreach (SourceCode.Forms.Authoring.ValidationMessage val in e.Validation.Messages)
{

list.Add(new SmartFormViewActionValidationMessage
{
message = val.Message

});
}

return list;
}

}
}

7.Now we can build the solution and we are ready to tell K2 about it and make it a service object and then a SmartObject.

You can download the code from this location

 

Creating the Service Object

Creating the service object is really easy, open up the ‘SmartObject Service Tester’

ServiceObjectTester

1.Right Click on the ‘Endpoints Assembly’ and click on ‘Register Service Instance’

AddServiceInstance

2.In the ‘Assembly Full Path’ enter in the full address of where the dll of the assembly is kept.

3.Click on ‘Next’ and enter in ‘Form Spider’ in the ‘Display Name’ and ‘System Name’

4.Click ‘Finish’

K2 will then integrate the Dll and map out all the public static methods.

ServiceObjectTester

Now that we have the service objects we can now create the SmartObjects. For this project i have just created two SmartObjects one for Smartforms and for the Views. Each of these objects will contain all the public static methods we created in the class library earlier.

Below is an example of one

ServiceObjectTester

 

 

 

More information on Endpoint Assemblies can be found here 

 

In the final part of this series we will take the SmartObjects and build the  Smartforms and Views.

 

 

 

 

Building a K2 Smartform spider part 4

Rules

In part 3, we looked at how to get additional information from Smartform such as parameters and controls. In part 4 we will now look at how to be able to get the rules from the forms and views.

This is probably most complex part of the API as it involves a number of different methods to get the  necessary information.

To access the rules  of the artifact we need to use the following code as we did in part 3 this will give us access to the Events object.

Code for a Smartform

SourceCode.Forms.Authoring.Form form = new SourceCode.Forms.Authoring.Form(frm.GetFormDefinition(‘form name’));

Code for a view

SourceCode.Forms.Authoring.View view = new SourceCode.Forms.Authoring.View(frm.GetViewDefinition(‘View Name’));

So lets take a look and see what we can from the events object

Events

Majority of rules in Smartforms and views start with an event.  An event is when something happens such as a ‘click of a button’.

public List<SmartFormViewEvents> ArtefactEvents(SourceCode.Forms.Authoring.Eventing.EventCollection events)
{
List<SmartFormViewEvents> list = new List<SmartFormViewEvents>();
foreach (SourceCode.Forms.Authoring.Eventing.Event ev in events)
{

if (ev.SourceType == SourceCode.Forms.Authoring.Eventing.EventSourceType.Rule)
{
list.Add(new SmartFormViewEvents
{
name = ev.Name,
type = ev.EventType.ToString(),
handlers = ev.Handlers,
properties = ev.Properties

});

}
}

return list;
}

The above method gives a list of all the events on the artifact and access to more additional objects

First thing we do is we loop through the event collection and we check to see if the event type is the ‘Rule’ type.

if (ev.SourceType == SourceCode.Forms.Authoring.Eventing.EventSourceType.Rule)

The objects we want to have access to are the following

  1. Name
  2. Type
  3. Handlers
  4. Properties

The important object from this is the Handlers, as this will give us access to the Conditions and Actions of the rule.

Handlers

The handler object is where we can drill down into the rule and access the conditions of the rule and also the actions of the rule.

public List<SmartFromViewHandlers> ArtefactHandlers(SourceCode.Forms.Authoring.Eventing.HandlerCollection handlers)
{
List<SmartFromViewHandlers> list = new List<SmartFromViewHandlers>();
foreach (SourceCode.Forms.Authoring.Eventing.Handler handle in handlers)
{
list.Add(new SmartFromViewHandlers
{
Actions = handle.Actions,
Conditions = handle.Conditions,
Name = handle.HandlerType.ToString()
});

}

return list;

}

The methods starts by passing in the handler object from the previous method, now the method can loop through the all the handlers for that particular event

foreach (SourceCode.Forms.Authoring.Eventing.Handler handle in handlers)

On each loop, we can then access the following objects

  1. Name
  2. Conditions
  3. Actions

Conditions

Conditions check to see if something is equal to true, for example ‘all the required fields are entered’.

public List<SmartFormViewConditions> ArtefactConditions(SourceCode.Forms.Authoring.Eventing.ConditionCollection conditions)
{
List<SmartFormViewConditions> list = new List<SmartFormViewConditions>();
foreach (SourceCode.Forms.Authoring.Eventing.Condition condition in conditions)
{

list.Add(new SmartFormViewConditions
{
Property = condition.Properties
});
}

return list;
}

 

Actions

So we can access the event, the conditions and now lets look how we can access the actions of a rule.

public List<SmartFormViewActions> ArtefactActionss(SourceCode.Forms.Authoring.Eventing.ActionCollection actions)
{
List<SmartFormViewActions> list = new List<SmartFormViewActions>();

foreach (SourceCode.Forms.Authoring.Eventing.Action action in actions)
{
list.Add(new SmartFormViewActions
{
properties = action.Properties,
parameters = action.Parameters,
results = action.Results,
validation = action.Validation,
viewguid = action.ViewGuid,
method = action.Method,
formguid = action.FormGuid,
executiontype = action.ExecutionType.ToString(),
controlguid = action.ControlGuid,
actiontype = action.ActionType.ToString()
});
}
return list;
}

Using the above method, we can get the complete information of the action.  The action opens up some additional objects that we can explore to get more detailed information about the action.

Below are some examples of the more useful ones

Action Parameters

public List<SmartFormViewActionParameters> SmartFormViewActionParameters(SourceCode.Forms.Authoring.Eventing.MappingCollection parameters)
{
List<SmartFormViewActionParameters> list = new List<SmartFormViewActionParameters>();
foreach (SourceCode.Forms.Authoring.Eventing.Mapping map in parameters)
{

list.Add(new SmartFormViewActionParameters
{

validation = map.Validation,
targettype = map.TargetType.ToString(),
targetpath = map.TargetPath,
targetid = map.TargetID,
sourcevalue = map.SourceValue,
sourcetype = map.SourceType.ToString(),
sourcepath = map.SourcePath,
sourceid = map.SourceID

});
}

return list;
}

Action Results

public List<SmartFormViewActionParameters> SmartFormViewActionResults(SourceCode.Forms.Authoring.Eventing.MappingCollection Results)
{
List<SmartFormViewActionParameters> list = new List<SmartFormViewActionParameters>();
foreach (SourceCode.Forms.Authoring.Eventing.Mapping result in Results)
{

list.Add(new SmartFormViewActionParameters
{

validation = result.Validation,
targettype = result.TargetType.ToString(),
targetpath = result.TargetPath,
targetid = result.TargetID,
sourcevalue = result.SourceValue,
sourcetype = result.SourceType.ToString(),
sourcepath = result.SourcePath,
sourceid = result.SourceID

});
}
return list;
}

Action Validation

public List<SmartFormViewActionValidation> SmartFormViewActionValidations(SourceCode.Forms.Authoring.ValidationResult validations)
{

List<SmartFormViewActionValidation> list = new List<SmartFormViewActionValidation>();

SourceCode.Forms.Authoring.ValidationResult validation = validations;

list.Add(new SmartFormViewActionValidation
{
messages = validation.Messages,
status = validation.Status.ToString()
});
return list;
}

Action Messages

public List<SmartFormViewActionValidationMessage> SmartFormViewActionValidationMessages(ValidationMessageCollection messages)
{
List<SmartFormViewActionValidationMessage> list = new List<SmartFormViewActionValidationMessage>();
foreach (ValidationMessage message in messages)
{
list.Add(new SmartFormViewActionValidationMessage
{
message = message.Message
});
}
return list;
}

 

In the next part, we will take the methods we have explored in parts 1 to 4 and put it altogether to build the form spider.

I will make the source code available at the end of this series.

 

Building a K2 Smartform spider part 2

Taking part 1 further

So in part 1 we looked at a couple of basic methods for getting a list of  Smartforms and Views that are currently on the K2 Server. Which can be really handy if you wanted to build a library of all your forms and views.

But can take this further? We can already from the K2 designer expand the form and see what views make up that form, but we can’t though click on a view and see what forms it is being used in.

Finding all forms for a selected view

So in this section I am going to go through how we can retrieve a list of all the forms that a view has been used in. It pretty much uses the same code as the previous examples except this time we will be using  some additional methods that come with the API.

public List<SmartFormView> GetAllFormsForView(string viewName)
{
var list = new List<SmartFormView>();
var frm = new FormsManager(servername, port);
FormExplorer formexplorer = frm.GetFormsForView(viewName);
foreach (SourceCode.Forms.Management.FormInfo forminfo in formexplorer.Forms)
{

list.Add(new SmartFormView
{
name = forminfo.Name,
displayname = forminfo.DisplayName,
description = forminfo.Description,
guid = forminfo.Guid,
version = forminfo.Version,
CheckedOutBy = forminfo.CheckedOutBy,
theme = forminfo.Theme.ToString()
});

}
return list;
}

 

So you can see from the code above , its practically the same as just looping through all the forms. The only difference is this method call

frm.GetFormsForView(viewName)

All we do is call the above method and pass in the name of the view and we can then loop through all the forms  where that view is being used.

Finding all views for a selected form

So as we have done this for the view, it would only be fair if we did this for the form and like the example above it is very similar to the examples in part 1.

public List<SmartFormView> GetAllViews(string formname)
{
List<SmartFormView> list = new List<SmartFormView>();
FormsManager frm = new FormsManager(servername, port);
ViewExplorer formexplorer = frm.GetViewsForForm(formname);
foreach (SourceCode.Forms.Management.ViewInfo viewinfo in formexplorer.Views)
{

list.Add(new SmartFormView
{
name = viewinfo.Name,
displayname = viewinfo.DisplayName,
description = viewinfo.Description,
guid = viewinfo.Guid,
version = viewinfo.Version,

});

}
return list;

}

If we look at the code above the only difference is the method that is being called

frm.GetViewsForForm(formname)

We call this method and pass in the name of the form, or even the GUID and it then returns a list of all the views that are in the form.

Other methods

We can take this even further  and we can get a list of views that is being used by  a SmartObject and even a  list of views/forms that is calling a specific workflow

GetViewsForObject(Smartobject GUID)

GetViewsForProcess(Process Name)

GetFormsForProcess(Process Name)

 

In part 3 we will take these a bit further and drill down into the views and forms to see what makes up those artifacts.

I will make the source code available at the end of this series.

Building a endpoint assembly for K2 Blackpearl

As I mentioned in my last post, K2 can talk to dll assemblies. Which is brilliant as it opens up a whole lot of different API’s to the K2 environment. So for example it could open up old Com assemblies to K2 with a some wrap arounds the code. It could allow for REST services to be linked into K2. More importantly it allows you to bring code directly into your smartforms and workflow.

So how do we create an assembly that can be consumed by K2?

Well it’s really easy, we start off a with c# class library.

start

Now we have a project with  a empty class called ‘class1.cs’. Rename the class to ‘HelloWorld’ and now your solution should look like the below image

emptyclass

Before we get started there is one simple rule, that the methods must be public and static.

Now we can start having some fun. So in true tutorial style lets build a ‘Hello World’ method.

public static string HelloWorldMethod()
 {
   return Hello World;
 }

So when we register this class with K2 it will interrogate the assembly and extract all the methods. Each method in the class will be treated as a service object. In the same way a table in sql is treated as a service object in K2.    The example above is really simple one, so lets take this a step further and lets add a parameter to a method.

public static string WhatIsYourName(string name)
{
  return Hello World  + name;
}

As you can see it’s still very simple, nothing special needs to be added. No additional libraries need to be referenced.

So the above is ok for returning a single value like a primary key, but what if we want to return more than a single value and more importantly what if we want to bring back more than one row of data?

Well it involves Lists. So the first thing i am going to do is  create a simple class to hold my data

public class MyDetails
    {
        public int Id
        {
            get;
            set;

        }

        public string Firstname
        {
            get;
            set;
        }

        public string Lastname
        {
            get;
            set;
        }

        public string EmailAddress
        {
            get;
            set;
        }

}

So as you can see i have simple class that has public properties.Now we can build the method that will return the rows of data

We start off with  a public static method that returns a list of type MyDetails

public static List<MyDetails> GetUserDetails()

We can then create an instance of that list

List<MyDetails> result = new List<MyDetails>();

Now that we have done this we can loop through the data source. In this example we are going to loop through a object that contains user details and for each row i am going to add it to my list.

foreach(User.detail item in UserDetails.GetDetails())
            {
                result.Add(new MyDetails
                    {
                        Id = item.UserId
                        // Direction = item..ToString(),
                        Firstname = item.forename,
                        lastname  = item.Surname,
                        EmailAddress = item.email
                        
                    });
  }

If we put this together it will look something like this

public static List<MyDetails> GetUserDetails()

{

     List<MyDetails> result = new List<MyDetails>();

foreach(User.detail item in UserDetails.GetDetails())
            {
                result.Add(new MyDetails
                    {
                        Id = item.UserId
                        // Direction = item..ToString(),
                        Firstname = item.forename,
                        lastname  = item.Surname,
                        EmailAddress = item.email
                        
                    });
  }

return result;

}

The solution is now complete, build the solution and make a note of the the location of the dll that has been created.

Telling K2 about the assembly

Now that we have the assembly we can now nook it into K2.  To do this we can use the service object tester. Which if you don’t know where that is you can find it here C:\Program Files (x86)\K2 blackpearl\Bin

Expand the ‘ServiceObject Explorer’ and right click on ‘Endpoints Assembly’ and select ‘Register ServiceInstance’

ServiceObjectTester

Under service keys  – Assembly Full path, enter in the complete file location of your dll and click ‘Next’ and ‘Finish’

AddServiceInstance

K2 will now go and map out all the public static methods it can find in the assembly and you can build a SmartObject from these.

We are given a couple of options to do this, we can get K2 to auto generate a Smartobject for each of the methods it finds in the assembly or we can use one of the tools like K2 Studio or K2 Designer to create a custom Smartobject where we can create Smartobject methods for each of the methods K2 finds in the assembly.

Auto Generate the smartobjects from the tester

CreateSmartobjects

  1. Right click on your newly created service objects and select ‘Create Smartobjects’
  2. Uncheck ‘System types’ folder
  3. Click ‘OK’

Your Smartobjects are now created and can be used by K2.

You can download the example code from here