Handling Request Parameters in your Workflow Activity code

I was reading Carol’s post on why there are reasons you’d want to perform actions in the Authorization (AuthZ) phase of the request processing pipeline and felt the need to respond to Carol’s statement on handling the request parameters in your custom Workflow (WF) activity library code.

My colleague (who was also my customer), who cannot be named (because he’s really, really shy), and I wrote a number of utility functions that complimented our overall Visual Studio solution that we held in a separate project under a separate namespace. One of our classes focussed specifically on simplifying accessing the deserialized request parameters object of the current request. I’ll therefore share the code here for other to utilise. Please feel free to comment on the code. Neither of us are real developers. J

RequestHandling.cs

using System;
using System.Collections.Generic;
using Microsoft.ResourceManagement.WebServices.WSResourceManagement;
using System.Xml.Serialization;

namespace msresource.net.Forefront.IdentityManager.Custom.Workflow.Activities.Utilities
{
    public class RequestHandling
    {
        /// <summary>
        /// Returns true plus value if single request parameter for specified attribute exists in request.
        /// </summary>
        /// <param name="currentRequest">A copy of the current instance of the (RequestType) current request activity output.</param>
        /// <param name="targetAttributeName">The name of the attribute to verify whether or not it's in the current request.</param>
        /// <param name="value">The value of the attribute, if found, is passed out via this attribute.</param>
        /// <returns></returns>
        public static Boolean tryFetchSingleRequestParameterValue(RequestType currentRequest, string targetAttributeName, out Object value)
        {
            Boolean attributeExists = false;
            Boolean singleAttributeExists = false;
            value = null;

            switch (currentRequest.Operation)
            {
                case OperationType.Create:
                    List<CreateRequestParameter> lCRP = new List<CreateRequestParameter>();
                    attributeExists = tryFetchCreateParametersByAttribute(currentRequest, targetAttributeName, out lCRP);
                    if (true == attributeExists)
                    {
                        if (lCRP.Count == 1)
                        {
                            value = lCRP[0].Value;
                            singleAttributeExists = true;
                        }
                    }
                    break;

                case OperationType.Put:
                    List<UpdateRequestParameter> lURP = new List<UpdateRequestParameter>();
                    attributeExists = tryFetchUpdateParametersByAttribute(currentRequest, targetAttributeName, out lURP);
                    if (true == attributeExists)
                    {
                        if (lURP.Count == 1)
                        {
                            value = lURP[0].Value;
                            singleAttributeExists = true;
                        }
                    }
                    break;

                default:
                    singleAttributeExists = false;
                    value = null;
                    break;
            }

            return singleAttributeExists;
        }

        /// <summary>
        /// Returns true plus a list of update parameters if any exist for the specified attribute.
        /// </summary>
        public static Boolean tryFetchUpdateParametersByAttribute(
            RequestType currentRequest,
            string targetAttributeName,
            out List<UpdateRequestParameter> requestParameters)
        {
            Boolean attributeExists = false;
            List<UpdateRequestParameter> lURP = new List<UpdateRequestParameter>();

            if (currentRequest.Operation == OperationType.Put)
            {
                foreach (UpdateRequestParameter updateRequestParameter in currentRequest.ParseParameters<UpdateRequestParameter>())
                {
                    if (targetAttributeName == updateRequestParameter.PropertyName)
                    {
                        attributeExists = true;
                        lURP.Add(updateRequestParameter);
                    }
                }
            }

            requestParameters = lURP;
            return attributeExists;
        }

        // override allows for an UpdateMode to be specified.
        // no simply way of implementing overload without code-duplication :(
        /// <summary>
        /// Returns true plus a list of update parameters if any exist for the specified attribute.
        /// </summary>
        /// <param name="currentRequest">A copy of the current instance of the (RequestType) current request activity output.</param>
        /// <param name="targetAttributeName">The name of the attribute to verify whether or not it's in the current request.</param>
        /// <param name="updateType">The type of operation (Add, Remove, Update)</param>
        /// <param name="requestParameters">The value of the attribute, if found, is passed out via this attribute.</param>
        /// <returns></returns>
        public static Boolean tryFetchUpdateParametersByAttribute(
            RequestType currentRequest,
            string targetAttributeName,
            UpdateMode updateType,
            out List<UpdateRequestParameter> requestParameters)
        {
            Boolean attributeExists = false;
            List<UpdateRequestParameter> lURP = new List<UpdateRequestParameter>();

            if (currentRequest.Operation == OperationType.Put)
            {
                foreach (UpdateRequestParameter updateRequestParameter in currentRequest.ParseParameters<UpdateRequestParameter>())
                {
                    if (targetAttributeName == updateRequestParameter.PropertyName
                        && updateRequestParameter.Mode == updateType)
                    {
                        attributeExists = true;
                        lURP.Add(updateRequestParameter);
                    }
                }
            }

            requestParameters = lURP;
            return attributeExists;
        }

