Monthly Archives: July 2013

Provision SharePoint OOTB Approval Workflow programmatically in Visual Studio

In this article, I would like to show you on how to provision SharePoint out of the box Approval Workflow programmatically in Visual Studio.

In this scenario, I will provision the approval workflow when Feature Activated. So the feature receiver will look like:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
    SPWeb web = properties.Feature.Parent as SPWeb;
    SPList listTemplateManagement = web.Lists["Template Management"];

    // Create Approval Workflow and associate it with the library
    SPWorkflowTemplate baseTemplate = web.WorkflowTemplates.GetTemplateByName("Approval - SharePoint 2010", CultureInfo.CurrentCulture);
    SPWorkflowAssociation assoc = SPWorkflowAssociation.CreateListAssociation(baseTemplate, "Template Management Approval Workflow", web.Lists["Workflow Tasks"], web.Lists["Workflow History"]);

    // Checked: Allow this workflow to be manually started by an authenticated user with Edit Item permissions.
    assoc.AllowManual = true;

    // Checked: Require Manage Lists Permissions to start the workflow.
    if (assoc.AllowManual)
        SPBasePermissions emptyMask = SPBasePermissions.EmptyMask;
        emptyMask |= SPBasePermissions.ManageLists;
        assoc.PermissionsManual = emptyMask;

    assoc.AllowAsyncManualStart = false;
    assoc.AutoStartCreate = false;
    assoc.AutoStartChange = false;
    string data = GetApprovalWorkFlowData();
    assoc.AssociationData = data;

    // Checked: Start this workflow to approve publishing a major version of an item.
    listTemplateManagement.DefaultContentApprovalWorkflowId = assoc.Id;

private string GetApprovalWorkFlowData()
    string result = string.Empty;
    result = ""
        + " <dfs:myFields xmlns:xsd=\"\" xmlns:dms=\"\" xmlns:dfs=\"\" xmlns:q=\"\" xmlns:d=\"\" xmlns:ma=\"\" xmlns:pc=\"\" xmlns:xsi=\"\">"
        + " <dfs:queryFields></dfs:queryFields>"
        + " <dfs:dataFields>"
        + " <d:SharePointListItem_RW>"
        + " <d:Approvers>"
        + " <d:Assignment>"
        + " <d:Assignee>"
        + " <pc:Person>"
        + " <pc:DisplayName>DMS Template Owners</pc:DisplayName>"
        + " <pc:AccountId>DMS Template Owners</pc:AccountId>"
        + " <pc:AccountType>SharePointGroup</pc:AccountType>"
        + " </pc:Person>"
        + " </d:Assignee>"
        + " <d:Stage xsi:nil=\"true\" />"
        + " <d:AssignmentType>Parallel</d:AssignmentType>"
        + " </d:Assignment>"
        + " </d:Approvers>"
        + " <d:ExpandGroups>false</d:ExpandGroups>"
        + " <d:NotificationMessage>Please review the updated template.</d:NotificationMessage>"
        + " <d:DueDateforAllTasks xsi:nil=\"true\" />"
        + " <d:DurationforSerialTasks>3</d:DurationforSerialTasks>"
        + " <d:DurationUnits>Day</d:DurationUnits>"
        + " <d:CC />"
        + " <d:CancelonRejection>true</d:CancelonRejection>"
        + " <d:CancelonChange>true</d:CancelonChange>"
        + " <d:EnableContentApproval>true</d:EnableContentApproval>"
        + " </d:SharePointListItem_RW>"
        + " </dfs:dataFields>"
        + " </dfs:myFields>";
    return result;

Next question is … How do you figure out the AssociationData xml? I create the OOTB Approval Workflow manually and Create simple Console Application to retrieve the AssociationData xml.

static void Main(string[] args)
        using (SPSite site = new SPSite("http://yoursite"))
            using (SPWeb web = site.OpenWeb("yourweb"))
                SPList listTM = web.Lists["Template Management"];
                SPWorkflowAssociation assoc = listTM.WorkflowAssociations[0];
                string xmlResult = assoc.AssociationData;
    catch (Exception ex)
        Console.WriteLine("ERROR: " + ex.Message);

