In SharePoint there is no easy way to copy over a discussion board thread over to another board. So for instance, if there is a thread that is in the wrong place, and needs to be moved over to a different discussion board that is of a different topic, you are fresh out of luck. The tradition copy items through the “Manage Site Content and Structure” just doesn’t work. The only way I found to do this while maintaining all the information is to copy it over programmatically.
In this example I created a drop down list of the the discussion boards on a site:
foreach (SPList l in web.Lists)
{
if (l.BaseTemplate == SPListTemplateType.DiscussionBoard)
{
ListItem entry = new ListItem();
entry.Text = l.Title;
entry.Value = web.Url + "/" + l.RootFolder;
ddl.Items.Add(entry);
}
}
Then I created a method to copy the discussion over once the source board, discussion, and destination board were set.
string site = this.Page.Request.Url.ToString();
using (SPSite spsSite = new SPSite(site))
{
using (SPWeb web = spsSite.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList splSource = web.GetList(ddlSourceList.SelectedItem.Value.ToString());
SPListItem spliDiscussion = web.GetListItem(ddlSourceDiscussion.SelectedItem.Value.ToString());
SPList splDestination = web.GetList(ddlDestinationList.SelectedItem.Value.ToString());
try
{
SPFolder fldrDiscussion = web.GetFolder(ddlSourceDiscussion.SelectedValue);
SPListItemCollection listCol = splDestination.Items;
SPListItem discussion = SPUtility.CreateNewDiscussion(listCol, spliDiscussion[SPBuiltInFieldId.Title].ToString());
discussion[SPBuiltInFieldId.Body] = spliDiscussion[SPBuiltInFieldId.Body];
discussion[SPBuiltInFieldId.Author] = spliDiscussion[SPBuiltInFieldId.Author];
discussion[SPBuiltInFieldId.Editor] = spliDiscussion[SPBuiltInFieldId.Editor];
discussion[SPBuiltInFieldId.Created] = spliDiscussion[SPBuiltInFieldId.Created];
discussion.Update();
CopyAttachments(spliDiscussion, discussion);
discussion.Update();
//copy replies
SPQuery q = new SPQuery();
q.Query = "<OrderBy><FieldRef Name='Title'/></OrderBy>";
q.Folder = fldrDiscussion;
SPListItemCollection flc = splSource.GetItems(q);
foreach (SPListItem li in flc)
{
SPListItem reply = SPUtility.CreateNewDiscussionReply(discussion);
reply[SPBuiltInFieldId.Body] = li[SPBuiltInFieldId.Body];
reply[SPBuiltInFieldId.Author] = li[SPBuiltInFieldId.Author];
reply[SPBuiltInFieldId.Editor] = li[SPBuiltInFieldId.Editor];
reply[SPBuiltInFieldId.Created] = li[SPBuiltInFieldId.Created];
reply.Update();
CopyAttachments(li, reply);
reply.Update();
discussion.Update();
}
//delete discussion
spliDiscussion.Delete();
this.Page.Response.Redirect(this.Page.Request.RawUrl);
}
catch { }
finally
{
}
}
}
Here is the method for copying the attachments over for the discussion as well:
private void CopyAttachments(SPListItem spliDiscussion, SPListItem targetItem)
{
try
{
//get the folder with the attachments for the source item
SPFolder fldrDiscAttachments = spliDiscussion.Web.Folders["Lists"].SubFolders[spliDiscussion.ParentList.Title].SubFolders["Attachments"].SubFolders[spliDiscussion.ID.ToString()];
//Loop over the attachments, and add them to the target item
foreach (SPFile file in fldrDiscAttachments.Files)
{
byte[] binFile = file.OpenBinary();
targetItem.Attachments.AddNow(file.Name, binFile);
}
}
catch { }
finally
{
}
}
There is one area where this is lacking, and that is the embedded content. (ie. if an image is attached, and then embedded with the full path URL, that will break, so you will either have to compensate for this in your code, or else just go into the posts and change the uploaded+embedded content manually.