Getting something back from the EnumerateResourcesActivity

I have just spent a very frustrating day trying to figure out how to get access to the resource found by the EnumerateResourcesActivity, not helped even slightly by the usual machine-generated “documentation“. I’m still not very happy with it, and can’t for the life of me understand why it can’t give me a straight object collection as output, but at least I’ve got the data I need from it now.

The EnumerateResourcesActivity is the recommended way to search for objects using an XPath filter. But, quite bizarrely, the only readily accessible data you get back from it is how many objects it found – not the actual objects! This is despite the fact that one of the input parameters is a list of attributes you want back. I feel cheated!!

The only time I’d used this activity before was for checking uniqueness, and all I needed then was an object count. But today I needed to write a custom Notification Activity and (as there’s no way I know of to add an Identity Picker to a custom workflow UI) I wanted to be able to specify the email template by it’s name.

Clearly this was going to involve an object lookup as I need to specify the template’s ResourceID going in to the EmailNotificationActivity. In this example the “searchEmailTemplate” activity is the EnumerateResourcesActivity, and I only expect it to return one object.

This is where all the pain started, and if it hadn’t been for the following blog posts I never would have worked this out:

http://c–shark.blogspot.com.au/2009/04/how-to-use-enumerateresourcesactivity.html#comment-form (including comments as it was Luka who had the crucial bit of advice that you need to set all the properties on the EnumerateResourcesActivity going in).
http://bennettadelson.wordpress.com/2012/02/20/fim-2010-user-rcdc-to-add-user-to-groups/
http://blog.clauskonrad.net/2011/11/fim-2010-how-to-use-std.html
http://www.fimspecialist.com/fim-portal/custom-workflow-examples/custom-workflow-example-enumerate-resources-activity/

So thank you very much lovely bloggers for sharing your experiences on this!

The Code

The first totally weird thing you have to do is hack the Designer code for your custom workflow. I’m using VB.NET so mine is called <ActivityName>.Designer.vb. I found I had to click “Show All Files” to see it:

We have to completely ignore the message that says we shouldn’t edit this code and do the following:

  • Add a declaration for codeActivity1 at the end of the class, and
  • Add the lines as shown before “Me.CanModifyActivities = False” inside the InitializeComponent Sub.
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class AlternateEmailNotification

    'NOTE: The following procedure is required by the Workflow Designer
    'It can be modified using the Workflow Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerNonUserCode()> _
    <System.CodeDom.Compiler.GeneratedCode("", "")> _
    Private Sub InitializeComponent()
	   ... (pre-existing code) ...
        '
        ' Manually added code for the EnumerateResourcesActivity
        '
        Me.codeActivity1 = New System.Workflow.Activities.CodeActivity()
        Me.codeActivity1.Name = "codeActivity1"
        AddHandler Me.codeActivity1.ExecuteCode, AddressOf Me.GetEmailTemplate_ExecuteCode
        'Make the codeActivity the child of the EnumerateResourcesActivity 
        Me.searchEmailTemplate.Activities.Add(Me.codeActivity1)

        Me.CanModifyActivities = False
    End Sub

    ... (pre-existing declarations) ...

    'Manually added code activity that allows access to objects returned by EnumerateResourcesActivity
    Private codeActivity1 As CodeActivity
End Class

In the code for the activity itself (AlternateEmailNotification.vb in the picture above) I add the following code which is being called by that handler we added above. This does actually manage to get you the first object returned by the enumeration. (I still don’t know how to get at all the objects found but don’t need to for this activity – leaving that for another day.)

    Private Sub GetEmailTemplate_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim currentItem As ResourceType = TryCast(EnumerateResourcesActivity.GetCurrentIterationItem(DirectCast(sender, CodeActivity)), ResourceType)
        If currentItem Is Nothing Then
            Throw New WorkflowTerminatedException("Unable to find email template " & Me.Template)
        End If
        'TemplateID is a System.Guid declared globally
        TemplateID = currentItem.ObjectID.GetGuid
    End Sub

Now back on more familiar ground, here’s the code activity that runs just before the EnumerateResourcesActivity to set the scene. Remember as I’ve mentioned you have to set all the properties. If you don’t you wind up with “Nothing” instead of a resource.

    Private Sub initSearch_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs)
        searchEmailTemplate_ActorId1 = New Guid(FIMADMIN_GUID)
        Dim filter As String = "/EmailTemplate[DisplayName ='" & Me.Template & "']"
        searchEmailTemplate_XPathFilter1 = filter
        searchEmailTemplate_Selection1 = New String() {"DisplayName"}
        searchEmailTemplate_PageSize1 = 100
        searchEmailTemplate_SortingAttributes1 = Nothing
        searchEmailTemplate_TotalResultsCount1 = 0
    End Sub

Finally now I set up my EmailNotificationActivity, which was at least as simple as advertised.

    Private Sub initNotification_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs)
        emailNotificationActivity_To1 = EmailOther
        emailNotificationActivity_EmailTemplate1 = TemplateID
    End Sub

2 Replies to “Getting something back from the EnumerateResourcesActivity”

  1. Hi Carol – thank you for the awesomely clear write-up for this issue. It’s been sending me nuts for days, and your explanation and solution got me working. Much appreciated.

Leave a Reply

Your email address will not be published. Required fields are marked *


*