Passing data from a custom Workflow via the Request object

I have been writing an activity that resets forgotten BPOS passwords (more on that later) and I wanted to include a Notification activity that would inform the user about the password reset request. To make the notification useful I want to include whether the reset succeeded, and if it failed, what the reason was. To do this I need to be able to pass information from the custom “Change BPOS Password” activity to the Notification activity.


What does the documentation say?

The first thing I did was consult the official document Developing Custom Activities and Workflows. The only thing I could find about passing data was this:

Passing Data between Workflow Phases

Some scenarios may require that an authorization workflow share some information with an action workflow that runs for the same request. (For more information, see Request Processing.) The recommended approach for accomplishing this scenario is as follows:

Passing Data from an Authorization Workflow Activity to an Action Workflow

  1. Create and bind one or more attributes to the Request resource type in the FIM schema that can store the information that you want to share between activities. You can do this through Web services or by using the FIM Portal.
  2. Grant permissions to the person or resource that will be assigned to the ActorID of the activity to read and modify the new attribute. Note that this step is not required if the ActorID is set to the FIM Service Account resource. For more information, see Microsoft.ResourceManagement.Workflow.Activities.
  3. In the authorization workflow activity, use the UpdateResourceActivity activity to set the desired value on the new attribute.
  4. In the action workflow activity, use the ReadResourceActivity to get the value of the new attribute.

However this didn’t seem to address my simpler situation. I’m not trying to pass a value between an AuthZ and an Action workflow – I just want to pass the data between two steps in the same Action workflow. Perhaps I can use a WorkflowData parameter?

But as I thought about it I decided that maybe the method mentioned in the documentation was the right way to go. Essentially I am updating the request object itself with the results of the activity, and this then forms a permanent record. To jump ahead in the story, here’s what a request object looks like after a failed password reset operation. I think that’s pretty useful!

Create the Attributes

So following step one from the documentation, I created the following attributes and bound them to the Request resource type:

  • “Activity Status” – indexed string. This will normally contain “Succeeded” or “Failed”.
  • “Activity Status Message” – unindexed string. Here I can put extra info about why an activity failed.

Grant permissions to the new attributes

I added the new attributes to both of the following MPRs:  Request management: Request creators can read their approval resources and Request management: Request participants can read their request resources.

I also updated Administration: Administrators can control requests because I’m using the FIM service account to make the changes to the request (note the documentation above says you don’t have to do that if using the service account . I think that may be a mistake as rights always have to be granted, and I certainly had to).

Code the custom workflow activity to update the Request

 

The custom workflow must include a CurrentRequestActivity to get the details of the current request – I think this is probably standard anyway.

Here I’m finishing up with two UpdateResourceActivities which update respectively the “Activity Status” and “Activity Status Message”.

And I also need a code activity somewhere to feed the values to the UpdateResourceActivities. I tack this at the end of the code activity where I’m running my password reset code, because that’s where I have easy access to the results of the reset attempt. This code that sets up the UpdateResourceActivities is below. Note I am using the Built-In Admin account to update the request object. The variable “failureMessage” was already set earlier in the code.

    Const FIMADMIN_GUID As String = "7fb2b853-24f0-4498-9534-4e10589723c4"

    '' Prepare variables for UpdateRequest activities which write the activity status back to the Request object.
    Me.updateRequest1_ActorId1 = New Guid(FIMADMIN_GUID)
    Me.updateRequest1_ResourceId1 = Me.currentRequestActivity1.CurrentRequest.ObjectID
    Dim updateInstruction1 As New UpdateRequestParameter
    updateInstruction1.PropertyName = "ActivityStatus"
    If success Then
        updateInstruction1.Mode = UpdateMode.Modify
        updateInstruction1.Value = "Succeeded"
    Else
        updateInstruction1.Mode = UpdateMode.Modify
        updateInstruction1.Value = "Failed"
    End If

    Me.updateRequest1_UpdateParameters1 = New UpdateRequestParameter() {updateInstruction1}
    Me.updateRequest2_ActorId1 = New Guid(FIMADMIN_GUID)
    Me.updateRequest2_ResourceId1 = Me.currentRequestActivity1.CurrentRequest.ObjectID
    Dim updateInstruction2 As New UpdateRequestParameter
    updateInstruction2.PropertyName = "ActivityStatusMessage"
    If success Then
        'No message
    Else
        updateInstruction2.Mode = UpdateMode.Modify
        updateInstruction2.Value = failureMessage
    End If
    Me.updateRequest2_UpdateParameters1 = New UpdateRequestParameter() {updateInstruction2}

Accessing the values from an Email Template

My final step is to create the Email Template that will be used by the Notification Activity.

For the Subject:

BPOS Password Reset [//Request/ActivityStatus]

And in the body I add the following:

<p class="MsoNormal"><b>Request Status:</b></p>
<p class="MsoNormal">[//Request/ActivityStatus]</p>
<p class="MsoNormal">[//Request/ActivityStatusMessage]</p>
<p class="MsoNormal"><o:p> </o:p></p>

The result is that the password reset operation runs and depending on the result of the attempt, the user gets one of these emails:

And I think that that’s pretty cool!

8 Replies to “Passing data from a custom Workflow via the Request object”

  1. Thanks for a great article Carol!
    If you don’t want to create new attributes on the Request Resource there’s a multi-valued RequestStatusDetail string attribute already that could be used for this. There is even a special Activity for manipulating this attribute OOB called UpdateRequestActivity but this Activity is likely to disappear in the future since documentation is gone so don’t use it.

    The Description on the attribute in FIM is:
    Additional request information generated during the processing of this request. This may contain information messages or details of errors.

    Another thing worth knowing is that unless you need to actually get more detailed information about the current Request you could get it’s ObjectID, target resource ObjectID and the current actors ObjectID directly from the workflow instance without adding a CurrentRequestActivity.

    //Henrik

  2. Hi Herik. I had a look at that multivalue attribute but wasn’t convinced I’d be able to get the data I wanted out of it in the Email Template – which was the main aim of the exercise.
    And you’re right about the CurrentRequestActivity – I think I’ve just been sticking it in there because all the examples I’ve seen do that, but in fact I’ve been using the containing Workflow method to get the IDs anyway. Thanks for clarifying that for me!

  3. Carol,

    I do use //WorkflowData to store activity execution results and later [//WorkflowData/] in my email templates.

    this requires no schema modification but also it doesn’t keep activity execution status in the request body for historical purposes – so there’s a choice 🙂

  4. Thanks Eugene, that’s good to know! So, like you say, it depends on whether you want to keep the data on record.

  5. Hi Carol, I love it, I’ll certainly find a need to bypass WorkflowData in the future and as you said, you get a nice record on the original request!

  6. Hi Carol,

    Did you ever run into a problem where the Request was not fully updated with the Status by the time the Action phase of the policy is triggered.

    I am running into a problem where I have a custom workflow updating the Request attribute with a certain value from the target object in an authorization phase. Then in the action workflow, I was simply looking to write up the Request attribute in a email notification. But for whatever reason, the Request value didn’t seem to have enough time to get updated by the time the email is sent. If I end up adding an email notification activity within the workflow hosting the Request update activity, that seems to allow the Request just enough time to update the Request attribute and pass the value out to the action workflow notification.

    Thanks.

  7. I haven’t had that particular experience. I’m guessing that as the Target AuthZ change has been completed it moves on to the Action phase – it is not actually looking at the state of any changes to the Request object. You’ve found a way round anyway, so thanks for commenting about that here.

Leave a Reply

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


*