        /// <summary>
        /// Returns true plus a list of create parameters if any exist for the specified attribute.
        /// </summary>
        /// <param name="currentRequest">A copy of the current instance of the (RequestType) current request activity output.</param>
        /// <param name="targetAttributeName">The name of the attribute to verify whether or not it's in the current request.</param>
        /// <param name="requestParameters">The value of the attribute, if found, is passed out via this attribute.</param>
        /// <returns></returns>
        public static Boolean tryFetchCreateParametersByAttribute(
            RequestType currentRequest,
            string targetAttributeName,
            out List<CreateRequestParameter> requestParameters)
        {
            Boolean attributeExists = false;
            List<CreateRequestParameter> lCRP = new List<CreateRequestParameter>();

            if (currentRequest.Operation == OperationType.Create)
            {
                foreach (CreateRequestParameter createRequestParameter in currentRequest.ParseParameters<CreateRequestParameter>())
                {
                    if (targetAttributeName == createRequestParameter.PropertyName)
                    {
                        attributeExists = true;
                        lCRP.Add(createRequestParameter);
                    }
                }
            }

            requestParameters = lCRP;
            return attributeExists;
        }

    }
}

In the above C-Sharp (C#) class there are four methods:

  • public static Boolean tryFetchSingleRequestParameterValue(RequestType currentRequest, String targetAttributeName, out Object value)
  • public static Boolean tryFetchUpdateParametersByAttribute(RequestType currentRequest, String targetAttributeName, out List requestParameters)
  • public static Boolean tryFetchUpdateParametersByAttribute(RequestType currentRequest, String targetAttributeName, UpdateMode updateType, out List requestParameters)
  • public static Boolean tryFetchCreateParametersByAttribute(RequestType currentRequest, String targetAttributeName, out List requestParameters)

I’ve actually commented this class, so you can see what they do, but the crux is this:

  • tryFetchSingleRequestParameterValue returns the value of the input request parameter (targetAttributeName) in the provided request object as an out variable if it exists. The method returns a true if it exists or a false otherwise. The value of targetAttributeName is case sensitive.
  • tryFetchUpdateParametersByAttribute works in the same way but returns a list of values as it’s quite possible the request contains more than once instance of the Update Request Parameter. tryFetchUpdateParametersByAttribute also has an override so that you can specify the operation or update mode, e.g. you can choose to only pull Add requests.
  • And lastly tryFetchCreateParametersByAttribute is the same as tryFetchUpdateParametersByAttribute but for Create Request Parameters instead. There’s currently no need for an override for this one.

If you want to get hold of a specific request parameter in an update operation you simply call tryFetchUpdateParametersByAttribute(…). You work out whether to call tryFetchUpdateParametersByAttribute or tryFetchCreateParametersByAttribute in an if else or switch statement, using something like this:

case OperationType.Put:
	List u;
	bool found;

	switch (updateMode.ToUpper())
        {
	        case "ADD":
			found = RequestHandling.tryFetchUpdateParametersByAttribute(currentRequest, targetAttributeName, UpdateMode.Insert, out u);
			break;

		case "REMOVE":
	                found = RequestHandling.tryFetchUpdateParametersByAttribute(currentRequest, targetAttributeName, UpdateMode.Remove, out u);
			break;

		case "BOTH":
		default:
			found = RequestHandling.tryFetchUpdateParametersByAttribute(currentRequest, targetAttributeName, out u);
			break;
	}

Hopefully this helps people! J

Advertisements

About Paul Williams

IT consultant working for Microsoft specialising in Identity Management and Directory Services.
This entry was posted in FIM, Programming and tagged , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s