Sending files to a record center using the SP2010 webservice Officialfile.asmx

When you send a document to the record center through  the web service officialfile.asmx there is a way to retain and even add more metadata to the file.

In our case, we wanted to use the same content type on the team sites as inn the record center, but with some additional columns in the record center. Since all our content types are pushed out through a Managed Metadata service, they are easy to maintain and update. But we felt a bit uncomfortable if we had to expose metadata fields only meant for the record center in all our team sites. So how could we add them?

It turned out we could use “RecordsRepositoryProperty” to accomplish this. In the code below, I generate a RecordsRepositoryProperty array of all the fields to the SPListItem we are about to send to the webservice and then I add another two “custom” properties. (You can of course add as many or few as you would like.)

               SPListItem item = workflowProperties.Item;
               SPFile file = item.File;
               byte[] bytes = file.OpenBinary();
               string fileType = file.Item.ContentType.Name;
               SPFieldCollection fields = file.Item.Fields;

//I’m adding two additional properties, hence the +2
OfficialFile.RecordsRepositoryProperty[] properties = new OfficialFile.RecordsRepositoryProperty[fields.Count + 2];               GenerateRecordsRepositoryArray(file, fields, properties);

               System.Configuration.AppSettingsSection s = GetWebConfigSiteConfigurations();

               OfficialFile.RecordsRepository sv = new OfficialFile.RecordsRepository();
               string recordCenterUrl = s.Settings["RecordCenterUrl"].Value;
               sv.Url = recordCenterUrl + "/_vti_bin/officialfile.asmx";
               string UserName = s.Settings["RecordCenterLogInUserName"].Value;
               string sDomain = s.Settings["RecordCenterLogInDomain"].Value;
               string PassWord = Password; //You should use some encryption here…

               CredentialCache credentialCache = new CredentialCache();
               NetworkCredential credentials = new NetworkCredential(UserName, PassWord, sDomain);

               credentialCache.Add(new Uri(recordCenterUrl), "NTLM", credentials);
               //credentialCache.Add(new Uri(recordCenterUrl), "Negotiate", credentials); //For some reason or another, this would not work?
               sv.Credentials = credentialCache;

               string fullUrl = recordCenterUrl + string.Format("{0}/{1}", item.ParentList.ParentWebUrl, item.File.Url);

               SubmitStatus = "Sending";
               SubmitStatus = sv.SubmitFile(bytes, properties, item.ContentType.ToString(), fullUrl, file.ModifiedBy.LoginName);
               LogUtility.LogVerbose(string.Format("Result code from submitting {0} to the record center is: {1}.", file.Title, SubmitStatus), traceCategory);

 

private void GenerateRecordsRepositoryArray(SPFile file, SPFieldCollection fields, OfficialFile.RecordsRepositoryProperty[] properties)
    {
        // Create a RecordsRepositoryProperty for each metadata field.
        int i = 0;
        foreach (SPField field in fields)
        {
            try
            {
                string value = Convert.ToString(field.GetFieldValue(Convert.ToString(file.Item[field.Title])));
                LogUtility.LogVerbose(string.Format("Name:{0}, Type:{1}, Value:{2}", field.Title, field.TypeAsString, value), traceCategory);
                OfficialFile.RecordsRepositoryProperty property = new OfficialFile.RecordsRepositoryProperty
                {
                    Name = field.Title,
                    Type = field.TypeAsString,
                    Value = value
                };
                properties[i] = property;
            }
            catch (Exception exception)
            {
                LogUtility.LogError(string.Format("Error - Failed to process field {0}", field.Title), exception, traceCategory);
            }
            i++;
        }

        //Add the two custom "field", in order for the content organizer rules to pick them up.
        OfficialFile.RecordsRepositoryProperty property1 = new OfficialFile.RecordsRepositoryProperty
        {
            Name = FolderIDField,
            Type = "Text",
            Value = FolderID
        };
        properties[i] = property1;
        OfficialFile.RecordsRepositoryProperty property2 = new OfficialFile.RecordsRepositoryProperty
        {
            Name = SubFolderTitleField,
            Type = "Text",
            Value = SubSiteTitle
        };
        i++;
        properties[i] = property2;
    }

 

These properties turn up in the record center’s drop off library in a column called “original properties”. So how can this be useful? It is really quite easy: If you have a column (on the record centers content type) whose name is the same as the RecordsRepositoryPropery’s name you are sending over, SharePoint will match them for you!

So in our case, we have changed the content types in the record center only, by adding two more columns. We are sending RecordsRepositoryProperties over and matching the names. Then we can even use Content organizer rules to move the items along to the records library!