SP2010 SPF Workflow Part 5: List ID Lookups The Proper MS Way

23 June 2011

Finally after a couple of days of pain, I've got the end to end workflow which can be modified in SPD, and can be deployed to any site regardless of List/ListID...and here's the two biggest gotchas I encountered.

  1. Make sure you are developing your workflows on the same version of SP as the target environment – SPD is smart/crazy enough to generate .xsn task forms if you are connected to a SP2010 box, but use regular .aspx forms if you are connected to a SPF box.
  2. If you have any lookups to lists, you will have to open the generated workflow .xoml files and remove the hardcoded references to listids.

If you'll recall from previous posts, for point #2, I had created a crazy feature receiver that dynamically strips out the list ids and replaces them with the correct list ids. But it turns out that there's actually a much easier way, hidden in the SharePoint dlls. Taking a quick look in reflector....

// Microsoft.SharePoint.WorkflowActions.FindValueActivity
protected override ActivityExecutionStatus Execute(ActivityExecutionContext context)
{
    int returnValue = Helper.FindValue(this.__Context, this.ExternalListId, this.ExternalFieldName, this.FindValue);                                        //Note the external list id property…
    this.ReturnValue = returnValue;
    return ActivityExecutionStatus.Closed;
}

// Microsoft.SharePoint.WorkflowActions.Helper
public static int FindValue(WorkflowContext context, string externalListId, string fieldNameInExternal, object value)
{
    return Helper.FindValueWithKey(context, Helper.GetListGuid(context, externalListId), fieldNameInExternal, value).Id;                                //goes into this Helper method…
}

// Microsoft.SharePoint.WorkflowActions.Helper
public static Guid GetListGuid(WorkflowContext context, string listNameOrId)
{
    Guid result;
    try
    {
        if (null == context)
        {
            result = new Guid(listNameOrId);
        }
        else
        {
            SPWeb web = context.Web;
            if (null == web)
            {
                result = new Guid(listNameOrId);
            }
            else
            {
                SPList sPList = null;
                try
                {
                    Guid uniqueID = new Guid(listNameOrId);
                    sPList = web.Lists[uniqueID];
                }
                catch (FormatException)
                {
                    sPList = web.Lists[listNameOrId];                                                                                        //which supports setting listid by name!!
                }
                result = sPList.ID;
            }
        }
    }
    catch (Exception)
    {
        result = default(Guid);
    }
    return result;
}

If that didn't make any sense to you, it just means that you can use List Names in place of the ListId and ExternalListId properties within your .xoml files.

For example:

<ns1:FindValueActivity x:Name="ID55" __Context="{ActivityBind ROOT,Path=__context}" ExternalFieldName="User_x0020_Account" ReturnValue="{x:Null}" ExternalListId="<strong>My List Name</strong>" ValueType="System.String">

This isn't very well documented (on MSDN, for example, it just says Identifier which kind of implies GUIDS only).

Now, we just need SharePoint designer to at least have the option to generate .xoml files in a site-collection agnostic way, and then none of this would be necessary!

Tags: list id, SharePoint 2010, SharePoint Designer, Workflow

Add a Comment

No Comments