Update a K2 ClientEvent URL using code

In our current project there are 18 processes with each at least 4 client events. There are even processes with 8 or 12 client events. We also have 1 webpart that handles all the client events. In the beginning we decide on the URL passing a parameter to allow the webpart to render correctly. The basis of that decision has (of course) changed and the querystring isn’t used anymore.

This also means, that querystring only contains the SerialNumber. The URL itself is based on a field from the Environment library. As you noticed, we’ve got at least 72 client events to update, this means a lot of manual work, luckily there is the K2 SourceCode.Workflow.Authoring API. If you have a big-ish project like we do, you’re going to use this API more and more….

Show me the code!

The following code allows us to update the Client Event URL:

DirectoryInfo di = new DirectoryInfo(@"C:\LocationOfK2Solution\");
FileInfo[] fileInfo = di.GetFiles("*.kprx");

foreach (FileInfo processFile in fileInfo)
    Process proc = Process.Load(processFile.FullName);
    Console.WriteLine("Process: {0}", proc.Name);
    foreach (Activity act in proc.Activities)
        Console.WriteLine("\tActivity: {0}", act.Name);
        foreach (Event evnt in act.Events)
            Console.WriteLine("\t\tEvent name: {0}", evnt.Name);
            Console.WriteLine("\t\tEvent type: {0}", evnt.Type);
            if (evnt.Type == EventTypes.Client)
                ClientEventItem clEvent = (ClientEventItem)evnt.EventItem;

                if (clEvent.InternetUrl == null || clEvent.InternetUrl.Parts == null)
                    throw new Exception("client event InternetURl is empty.");

                K2FieldPartCollection fieldPartCollection = clEvent.InternetUrl.Parts;

                // The first fieldpart should be the envField(from the artifact library)
                K2FieldPart envField = fieldPartCollection[0];
                if (envField.GetType() != typeof(ArtifactLibraryFieldPart))
                    throw new Exception("K2FieldPartCollection's 1st element is not an ArtifactLibraryFieldPart (is not the expected environment setting)");

                // Remove everything and build it up again.

                // Add the original first element

                // Add the SerialNumberField.
                SerialNoFieldPart serialField = new SerialNoFieldPart();

                // Save it back to the clientEvent.
                clEvent.InternetUrl.Parts = fieldPartCollection;

                Console.WriteLine("\t\tClient event URL updated, is now {0}", clEvent.InternetUrl.DesignTimeValue);
        } // foreach act.Events
    } // Foreacht process.activities

    Console.WriteLine("Saving process");
} //foreach file

Code explained

The code isn’t very hard to understand. We first get all the kprx files (i know, you can load the solution and get the files from there). We load the process using Process.Load(). Loop trough the activities and then loop trough al the events. We simply get all the clientevents by looking at the event type.

This is where it gets interesting. You can cast an event to a ClientEventItem. This allows you to get the InternetUrl as a property. That InternetURL is actually a K2FieldPartCollection. A k2FieldPart can be a lot of things, in this case we check if the first one is an ArtifactLibraryFieldPart which is a value from the ArtifactLibrary (or the Environment Library as most people know it). This check was simply there to check if we are doing the correct thing.

After that we clear the K2FieldPartCollection and add the ArtifactLibrary field we just saved in another variable, then just add the SerialFieldPart which represents the SerialNumber.
You can then simply print out the DesignTimeValue as shown. After that, we save the process and we’re done.

As you can see, the SourceCode.Workflow.Authoring API is very easy to use. We use it a lot to update and do stuff to our processes and the K2 Documentation also provide some examples on how to build processes using code!