SharePoint Automation Gary Lapointe – Founding Partner, Aptillon, Inc.

27Nov/0730

Customizing MySites

This posting doesn't actually have anything to do with stsadm (unless you count the fact that you need stsadm to install Features) but I figured I'd post this here regardless as I've seen a lot of questions out there regarding how to do this. My specific requirement was to remove the "Create Blog" button on the My Sites home page. There are two ways to accomplish this - one that's supported and one that's not. The easiest approach (and the unsupported approach) is to modify the default.aspx file located at "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\SiteTemplates\SPSPERS". In this file simply remove or comment out the CreateBlogButton web control (ID="TBBCreateBlogButton"). Note that I don't recommend doing this as modifying these files will violate your support with Microsoft but I figure it's at least worth mentioning that it's possible.

The other approach is to use a Feature. There's a great article by Steve Peschka on customizing My Sites which explains how to do all of this. There's also a template project which you can find on CodePlex. I used this project as a starting place and tweaked it to meet my needs. There's three approaches you can take to remove the create blog button (I won't bother to address the other customizations you can do as they are documented on the above sites and in the readme files provided with the download).

The first is to modify the master page and make the PlaceHolderMiniConsole control no longer visible. The problem with this approach is that it also hides any other buttons that may be loaded into this control. The second approach is to put some code into the master page in a server script tag - that code would then do a series of FindControl calls to get the TBBCreateBlogButton control and then hide it. The problem with this is that it requires you to make some web.config changes to allow code blocks - something I'd strongly recommend against doing unless you had no other choice. The third option (which is the one I took) is to have the MySiteCreatePart control look for and remove the button (again, using FindControl). The one downside of this is that the code to hide the button has to run every time the page is loaded.

There may be other ways to do this but I was not able to identify one. Just a quick overview of what Steve's code is doing - there are three components: the first is the MySiteStaplee which contains the custom master page and the MySiteStaplee.xml file which has all the settings that the MySiteCreatePart code utilizies. The custom master page is exactly like the default master page with the addition of two lines - one registers the MySiteCreatePart web control and the other adds the web control to the page in the Head section (you can modify this further to your heart's content). The second part is the MySiteStapler which simply associates the MySiteStaplee feature with the SPSPERS#0 site template (so when a site is created with this site template the MySiteStaplee feature will be activated). The third piece is the web control (MySiteCreatePart) which gets loaded up by the master page.

This approach of using a web control allows the code to manipulate the running page without having to embed server side script blocks which would open up security issues (note that this is a simple object inheriting from WebControl - it is not a WebPart object - it really is about as basic as you can get so it's real easy to work with). And finally, there's a web.config change that is necessary to mark the web control as a safe control. In order to do what I needed I had to modify the code that Steve provided.

The first thing I did was to clean it up a bit - I broke the main method into a couple of smaller methods to help in readability and I modified the code so that it properly disposed of the objects such as the SPLimitedWebPartManager object and the various WebPart objects (minor issue but this should help with memory management). The next thing I added was a new attribute to the MySiteStaplee.xml file. I wanted to make it so that I could control whether the button appeared or not via the XML file so I added a "removeBlogButton" attribute to the document element. This way the value can be changed in the future so that any new MySites created would reflect the change (to address existing MySites one would simply need to loop through all the sites and set a custom property to true or false (assuming of course that the feature has been installed)). With this attribute in place I was then able to set a property on the SPWeb object which I then check whenever the page is loaded. The final code changes I made was to support an additional action and handle deactivation of the feature - Steve's version only allowed Delete, Move, Add, and SetProperties, but I needed to be able to do a Close as well so I added that logic in. I also wanted it so that if the MySiteStaplee feature was deactivated that the original master page would be reassociated so I added that code in. The other changes I made to the MySiteStaplee.xml file were to simply move a couple of web parts around.

Download the original version for additional examples (I also included the original version within my download). Feel free to download my version of the MySiteCreate Feature and let me know if you have any issues.

Update 1/15/2008: I've fixed the batch files and updated the FeatureActivating event so that it won't activate the feature at the root site and in case it does it will only switch the master page if the template is SPSPERS.

25Sep/074

My Site Settings

This command replaces the gl-setmysitesnamingformat command as it includes the same functionality along with additional capabilities.

I had originally created the gl-setmysitesnamingformat command to address a need to set the naming format of personal sites and I originally didn't think I'd have to worry about the other settings on the My Sites Settings page but turns out that I did need to set one other field. So rather than create another command for just one field I decided to create a command that would allow me to set any value on that particular page.

I was originally thinking I would exclude the naming format as I already had a command for that but then decided that I'd just include it so that this command became a one-stop-shop and the other could be deprecated (I'll leave it in but there's not much need for it now that this command exists).

Like the original command I had to use reflection to set the internal properties (I just don't understand why Microsoft chose not to make the UserProfileApplication object public). Beyond using the internal UserProfileApplication class the command also uses an internal method called CommitPersonalSiteSettings which is part of the UserProfileManager class (I had to use reflection to call this method but at least I'm not accessing the database directly).

I'm hoping that Microsoft will either make these methods and objects public or will create the ability to set these values via the existing properties. The core code is shown below (if using reflection scares you I'd suggest clicking away):

   1: /// <summary>
13Aug/075

Set My Sites Naming Format

Update 9/25/2007: This command has been deprecated in favor of the gl-mysitesettings command.

Update 9/18/2007: I've modified this command so that it no longer manipulates the database directly. The content below has been updated to reflect the changes. T

his is another one of those for which there is no public API to manipulate programmatically. The command uses an internal method called CommitPersonalSiteSettings which is part of the UserProfileManager class (I had to use reflection to call this method but at least I'm not accessing the database directly). The previous version of this command required passing in the database server and database name for the SSP - now that I'm not hitting the database directly all that's necessary is the SSP name (and the naming format of course). I'm hoping that Microsoft will either make this method public or will create the ability to set these values via the existing properties:

   1: public override int Run(string command, StringDictionary keyValues, out string output)
   2: {
   3:     output = string.Empty;
   4:  
   5:     InitParameters(keyValues);
   6:  
   7:     string sspname = Params["sspname"].Value;
   8:     string format = Params["format"].Value;
   9:  
  10:     SiteNameFormat nameFormat = (SiteNameFormat)Enum.Parse(typeof(SiteNameFormat), format, true);
  11:  
  12:     UserProfileManager upm = new UserProfileManager(ServerContext.GetContext(sspname));
  13:     
  14:     MethodInfo commitPersonalSiteSettings =
  15:         upm.GetType().GetMethod("CommitPersonalSiteSettings",
  16:                                 BindingFlags.NonPublic | BindingFlags.Public |
  17:                                 BindingFlags.Instance | BindingFlags.InvokeMethod);
  18:  
  19:     commitPersonalSiteSettings.Invoke(upm,
  20:                     new object[]
  21:                         {
  22:                             upm.PersonalSiteInclusion, nameFormat, upm.PersonalSiteReaders, upm.IsPersonalSiteMultipleLanguage
  23:                         });
  24:  
  25:     return 1;
  26: }

The syntax of the command I created to do this can be seen below.

1. gl-setsitenamingformat

C:\>stsadm -help gl-setsitenamingformat

stsadm -o gl-setsitenamingformat

Sets the site naming format for the My Sites web application.

Parameters:
        -sspname <SSP name>
        -format <Username_CollisionError|Username_CollisionDomain|Domain_Username>

Here’s an example of how to set the site naming format:

stsadm –o gl-setsitenamingformat –sspname SSP1 -format Username_CollisionDomain

Please note that because this command uses an internal only method directly it could, according to Microsoft, put your environment into an un-supported state (though this is Microsoft's recommended approach over directly manipulating the database). Please make sure you understand what the command is doing and what your support options with Microsoft are.