Fix: Content Approval always Modified By System Account

If you found this article, it means you know how to setup OOB SharePoint Approval Workflow and Content Approval and just realize the issue where Modified By always be System Account.

For those of you who wants to know how to set approval and content approval; or find issue where content approval not approved after approval workflow completed; there is a great article to show you how to use a workflow to manage content approval for a library.

Issue

Content Approval issue

Resolution

1. Update SharePoint OOB Approval Workflow Start Option > Clear Start this workflow to approve publishing a major version of an item.

ContentApproval2

2. Update SharePoint OOB Approval Workflow Enable Content Type Option > Update the approval status after the workflow is completed (use this workflow to control content approval).

ContentApproval3

3. Implement ItemUpdated event receiver to start approval workflow manually if user check in major version.

public override void ItemUpdated(SPItemEventProperties properties)
{
 base.ItemUpdated(properties);
 int iBefore, iAfter;
 iBefore = (int.TryParse(properties.BeforeProperties["vti_level"].ToString(), out iBefore) ? iBefore : -1);
 iAfter = (int.TryParse(properties.AfterProperties["vti_level"].ToString(), out iAfter) ? iAfter : -1);
 if (iAfter != iBefore)
 {
  StartWorkflow(properties.ListItem, "Templates Approval Workflow");
 }
}

public void StartWorkflow(SPListItem listItem, string wfName)
{
 SPSecurity.RunWithElevatedPrivileges(delegate()
 {
  using (SPSite site = new SPSite(listItem.Web.Site.ID))
  {
   using (SPWeb web = site.OpenWeb(listItem.Web.ID))
   {
    SPList listTemplate = web.Lists.TryGetList(listItem.ParentList.Title);
    if(listTemplate != null)
    {
     SPListItem currItem = listTemplate.Items[listItem.UniqueId];
     SPWorkflowAssociationCollection associationCollection = listTemplate.WorkflowAssociations;
     SPWorkflowAssociation approvalWorkflow = associationCollection.GetAssociationByName(wfName, CultureInfo.CurrentCulture);

     if(approvalWorkflow != null)
      site.WorkflowManager.StartWorkflow(currItem, approvalWorkflow, approvalWorkflow.AssociationData, true);
    }
   }
  }
 });
}

4. Implement WorkflowCompleted event receiver.

public override void WorkflowCompleted(SPWorkflowEventProperties properties)
{
 base.WorkflowCompleted(properties);

 PublishItemBasedOnWorkflowStatus(properties);
}

private void PublishItemBasedOnWorkflowStatus(SPWorkflowEventProperties properties)
{
 SPSecurity.RunWithElevatedPrivileges(delegate()
 {
  using (SPSite site = new SPSite(properties.WebUrl))
  {
   using (SPWeb web = site.OpenWeb(properties.RelativeWebUrl))
   {
    SPListItem workflowHistoryItem = GetWorkflowHistoryItem(web, properties);
    if (workflowHistoryItem == null)
     return;

    SPListItem item = GetItemForThisWorkflow(properties);

    //Provide association name as approval workflow name
    string associationName = "Approval";

    //This code runs for each workflow available in the site
    //so just make sure you are not intrupting other workflow (for instance your custom one, collect feedback etc)
    //and make sure it approve or reject for your specific libraries
    MarkItemApproveOrRejectBasedWorkflowStatus(item, web, associationName, properties);
   }
  }
 });
}

private void MarkItemApproveOrRejectBasedWorkflowStatus(SPListItem item, SPWeb web, string associationName, SPWorkflowEventProperties properties)
{
 SPListItem latestApprovalTask = GetLatestApprovalTask(properties, web);
 string status = (latestApprovalTask != null ? latestApprovalTask["WorkflowOutcome"].ToString() : string.Empty);

 //we are only interested in OUR WORKFLOW ASSOCIATION (i.e. configured in Settings List)
 //if it is different, then it returns empty string
 if (string.IsNullOrEmpty(status))
  return;

 item.ModerationInformation.Status = SPModerationStatusType.Denied;
 if (status.Equals("Approved"))
  item.ModerationInformation.Status = SPModerationStatusType.Approved;

 item.Update();
}

private SPListItem GetLatestApprovalTask(SPWorkflowEventProperties properties, SPWeb web)
{
 SPListItem item = null;
 string caml = @"y{0}";

 SPQuery query = new SPQuery();
 query.Query = string.Format(caml, properties.InstanceId);
 query.RowLimit = 1;
 SPList list = web.Lists["Workflow Tasks"];
 SPListItemCollection items = list.GetItems(query);
 if (items.Count > 0)
  item = items[0];

 return item;
}

private SPListItem GetItemForThisWorkflow(SPWorkflowEventProperties properties)
{
 SPListItem itemRelated = null;
 using (SPWeb web = new SPSite(properties.WebUrl).OpenWeb())
 {
  //Get the workflow instance Id
  String wfInstanceId = properties.InstanceId.ToString();

  //Assume "Tasks" list manages all the workflow tasks
  SPList listRelated = web.Lists[properties.ListId];
  SPQuery query = new SPQuery();
  query.Query = String.Format("{0}", wfInstanceId);
  SPListItemCollection itemColl = listRelated.GetItems(query);
  if (itemColl.Count > 0)
   itemRelated = itemColl[0];
 }
 return itemRelated;
}

private SPListItem GetWorkflowHistoryItem(SPWeb web, SPWorkflowEventProperties properties)
{
 string caml = string.Format(@"{0}2", properties.InstanceId.ToString("B"));

 SPList workflowHistory = web.Lists.TryGetList(SPResource.GetString("DefaultWorkflowHistoryListName", new object[0]));
 SPQuery query = new SPQuery();
 query.Query = caml;
 SPListItemCollection items = workflowHistory.GetItems(query);

 if (items.Count >= 1)
  return items[0];

 return null;
}

Reference
http://blog.mmasood.com/2012/12/approval-worfklow-showing-system.html

Advertisements

Tagged: , , , , , , , , , , , ,

2 thoughts on “Fix: Content Approval always Modified By System Account

  1. Grimpeur Fou 09/09/2014 at 2:01 AM Reply

    Hello,
    Thank you for this solution.

    When I use it, the workflow is launched when I click “publish” on the document BUT the workflow initialization form is not displayed, so I cannot change the approvers. This is a limitation of your solution.

    Regards,

    • tjenho 09/11/2014 at 7:34 AM Reply

      Does it not launch the workflow initiation form? its been a while back that I’ve done it for one of the client. Luckily its not the requirement at the time =)

      Thanks for clarifying

Leave a Reply

Please log in using one of these methods to post your comment:

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

%d bloggers like this: