Configure Information Management Policy programmatically

Following my previous article to set Expiry column using Reusable Workflow, I would also like to Configure Information Management Policy at Content type programmatically on Feature Activated.

What I could do first is to manually configure Information Management Policy at Content type to look like below.

RetentionPolicy1

 

Then, I’ve created simple SharePoint console application to retrieve the Information Management Policy custom data. It looks like below:

using System;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using Microsoft.Office.RecordsManagement.InformationPolicy;

namespace GetRetentionPolicyCustomData
{
    class Program
    {
        static void Main(string[] args)
        {
            using (SPWeb web = new SPSite("http://yourSiteURL").OpenWeb())
            {
                // Get Policy Custom Data
                string contentTypeName = "YourContentTypeName";
                SPContentType contentType = web.ContentTypes.Cast<SPContentType>().Where(cty => cty.Name.Trim().ToLower() == contentTypeName.ToLower()).FirstOrDefault();

                if (contentType != null)
                {
                    Policy policy = Policy.GetPolicy(contentType);
                    if (policy != null)
                    {
                        foreach (PolicyItem eachPolicy in policy.Items)
                        {
                            string customdata = eachPolicy.CustomData;
                            Console.WriteLine("Policy " + eachPolicy.Name + ": " + customdata);
                        }
                    }
                }
            }
        }
    }
}

 

And you will get something like below in Information Management Policy Custom Data variable.

 

<Schedules nextStageId="3">
 <Schedule type="Default">
  <stages>
   <data stageId="1">
    <formula id="Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Formula.BuiltIn">
     <number>0</number>
     <property>NearExpiry</property>
     <propertyId>15686f6f-8d25-4eba-be79-7792663f4675</propertyId>
     <period>days</period>
    </formula>
    <action type="workflow" id="f5c7ade6-1a7e-4231-bce8-81041b1b7fcd" />
   </data>
   <data stageId="2">
    <formula id="Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Formula.BuiltIn">
     <number>7</number>
     <property>Expiration</property>
     <propertyId>d2681865-a6d3-4d5d-850b-cd2a1be22b31</propertyId>
     <period>years</period>
    </formula>
    <action type="action" id="Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Action.MoveToRecycleBin" />
   </data>
  </stages>
 </Schedule>
</Schedules>

 

Now, Delete the Information Management Policy that you’ve configured manually on the Content Type and let implements it programmatically.
In Site Collection scope feature event receiver:

 

