Copying a newlywed’s SharePoint document

A couple of years ago, I wrote some code that copied documents from one SharePoint library to another. My first attempt looked something like this (SrcItem is the SPListItem I am copying, and DestParentFolder is the SPFolder that I want to copy into):

Byte[] FileContents = SrcItem.File.OpenBinary();
SPFile NewFile = DestParentFolder.Files.Add(
        DestParentFolder.ServerRelativeUrl + “/” + SrcItem.File.Name, // File name
        FileContents, // Data in the file
        SrcItem.File.Author, // Original creator
        SrcItem.File.ModifiedBy, // Latest modifier
        SrcItem.File.TimeCreated, // When created
        SrcItem.File.TimeLastModified);
NewFile.Update();
DestParentFolder.Update();
DestList.Update();

This copied the document, but despite specifying the file creation and modification time, SharePoint used the current time instead. Grrr. My second attempt was this (I found the idea here):

Byte[] FileContents = SrcItem.File.OpenBinary();
SPFile NewFile = DestParentFolder.Files.Add(
        DestParentFolder.ServerRelativeUrl + “/” + SrcItem.File.Name, // File name
        FileContents, // Data in the file
        SrcItem.File.Author, // Original creator
        SrcItem.File.ModifiedBy, // Latest modifier
        SrcItem.File.TimeCreated, // When created
        SrcItem.File.TimeLastModified);
SPListItem NewItem = NewFile.Item;
NewItem["Created"] = SrcItem.File.TimeCreated.ToLocalTime();
NewItem["Modified"] = SrcItem.File.TimeLastModified.ToLocalTime();
NewItem.Update();
NewFile.Update();
DestParentFolder.Update();
DestList.Update();

Ok, that’s better. Time passed, the world fell twice around the sun, and all was well until Amy decided to get married. Being an old-fashioned kind of girl, she changed her name and we duly updated her Active Directory entry. SharePoint picked up her new name just fine and displayed it proudly next to her document. I admit I felt a bit dewy-eyed. Sometime later, the code executed to copy this document and blooey! “User not found”. Seems that SrcItem.File.Author (and .ModifiedBy) returns a SPUser based on the old name, which no longer exists.

Back to the drawing board. I finally ended up with this (I found the idea here):

SPUser myAuthor;
try
{
        myAuthor = SrcItem.File.Author;
}
catch (Exception ex)
{
        SPField spField = SrcItem.Fields.GetFieldByInternalName(“Author”);
        string dislayName = spField.Title;
        string author = SrcItem[dislayName].ToString();
        int userId = Convert.ToInt32(author.Substring(0, author.IndexOf(“;#”)));
        myAuthor = SrcWeb.AllUsers.GetByID(userId);
}
SPUser myEditor;
try
{
        myAuthor = SrcItem.File.ModifiedBy;
}
catch (Exception ex)
{
        SPField spField = SrcItem.Fields.GetFieldByInternalName(“Editor”);
        string dislayName = spField.Title;
        string editor = SrcItem[dislayName].ToString();
        int userId = Convert.ToInt32(editor.Substring(0, author.IndexOf(“;#”)));
        myEditor = SrcWeb.AllUsers.GetByID(userId);
}

Byte[] FileContents = SrcItem.File.OpenBinary();
SPFile NewFile = DestParentFolder.Files.Add(
        DestParentFolder.ServerRelativeUrl + “/” + SrcItem.File.Name, // File name
        FileContents, // Data in the file
        myAuthor, // Original creator
        myEditor, // Latest modifier
        SrcItem.File.TimeCreated, // When created
        SrcItem.File.TimeLastModified);
SPListItem NewItem = NewFile.Item;
NewItem["Created"] = SrcItem.File.TimeCreated.ToLocalTime();
NewItem["Modified"] = SrcItem.File.TimeLastModified.ToLocalTime();
NewItem.Update();
NewFile.Update();
DestParentFolder.Update();
DestList.Update();

The above code correctly copies the document with Amy’s new name. Seems like a lot of effort to make something work when SharePoint already recognized the new name!

Leave a Reply