Archive

Archive for September, 2011

Configure Retention Policy through Code

September 4th, 2011 Comments off

Information Policies are nice to have it. It is also a reasonably simple job to configure an IM policy through user interface. But in order to automate the process, sometime you want to configure IM policies from code. In the below example I will give you some hint that how you can configure retention policy from the code. 

For this test I have created a content type in content type hub. Yes I recommend, plan your content types properly and use content type hub on all the possible places. It is a great feature in SharePoint 2010. Alright back to the today’s topic. Open visual studio 2010 and create a feature. Add a feature receiver to the feature and start writing the code. 

Something is better to understand on the first hand about retention policy. Retention policy can be defined for records and non-records.  Also you can set different stages for a retention policy and can set different actions for each stage. 

/// <summary>
/// Defines a constant used as the key for the workflow template name.
/// </summary>
private const string WorkFlowTemplateName = "Disposition Approval";

/// <summary>
/// Defines a constant used as the key for the Records Centre name to use in SendTo link.
/// </summary>
private const string RecordCenterNameForSendTo = "Corporate Records Centre";

/// <summary>
/// Defines a constant used as the key for the Records Centre name to use in SendTo link.
/// </summary>
private const string RecordCenterURLForSendTo = "<a href="http://archive/_vti_bin/officialfile.asmx">http://archive/_vti_bin/officialfile.asmx</a>";

/// <summary>
/// Gets or sets the SendTo ID.
/// </summary>
protected string SendToId { get; set; }

/// <summary>
/// This method will publish the content types from Content Type Hub.
/// </summary>
/// <param name="properties">The SPFeatureReceiverProperties object.</param>
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    try
    {
        if (properties == null)
        {
            throw new ArgumentNullException("properties");
        }

        SPSite site = properties.Feature.Parent as SPSite;

        using (SPWeb web = site.OpenWeb(site.RootWeb.ID))
        {
            this.SendToId = GetRCSendToLinkId(site);

            string ctypeName = "MyContentType";
            SPContentType ctype = web.ContentTypes[ctypeName];
            this.AddPolicyToContentType(ctype); 
        }
    }
    catch (Exception e)
    {
        // handle the exception here
    }
}

/// <summary>
/// Returns the SPOfficialFileHost for record center SendTo link.
/// </summary>
/// <param name="site">The feature parent SPSite object.</param>
/// <returns>ID of the send to link.</returns>
protected static string GetRCSendToLinkId(SPSite site)
{
     string sendToID = string.Empty;
     if (site != null)
     {
         string sendToHostName = string.Empty;

         SPSecurity.RunWithElevatedPrivileges(delegate
         {
             SPWebApplication webApp = site.WebApplication;
             for (int i = 0; i < webApp.OfficialFileHosts.Count; i++)
             {
                 SPOfficialFileHost host = webApp.OfficialFileHosts[i];
                 sendToHostName = host.OfficialFileName;

                 if (sendToHostName.Equals(RecordCenterNameForSendTo))
                 {
                     sendToID = host.UniqueId.ToString();
                     break;
                 }
             }
         });
     }

     return sendToID;
}

/// <summary>
/// Add a policy to content type.
/// </summary>
/// <param name="ctype">The content type.</param>
protected void AddPolicyToContentType(SPContentType ctype)
{
    string policyFeatureId = "Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration";

    Policy policy = Policy.GetPolicy(ctype);

    if (policy == null)
    {
        Policy.CreatePolicy(ctype, null);
        policy = Policy.GetPolicy(ctype);
    }

    if (policy.Items[policyFeatureId] == null)
    {
        string customData = string.Empty;

        if (ctype != null)
        {
            string workflowID = string.Empty;
            SPWorkflowAssociation workflowTemplate = ctype.WorkflowAssociations.GetAssociationByName(WorkFlowTemplateName, System.Globalization.CultureInfo.CurrentCulture);

            if (workflowTemplate != null)
            {
                workflowID = workflowTemplate.ParentAssociationId.ToString();
            }

            string ctypeName = ctype.Name;

            if (ctypeName.Equals("MyContentType"))
            {�
                customData = "<Schedules nextStageId='4' default=\"false\">"
                    + "<Schedule type='Default'>"
                    + "<stages>"
                    + "<data stageId='1'>"
                    + "<formula id=\"Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Formula.BuiltIn\">"
                        + "<number>1</number>"
                        + "<property>Modified</property>"
                        + "<period>Years</period>"
                    + "</formula>"
                    + "<action type=\"action\" id=\"Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Action.DeletePreviousVersions\" />"
                    + "</data>"
                    + "<data stageId='2'>"
                    + "<formula id=\"Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Formula.BuiltIn\">"
                        + "<number>1</number>"
                        + "<property>Modified</property>"
                        + "<period>Years</period>"
                    + "</formula>"
                    + "<action type=\"action\" id=\"Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Action.SubmitFileLink\" destnExplanation=\"Transferred due to organizational policy\" destnId=\"" + this.SendToId + "\" destnName=\"" + RecordCenterNameForSendTo + "\" destnUrl=\"" + RecordCenterURLForSendTo + "\" />"
                    + "</data>"
                    + "</stages>"
                    + "</Schedule>"
                    + "<Schedule type='Record'>"
                    + "<stages>"
                    + "<data stageId='3' recur='true' offset='1' unit='years'>"
                    + "<formula id=\"Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Formula.BuiltIn\">"
                        + "<number>10</number>"
                        + "<property>_vti_ItemDeclaredRecord</property>"
                        + "<period>Years</period>"
                    + "</formula>"
                    + "<action type=\"workflow\" id=\"" + workflowID + "\" />"
                    + "</data>"
                    + "</stages>"
                    + "</Schedule>"
                    + "</Schedules>";

                policy.Items.Add(policyFeatureId, customData);
            }
        }
    }
}

So what the above code is doing. It is creating a retention policy for provided content type. It is creating
retention policy for non-records (documents) and for records. As you can see you can define multiple stages
for policy. In each stage you can define different actions. Here in first stage it is deleting all the
previous versions and in next stage moving document to record centre. In my case record centre name is
Corporate Record Centre. For records it is staring a disposition workflow after a defined time.
You have to create this disposition workflow for the content type separately.

So that’s all really. Here how it looks after the feature activation.

Have fun ……… :)