using Microsoft.Office.RecordsManagement.InformationPolicy;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace InformationManagementPolicy
{
    /// <summary>
    /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
    /// </summary>
    /// <remarks>
    /// The GUID attached to this class may be used during packaging and should not be modified.
    /// </remarks>

    [Guid("92cf61e2-0ead-4a9d-b22d-4ff8969e1d05")]
    public class RetentionPolicyEventReceiver : SPFeatureReceiver
    {
        private const string LIST_WORKFLOWTASKS = "Workflow Tasks";
        private const string LIST_WORKFLOWHISTORY = "Workflow History";
        private const string COLUMN_EXPIRATION = "Expiration";
        private const string COLUMN_NEAREXPIRY = "NearExpiry";
        private const string WORKFLOW_SENDNOTIFICATION = "Send Expiry Notification Workflow";

        /// <summary>
        /// Event handler when feature activated
        /// </summary>
        /// <param name="properties"></param>
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPWeb web = new SPSite(((SPSite)properties.Feature.Parent).ID).OpenWeb())
                    {
                        string contentTypeName = "YourContentTypeName";
                        SPContentType contentType = web.ContentTypes.Cast<SPContentType>().Where(cty => cty.Name.Trim().ToLower() == contentTypeName.Trim().ToLower()).FirstOrDefault();
                        if (contentType != null)
                        {
                            // Attach Retention Policies to Content Type
                            CreateRetentionPolicyInContentType(web, contentType, COLUMN_EXPIRATION, COLUMN_NEAREXPIRY);
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                // exception "Issue found when CNP.CWE.CDA.Workflows feature activated."
            }
        }

        /// <summary>
        /// Event handler when feature deactivating
        /// </summary>
        /// <param name="properties"></param>
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPWeb web = new SPSite(((SPSite)properties.Feature.Parent).ID).OpenWeb())
                    {
                        string contentTypeName = "YourContentTypeName";
                        SPContentType contentType = web.ContentTypes.Cast<SPContentType>().Where(cty => cty.Name.Trim().ToLower() == contentTypeName.Trim().ToLower()).FirstOrDefault();
                        if (contentType != null)
                        {
                            // Delete Retention Policies to Content Type
                            if (Policy.GetPolicy(contentType) != null)
                                Policy.DeletePolicy(contentType);
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                // exception "Issue found when CNP.CWE.CDA.Workflows feature deactivating."
            }
        }

        // Uncomment the method below to handle the event raised after a feature has been installed.
        //public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        //{
        //}

        // Uncomment the method below to handle the event raised before a feature is uninstalled.
        //public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        //{
        //}

        // Uncomment the method below to handle the event raised when a feature is upgrading.
        //public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)
        //{
        //}

        #region Private methods

        /// <summary>
        /// Method to attach retention policy to specified content type
        /// </summary>
        /// <param name="web">current web</param>
        /// <param name="contentType">content type</param>
        /// <param name="expirationFieldName">expiration field name</param>
        /// <param name="nearExpiryFieldName">near expiry field name</param>
        private void CreateRetentionPolicyInContentType(SPWeb web, SPContentType contentType, string expirationFieldName, string nearExpiryFieldName)
        {
            try
            {
                SPField expiration = contentType.Fields.Cast<SPField>().Where(fld => fld.InternalName == expirationFieldName).FirstOrDefault();
                SPField nearExpiry = contentType.Fields.Cast<SPField>().Where(fld => fld.InternalName == nearExpiryFieldName).FirstOrDefault();
                SPWorkflowAssociation workflowAssoc = contentType.WorkflowAssociations.Cast<SPWorkflowAssociation>().Where(assoc => assoc.Name == WORKFLOW_SENDNOTIFICATION).FirstOrDefault();

                if (expiration != null && nearExpiry != null && workflowAssoc != null)
                {
                    if (Policy.GetPolicy(contentType) == null)
                        Policy.CreatePolicy(contentType, null);
                    Policy policy = Policy.GetPolicy(contentType);

                    string policyCustomData = GeneratePolicyCustomData(expiration, nearExpiry, workflowAssoc.ParentAssociationId.ToString());
                    policy.Items.Add("Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration", policyCustomData);
                    contentType.Update();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Method to generate Policy Custom Data
        /// </summary>
        /// <param name="expiration">expiration column</param>
        /// <param name="nearExpiry">near expiry column</param>
        /// <param name="parentAssociationId">send notification parent workflow association</param>
        /// <returns></returns>
        private string GeneratePolicyCustomData(SPField expiration, SPField nearExpiry, string parentAssociationId)
        {
            StringBuilder sb = new StringBuilder();
            try
            {
                sb.AppendLine("<Schedules nextStageId='3'>");
                sb.AppendLine("<Schedule type='Default'>");
                sb.AppendLine("<stages>");

                // Send Expiry Notification when Today = Near Expiry + 0 days
                sb.AppendLine("<data stageId='1'>");
                sb.AppendLine("<formula id='Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Formula.BuiltIn'>");
                sb.AppendLine("<number>0</number>");
                sb.AppendFormat("<property>{0}</property>", nearExpiry.InternalName);
                sb.AppendFormat("<propertyId>{0}</propertyId>", nearExpiry.Id.ToString());
                sb.AppendLine("<period>days</period>");
                sb.AppendLine("</formula>");
                sb.AppendFormat("<action type='workflow' id='{0}' />", parentAssociationId);
                sb.AppendLine("</data>");

                // Delete the item after Expiration + 7 years
                sb.AppendLine("<data stageId='2'>");
                sb.AppendLine("<formula id='Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Formula.BuiltIn'>");
                sb.AppendLine("<number>7</number>");
                sb.AppendFormat("<property>{0}</property>", expiration.InternalName);
                sb.AppendFormat("<propertyId>{0}</propertyId>", expiration.Id.ToString());
                sb.AppendLine("<period>years</period>");
                sb.AppendLine("</formula>");
                sb.AppendLine("<action type='action' id='Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Action.MoveToRecycleBin' />");
                sb.AppendLine("</data>");

                sb.AppendLine("</stages>");
                sb.AppendLine("</Schedule>");
                sb.AppendLine("</Schedules>");
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return sb.ToString();
        }
        #endregion
    }
}
Advertisements

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

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: