3 minute read

About a week ago I wrote an article about the “Content Organizer” feature of SharePoint 2010.

The “Content Organizer” feature makes it possible to route all kind of different information within your SharePoint site. If you want to read more about this feature click here.

In certain scenarios you would like to be able to re-submit documents when certain metadata of that document is changed. Out of the box this isn’t possible this means you will have to create a custom solution.

What you can do is create a list settings page that you will have to register on document libraries.

With this page you can enable the re-submitting feature and select the fields that have to be changed if the file needs to be re-submitted.

If you enable the re-submitting feature on the page it will install an event receiver on the current list. This event receiver will run on the ItemUpdated event. In the ItemUpdated event you can then check which fields are changed and then send the document for re-routing.

I hear you asking how can I submit a file for routing. Let’s take a look at the ItemUpdated receiver I have written.

/// <summary>
/// An item is being updated.
/// </summary>
public override void ItemUpdated(SPItemEventProperties properties)
{
    base.ItemUpdated(properties);

    if (CheckForReRouteItem(properties))
    {
        if (ReRoutItem(properties))
        {
            properties.ListItem.Delete();
        }
    }
}

This code will be executed by the event Receiver. The method Check ForReRouteItem will check if certain fields were changed.

private bool CheckForReRouteItem(SPItemEventProperties properties)
{
    List<string> changesFields = GetField(properties);

    foreach (string field in changesFields)
    {
        if (properties.AfterProperties[field] != properties.BeforeProperties[field])
        {
            return true;
        }
    }

    return false;
}

In the above method the fields for which we have to check if they are changed are retrieved by another method called GetFields(properties). This method will retrieve the fields that are saved in the property bag by the list settings page.

If a field is changed the method will return true to indicate that the files needs to be submitted to the Content Organizer.

private bool ReRoutItem(SPItemEventProperties properties)
{
    Guid webId = properties.Web.ID;
    Guid siteId = properties.SiteId;
    bool retVal = false;

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        using (SPSite site = new SPSite(siteId))
        {
            using (SPWeb web = site.OpenWeb(webId))
            {
                SPFile file = properties.ListItem.File;
                string fileType = properties.ListItem.ContentType.Name;
                SPFieldCollection fields = file.Item.Fields;
                List<RecordsRepositoryProperty> itemProperties = new List<RecordsRepositoryProperty>();

                foreach (SPField spField in fields)
                {
                    try
                    {
                        string fieldValue = file.Item[spField.Id] != null ? file.Item[spField.Id].ToString() : string.Empty;
                        string value = spField.GetFieldValue(fieldValue) as string;
                        RecordsRepositoryProperty property = new RecordsRepositoryProperty
                        {
                            Name = spField.Title,
                            Type = spField.TypeAsString,
                            Value = value
                        };
                        itemProperties.Add(property);
                    }
                    catch (ArgumentException) { }
                }

                string result = string.Empty;
                OfficialFileResult outcome = OfficialFileCore.SubmitFile(properties.Web, file.OpenBinary(), itemProperties.ToArray(), fileType, file.Web.Url + file.Url, out result);
                if (outcome == OfficialFileResult.Success)
                {
                    retVal = true;
                }
            }
        }
    });

    return retVal;
}

The above method performs the actual submitting of the file to the Content Organizer by calling OfficialFileCore.SubmitFile().

This method will return an OfficialFileResult to indicate whether the submitting was successful of not.

Important: With submitting the file we had a problem because it was giving us an outcome of NotFound every time we submitted the file. After debugging the SharePoint dlls we found out that Microsoft performs the following method EcmDocumentRoutingWeb.IsSubmitter(web)):

internal static bool IsSubmitter(SPWeb web)
{
    if (web == null)
    {
        return false;
    }
    bool flag = false;
    try
    {
        string str = web.Properties["_dlc_RepositoryUsersGroup"];
        if (!string.IsNullOrEmpty(str))
        {
            flag = web.IsCurrentUserMemberOfGroup(int.Parse(str, NumberFormatInfo.InvariantInfo));
        }
    }
    catch (FileNotFoundException exception)
    {
        ULS.SendTraceTag(0x636d7539, ULSCat.msoulscat_DLC_Routing, ULSTraceLevel.Medium, "Routing Engine: User does not have permissions to submit to this site. Exception: {0}", new object[] { exception.Message });
        flag = false;