Create Managed Metadata column (TaxonomyFieldType) in Visual Studio

In this article, I would like to show you on how to create Managed Metadata column programmatically in Visual Studio.
Below is the list of steps:

  1. Open Visual Studio 2010 > File > New Project > Empty SharePoint Project, enter the Project Name and Location. Then click OK.timer1
  2. In SharePoint Customization Wizard, Enter your local site URL and Select Deploy as sandboxed solution. Then click Finish.timer2
  3. Right click on the project in Solution Explorer, then select Add > New Item > Site Column. Then enter the Site Column Name.
  4. Edit Elements.xml to look like:
    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="">
          <Field ID="{a1f36e30-5e09-4357-9db1-f0819183627d}"
              Group="Custom Columns"
              Name="BusinessUnit_1" StaticName="BusinessUnit_1"
              Group="Custom Columns" ShowInViewForms="FALSE" Required="FALSE" Hidden="TRUE" />
  5. Mapped the site column to the Managed Metadata term group and set when Feature Activated.
            public override void FeatureActivated(SPFeatureReceiverProperties properties)
                SPSite site = properties.Feature.Parent as SPSite;
                // Map Managed Metadata site columns
                Guid fieldIdBU = new Guid("{A1F36E30-5E09-4357-9DB1-F0819183627D}");
                Guid noteFieldIdBU = new Guid("{d6594a04-2987-416a-b2ae-e7fd13c48df4}");
                MapManagedMetadataField(fieldIdBU, noteFieldIdBU, site, "Managed Metadata Service", "People", "Business Unit");
            private void MapManagedMetadataField(Guid fieldId, Guid noteFieldId, SPSite site, string sTermStore, string sTermGroup, string sTermSet)
                if (site.RootWeb.Fields.Contains(fieldId))
                    TaxonomySession session = new TaxonomySession(site);
                    if (session.TermStores.Count != 0)
                        var termStore = session.TermStores[sTermStore];
                        var group = GetByName(termStore.Groups, sTermGroup);
                        var termSet = group.TermSets[sTermSet];
                        TaxonomyField field = site.RootWeb.Fields[fieldId] as TaxonomyField;
                        // Set Manage Metadata's Text field to Note field
                        field.TextField = noteFieldId;
                        // Connect to MMS
                        field.SspId = termSet.TermStore.Id;
                        field.TermSetId = termSet.Id;
                        field.TargetTemplate = string.Empty;
                        field.AnchorId = Guid.Empty;
            private Group GetByName(GroupCollection groupCollection, string name)
                if (String.IsNullOrEmpty(name))
                    throw new ArgumentException("Not a valid group name", "name");
                foreach (var group in groupCollection)
                    if (group.Name == name)
                        return group;
                throw new ArgumentOutOfRangeException("name", name, "Could not find the group");

Why do I have to add Note field type ? If you don’t add it, you will have an issue as per my previous article.

_spPageContextInfo properties value

When you start development in SharePoint 2010 or 2013, you will have chance to utilize script to retrieve records from REST service and you definitely CANNOT get away from _spPageContextInfo.

I got this from Marc D Anderson blog and he is brilliant. Below is _spPageContextInfo properties and values.































SharePoint Calculated URL Column

I would like to share my experience in creating Custom Calculated URL column. My objective is to construct a URL from custom calculated column. Hopefully this might save some time for others cause I’ve spent a bit of time to Google it and found this article, but unfortunately it does not work in SharePoint 2010 and 2013.

While trying some silly thing, I ends up making it work and I should also reported it to Microsoft (because it looks like a bug). For now, I wouldn’t bother and as long as it works … =)


  1. Create a SharePoint list that looks like below:
  2. Create calculated column for URL. I would like to add calculate URL column “CaseURL” that has formula  “http://site/web/Pages/Case.aspx?caseno=[CaseNo]“. So, users can click the link and go to Case.aspx page with URL parameter passed. Instead of selecting “Single line of Text” as the data type returned from this formula, try to select “Number” or “Currency” or “Date and Time“. Then click OK to create the column.
  3. Done and we can test it.
%d bloggers like this: