This is the fourth article in a series which explores the SharePoint 2010 MySite features. This article will examine the ways that you can customise the default page for the MySite. It will describe the common requirement and how to approach them in a supportable and scalable fashion. The walkthrough will provide an example implementation which you can tailor to your exact needs.
Series contents:
- Overview, which details the MySite functionality provided by SP2010
- Anatomy, we delve inside the MySite and dissect its inner secrets
- Customisation for Branding, how to change the look and feel
- Customisation of My Content page, how to change the page layout and contents – This Article
- Customisation of a MySite Blog, how to alter the Blog
- The MySite centric intranet, putting the MySite at the centre of the universe
The challenge
With the up take of Social media and the focus many organisations are now putting on the MySite capability of SharePoint it is becoming more common for people to want customisations to the default page. Now before we get all excited and break out Visual Studio lets cover some basics. You’re not supported to modify the MySite Personal site definition which provisions the default aspx page. This could have you scratching you chin and turning to ‘Bing’ for answers. You also need to consider things like scale, first time site creation and on going performance and upgradability for future enhancements.
There are a couple of articles out on the web SharePoint Team and CKS MySiteCreate 1.0 Production. These solutions have an interesting approach of stapling modification features and using a control which performs the required page changes during load for the first render. After reading and walking through this approach I can see several things that are not optimal. First it forces you to change the masterpage in order to provision the one containing the actioning control. Second the actioning control itself, to be blunt this ‘smells’ to me.
Using a UI element to perform one time customisation doesn’t feel that smart. Although it only executes on the first page load per user the overhead for the user waiting for the required logic can lead to increased page load after the MySite is created. After testing, this process was found to often fail to execute in time and the user had a strange experience where the page sometimes looked empty until a refresh.
Following evaluation it became apparent that to perform customisations on large scale and have them consistently performant another approach was needed.
The new approach
After some tinkering over a particularly wet weekend I had a eureka moment. The stapling approach was right, but what about setting up the page? Well thinking a little laterally it becomes obvious. The MySite personal is like any other site, go to the root and it picks up the default page url and loads it. Anyone familiar with Publishing features knows that these sites allow you to set the ‘welcome page’ of any site. This means that if you browse http://sp/ for example it works out to render http://sp/pages/default.aspx instead.
After a quick test using SPManager to set the welcome url to a different page my suspicions were confirmed. You can indeed change the default page and therefore point it to another page other than default.aspx. Armed with this knowledge lets look at how we can create a feature set to provision and apply the MySite customisation.
So the basic elements for customising the default page are the following:
- Feature to activate and add the relevant web parts. (covered in article six)
- Feature to provision the new aspx page.
- Feature to change the set the welcome page.
- Feature to staple the above to the MySite Personal template.
The basic solution structure
Lets create a new Farm solution and add the basic structure to it.
The CustomPage feature is responsible for provisioning the custom page to the site. The WelcomePage feature sets the welcome page to the custom page. The Stapler feature associates these features with the MySite Personal site definition. There is a module to provision the custom page, and finally the stapling elements to ensure these features gets activated against the MySite on creation.
The CustomPage feature
The CustomPage feature provisions the customised aspx page and includes the web part provisioning as required. If you’ve got complex requirements you may wish to create more features to activate the required web part features as dependencies.
So lets look at the elements:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="CustomPage" Path="CustomPage">
<File Url="CustomPage.aspx">
</File>
</Module>
</Elements>
As you can see this simple elements provisions the custompage.aspx. If we were adding web parts to this custom page we’d add this to the all user web parts elements. For this article we’re not going to deal with this customisation. Although at this point it’s definitely worth mentioning the complexity if you want to keep the Shared and Personal documents views. As you’ll be aware these are provisioned from the Onet file and therefore it’s likely the list instances won’t exist when your stapled custom page feature fires. You’ll need to decide the best approach to provisioning list views from these ONET lists if you need them. As you’ll see in article six of this series we’re going to implement something quite different to the OOB so I’m not going to cover this now.
Another thing this feature is responsible for is activating the WelcomePage feature to set the page as the site welcome page. The reason we make this custompage feature responsible for it’s activation is that the welcome page property will throw an exception is the url is not resolvable.
[Guid("c61637c6-760f-4449-b997-08467930597f")]
public class CustomPageEventReceiver : SPFeatureReceiver
{
#region Methods/// <summary>
/// Occurs after a Feature is activated.
/// </summary>
/// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"/> object that represents the properties of the event.</param>
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
base.FeatureActivated(properties);SPWeb web = properties.Feature.Parent as SPWeb;
if (web != null)
{// Get the depended-upon Feature definition.
SPFeatureDefinition featureDefinition = null;
try
{
featureDefinition = SPFarm.Local.FeatureDefinitions[new Guid("9e852c4f-93c4-401e-a947-968fa85fb985")];
}
catch (Exception ex)
{
//Log here if you wanted
throw;
}web.Features.Add(featureDefinition.Id);
}
}#endregion
}
The WelcomePage feature
The WelcomePage feature sets the web root folder welcome page. This is done via the feature receiver which contains the following code:
[Guid("8616b35f-efa6-4c69-9c2f-809e50fb99ef")]
public class WelcomePageEventReceiver : SPFeatureReceiver
{
#region Constants//The mycontent.apsx
private const string CUSTOMPAGE = "custompage.aspx";//The default.aspx
private const string DEFAULTPAGE = "default.aspx";#endregion
#region Methods
/// <summary>
/// Occurs after a Feature is activated.
/// </summary>
/// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"/> object that represents the properties of the event.</param>
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
try
{
SPWeb web = properties.Feature.Parent as SPWeb;if (web != null)
{
SetDefaultPage(web, CUSTOMPAGE);
}
}
catch (Exception ex)
{
//Do the logging here
throw;
}
}/// <summary>
/// Occurs when a Feature is deactivated.
/// </summary>
/// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"/> object that represents the properties of the event.</param>
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
try
{
SPWeb web = properties.Feature.Parent as SPWeb;if (web != null)
{
SetDefaultPage(web, DEFAULTPAGE);
}
}
catch (Exception ex)
{
//Do the logging here
throw;
}
}/// <summary>
/// Sets the default page.
/// </summary>
/// <param name="web">The web.</param>
/// <param name="page">The page.</param>
protected virtual void SetDefaultPage(SPWeb web, string page)
{
#region Guardif (web == null)
{
throw new ArgumentException("Web was null");
}#endregion
SPFolder rootFolder = web.RootFolder;
rootFolder.WelcomePage = page;
rootFolder.Update();web.Update();
}#endregion
}
This gives you an example of how to change the default page for the MySite personal. The code would need some embellishment to be production ready but gives you a good starting point.
The Stapling feature
The Stapling feature staples the CustomPage feature to the MySite Personal site definition to ensure that when new sites are created the custompage.aspx is provisioned and set page to the default page.
The elements looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<!– CustomPage –>
<FeatureSiteTemplateAssociation Id="9dd6c130-4752-4ec7-910b-9b6be3cafb53" TemplateName="SPSPERS#0"/>
</Elements>
And that’s all there really is too it.
Before and after
Before the features are deployed the MySite created looks like the following:
It’s hosted under the standard url, which for example looks like ‘http://my/sites/administrator/default.aspx’.
After the Stapling feature is activated on the MySite web application the new MySites will change to our custom page. For the purposes of the example I’ve just dropped in a new paragraph of text. In reality you might make fundamental structural changes.
The major advantage is the light touch this approach makes. I’m a great believer that whenever customisations are made to SharePoint they should always leave you in a supportable and cleanable state. This approach leaves the OOB default.aspx alone and thus should you ever need to revert back to OOB you have that capability.
What’s next?
This article has laid some foundations to much deeper levels of customisation. It opens up structural as well as content changes as possible customisations. In the next article we’ll examine in more detail how to customise the blog feature for MySite to embellish the default blog site and how it gets created.
Great tutorial !
I have just one question : why do we need to have two Features to change the default page, why don’t we make the changes in CustomPage feature instead of making them in WelcomePage feature and then activate this feature in CustomPage feature ?
Hi,
You are correct you could combine them if you wanted with little impact. This information was taken from my live Production project and that has a few ‘extras’ going on over and above this which meant the seperate features were more appropriate.
Cheers,
Wes
Thank’s for the answer.
And keep up the good work.
How can I add the change to made in part 3 with the changes here?
I tried coping the delegate and theme and there events but I get an error :
Error occurred in deployment step ‘Activate Features’: Object reference not set to an instance of an object.
It is not hitting the catch areas in the code.
Any Idea?
Hi Ofer,
Hard for me to make comment without seeing your code. Sounds like an error during F5 deployment? I would suggest changing the active deployment to ‘no activation’ deploying the project and then attaching to the worker processes. This should allow you to step through the feature activation code once you activate the feature.
If you can let me know which line is throwing the error I’ll try and help 😀
Cheers,
Wes
Thanks for the help! I did as you advised.
The error is coming from the line: web.Features.Add(featureDefinition.Id); in WelcomePage.EventReceiver.cs (outside the try catch block)
I try replacing the GUID in featureDefinition = SPFarm.Local.FeatureDefinitions[new Guid(“9e852c4f-93c4-401e-a947-968fa85fb985”)];
To the one of the welcome page, did not help. So what is this Guid supposed to be? Which feature definition are we adding to the web?
Over all I had to make some assumptions because you did not say (Or I did not figured out :-))
1. I used the Guids from vs2010 in the event receivers (otherwise the packging complained)
2. Changed the scope of the stapling to site because the deployment complained:” Elements of type ‘FeatureSiteTemplateAssociation’ are not supported at the ‘Web’ scope”
3. I assumed the “Sample.txt” in the “CustomPage” module had to be replaced by the customized “CustomPage.aspx” page.
4. All other Guids I used what was in the article. Should I replace with something else?
I would also like to add the custom theme functionality, so I need to figure out how to add it to the gallery of the new site before assigning it. Or maybe it is better to set it to inherit the parent’s theme (in my case it is the same) but the “My content” is a site collection, is its parent really the “My site” host?
Any chance of downloading a working project from somewhere?
Thank you in advance 🙂
Great Article. Can you please provide little more insights for the organization structure page(OrganizationView.aspx) why the picture/thumbnail is not displaying from the client machine? However I am able to retrive and view all pictures, thumbnails on the local sharepoint server.
Everything is displayed correctly except photos. Please help
Can only suggest that you use something like fiddler to watch the request traffic to ensure the image urls are being resolved from the desktop. Failing that this is an out of the box page and control so I would suggest contacting MS Support if you are having issues getting it to work. The control is a silverlight control so I’m not really sure how it works internally.
Thanks Wes Hackett for the response. I verified all network path, alternate mapping and even did reset network adaptor to ensure that. I could retrive the picture for all members in the my site. Only when I click Organization browser, the image does not display from client machine. Even rest all properties are displaying correctly.
Any thoughts?
Thanks
Shridhar
I can only suggest either calling Microsoft support or entering a question into the MSDN / SharePoint overflow sites and seeing if anyone has encountered this issue before. As it’s an out of the box control I can’t really diagnose.
Hi,
I have followed the step that mentioned above but has confution in below code.
try
{
featureDefinition = SPFarm.Local.FeatureDefinitions[new Guid(“9e852c4f-93c4-401e-a947-968fa85fb985”)];
}
Please clarify What is this feature ID and use of the same.
Thanks in advance,
K Senthilrajan
Hi,
That’s the feature ID of the ‘Welcome Page’ feature. Obviously it will change for your specific version.
From the article text :
“Another thing this feature is responsible for is activating the WelcomePage feature to set the page as the site welcome page. The reason we make this custompage feature responsible for it’s activation is that the welcome page property will throw an exception is the url is not resolvable.”
Cheers,
Wes
Hi Wes,
can you please able how we can test creation of my site as its taking the time a lot.
http://social.msdn.microsoft.com/Forums/en-US/sharepoint2010general/thread/af2749bd-341d-40bf-88ed-1d050ed6a508/
please check the above question, give some guidance..
Need testing approach,
Regards
Guru
Very nice article – has helped me loads. I was just wandering if you could please give some more details on the “assumed” steps you took to get everything working. I am very new to the whole SP development thing and I’m not entirely sure how to go about getting everything to work. Where do I get the GUID and also you mention that “complexity if you want to keep the Shared and Personal documents view” exists – could you collaborate on this? You also mention “As you’ll see in article six of this series we’re going to implement something quite different to the OOB so I’m not going to cover this now.” but my article six a a series of diagrams that’s all.
Thanks
The guid is the feature id so your implementation will have its own one. The documents web parts are tricky because the are list views which are unique to the site instance.
The final article isn’t supposed to detail the code implementation, more the conceptual reason behind all of this research.
Hi,
Your post is very helpful.
But I would like to ask, why I follow your guide in feature stapling but when I tried to deploy the project, there is an error
“could not find a part of the path” in the Custom Page, indicating that custompage.aspx cant be found.
thank u very much for the help.
Hi Wes
Very nice article .I have a quick question i used the feature stapling to apply branding to our users personal site which is working absolutely fine but when they are creating a blog under their site it is not getting the branding .When i checked it i observed that when i am enabling publishing in site features it is taking the master page .So i added that feature also in my stapling but then it is creating an empty page which is going to default pages folder(I think this is something coming when i am enabling publishing ) .Can you suggest me how can i achieve this
Thanks