Recently, for a very large customer, I had to fix some issues with regards to SharePoint My Site lists. Destroying and recreating each person's My Site was not an option.
This scenario actually happened due to the fact that should you get the dreaded SPException which indicates a "Save Conflict" while updating a SPList object, it will wipe out some of your properties. I will show an example in code in a Console Application.
So, let's start with the Main method:
[STAThread]
static void Main(string[] args)
{
// Create TopologyManager
topologyManager = new TopologyManager();
site = topologyManager.PortalSites[new Uri("http://myspsserver/")];
context = PortalApplication.GetContext(site);
userProfileManager = new UserProfileManager(context);
// Iterate through users
long userCount = userProfileManager.Count;
IEnumerator profileEnumerator = userProfileManager.GetEnumerator();
while(profileEnumerator.Next())
{
// Set user profile
UserProfile userProfile = profileEnumerator.Current as UserProfile;
// Check for personal site
if(userProfile.PersonalSite != null)
{
// Create Personal Library
CreatePersonalDocumentLibrary(userProfile);
// Reset QuickLaunch and other properties
ResetProperties(userProfile);
} // if - userProfile
} // while - profileEnumerator
} // method - Main
Well, this code looks relatively simple. First, we create the Topology, and from there we eventually get to the UserProfileManager. From the UserProfileManager, we can get all the users for our particular Portal that we are interested in.
I then grab the IEnumeratorfrom the UserProfileManager so that I can iterate over the users. Once I am in the while loop, I need to check whether the Personal Site exists, because there is no need to fix a site that doesn't exist.
Now, let's get back to the issue at hand. We'll go to the place that gave me much heartache when dealing with the ever popular "Save Conflict". Apparently, the SharePoint API does not take too kindly to having the Default View deleted and recreated. This is unfortunate, because from my experience, you cannot modify the default view and you must delete and recreate it instead.
private static void CreatePersonalDocumentLibrary(UserProfile userProfile)
{
private string listName = "MyLibrary";
private string listDescription = "My Library Description";
// Set personal site
using(SPSite personalSite = userProfile.PersonalSite)
{
// Allow unsafe updates
personalSite.AllowUnsafeUpdates = true;
// Set rootweb
using(SPWeb rootWeb = personalSite.RootWeb)
{
// Allow unsafe updates
rootWeb.AllowUnsafeUpdates = true;
// Create document library
rootWeb.Lists.Add(listName, listDescription, SPListTemplateType.DocumentLibrary);
rootWeb.Update();
// Add document library to Quick Launch and enable versioning
SPList localList = rootWeb.Lists[listName];
localList.OnQuickLaunch = true;
localList.EnableVersioning = true;
localList.Update();
// Add document library to Quick Launch and enable versioning
SPList createdList = rootWeb.Lists[listName];
// Add custom fields
createdList.Fields.Add("MyDocID", SPFieldType.Text, true);
createdList.Fields.Add("MyDocDescription", SPFieldType.Note, false);
// Create new view columns
StringCollection viewFieldCollection = new StringCollection();
// Add field to collection
viewFieldCollection.Add("DocIcon");
viewFieldCollection.Add("LinkFilename");
viewFieldCollection.Add("MyDocID");
viewFieldCollection.Add("MyDocDescription");
viewFieldCollection.Add("Last_x0020_Modified");
viewFieldCollection.Add("Modified_x0020_By");
viewFieldCollection.Add("LinkCheckedOutTitle");
// Create default view query
string defaultQuery = "<OrderBy><FieldRef Name=\"FileLeafRef\" /></OrderBy>";
// Get default view information and delete
Guid oldViewId = createdList.DefaultView.ID;
createdList.Views.Delete(oldViewId);
// Add view as default
createdList.Views.Add("All Items", viewFieldCollection, defaultQuery, 1000, true, true);
createdList.DefaultView.Update();
try
{
// Try calling update
createdList.Update();
} // try
catch(SPException sp) {} // Do Nothing
// Close and dispose personalSite
rootWeb.Close();
} // using - rootWeb
personalSite.Close();
} // using - personalSite
} // method - CreatePersonalDocumentLibrary
Around the try block is where you will always have problems. I haven't been able to find a way around it when doing proof of concept work as of yet. If anyone has, please let me know. The other method called ResetProperties is a small subset of this method which just resets the OnQuickLaunch and EnableVersioning properties to true on the SPList.
This by no means was something I'd put into production, but instead more of dumbed down code for this example. There would be a good amount more code to do checks all over the place to make sure things exist and won't throw other types of exceptions.