Please upgrade your web browser now. Internet Explorer 6 is no longer supported.
Thinking Web Solutions?
We create smart, fun, functional websites that make your web a better place.

Monthly Archives: October 2007

How to Customize the User Information Page (3/3)

UPDATED: Changed the Edit Button to override the default SP edit button to fix edit link bug. The sample solution has been updated to reflect the changes.

Continuing on from the User Information page customization series:

Part 1 talked about some of the difficulties presented with application pages in general.

Part 2 demonstrated how to redirect the user to a custom User Profile page using feature deployment.

This part will show how you can simply customize the look and feel of the User Profile page. Before reading this part you should read Part 2 and have a look at the sample code.

I am going to focus on the more significant changes - all the HTML/CSS changes including the custom master page have been left out (The code used is included in the sample solution though).

In order to reuse as much of what SharePoint provides as possible - I will base my customized User Profile page on the SharePoint userdisp.aspx page.

The first thing to do is to turn the userprofile.aspx page created in Part 2 into code behind page that extends the UserDisplayEditPageBase. To do this, create a class like so:
public class UserProfilePage : UserDisplayEditPageBase

To resolve the UserDisplayEditPageBase class you need a reference to Microsoft.SharePoint.ApplicationPages.dll which is not in the GAC. You will need to Browse to the location "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\CONFIG\BIN" to find this dll.

I have included the dll in the sample source code for simplicity.

Now I will update my custom profile page to inherit from this class:
<%@ Page Language="C#" Inherits="CustomUserProfile.UserProfilePage, CustomUserProfile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1ba1bfabc83c4398" MasterPageFile="/_layouts/application.master" %>

Note that that I have used the fully qualified name and this assumes that the dll will be signed and placed in the GAC. See the sample solution for how this can be easily done.

Now put the contents of the original userdisp.aspx (from the 12 Hive) into the userprofile.aspx page. The first modification to make is to remove the delegate control in the custom page or so you don't get stuck in an infinite redirect loop.

At this point I could just apply a custom master page and be done. This would let me easily apply a new look and feel, but I'd like to make a few modifcations to the layout as well.

You will probably have already noticed that the guts of the page are contained in a FormComponent control. This control provides a set of properties and methods that make it easy to display a form based on a SharePoint list item. It's rendering is controlled by the TemplateName property which is currently set to 'UserListForm'. We can find the contents of this form by looking in c:\program files\common files\microsoft shared\web server extensions\12\template\controltemplates\DefaultTemplates.ascx. I don't want to modify this file directly (it will affect all SharePoint sites) so I will take a copy of the SharePoint:RenderingTemplate and put it in a new ascx file named CustomTemplates.ascx (this will live in the controltemplates dir). I then give it a custom name so that it only overrides it for the profile display page. Now I should have a FormComponent in my profile page like:
<SharePoint: FormComponent id="UserListForm" TemplateName="CustomUserListForm" ControlMode="Display" runat="server"/>

and in CustomTemplates.ascx file I have:
<SharePoint: RenderingTemplate ID="CustomUserListForm" runat="server">
<Template>
<span id="part1">
.....

Note that the TemplateName of the FormComponent matches up with the ID off the RenderingTemplate.

From here it is easy enough to edit some of the basic HTML elements of the form.

Next up is to customize the Toolbar. To do this copy the RenderingTemplate with the ID of "UserInfoListDisplayFormToolBar" from DefaultTemplates.ascx to the CustomTemplates.ascx file. I want to remove some of the buttons and have a custom Edit Item button so I can link to a custom user profile edit page. To do this change the control declaration from:
<SharePoint :UserInfoListFormToolBar runat="server"/>

to
<SharePoint :FormComponent id="UserToolBar" TemplateName="CustomUserInfoListDisplayFormToolBar" runat="server"/>

And then customize the RenderingTemplate like so:

<SharePoint :RenderingTemplate ID="CustomUserInfoListDisplayFormToolBar" runat="server">
<Template >
<script>
recycleBinEnabled = <SharePoint:ProjectProperty Property="RecycleBinEnabled" runat="server"/>;
</script>

<wssuc :ToolBar CssClass="ms-toolbar" id="toolBarTbl" runat="server" FocusOnToolbar="true">
<Template_Buttons >
<prof:UserProfileEditButton ID="UserProfileEditButton1 " runat="server " /> <SharePoint :UserInfoListDeleteItemButton ID="UserInfoListDeleteItemButton1" runat="server"/>
</Template_Buttons >
</wssuc: ToolBar>
</Template >
</
SharePoint: RenderingTemplate>

Note that I have removed a few of the buttons for alerts and regional settings as well as create a custom button for linking to the useredit.aspx.

The custom edit button simply overrides the standard SharePoint edit button and updates the URL:

 

public class UserProfileEditButton: UserInfoListEditItemButton
{
protected override void OnLoad(EventArgs
e)
{
base
.OnLoad(e);
base.NavigateUrl = base.NavigateUrl.Replace("useredit", "usermodify"
);
}
}

Next I want to tidy up up the user display name as it includes the domain and won't have any meaning for most users.

To do this I override the OnPreRender method in the UserProfilePage class created earlier:
protected override void OnPreRender(EventArgs e)
{
base.LabelTitle.Text = base.UserListForm.ListItem.GetFormattedValue("Title"
);
}

This will give us a nicer looking display name:

userinfo

In this case I don't want to display the SIP Address, so the next task is to remove this from the profile page. Currently all of the fields are rendered using a FieldIterator which is declared on the page as:
<SharePoint:ListFieldIterator runat="server"/>

In order to customize how the user list fields are displayed - we need to create a class that overrides the ListFieldIterator. My class is declared like this:

public class UserProfileFieldIterator : ListFieldIterator

Becuase I want to exclude the SIP Address I am then going to add override the IsFieldExcluded method like so:
protectedoverride boolIsFieldExcluded( SPField field)
{
if (field.Title == "SIP Address")
return true;

 

return base.IsFieldExcluded(field);
}

To replace the existing field Iterator currently being used I need to first register the assembly:
<%@ Register TagPrefix="prof" Namespace="CustomUserProfile" Assembly="CustomUserProfile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1ba1bfabc83c4398" %>

and then replace the field iterator declaration with the custom one just made:
<prof:UserProfileFieldIterator ID="UserIterator" runat="server" />

The last thing I'm going to do is attach the custom master page. This is simply a case of changing userprofile.aspx to point to a new master page:

 

<%@ Page Language="C#" Inherits="CustomUserProfile.UserProfilePage, CustomUserProfile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1ba1bfabc83c4398" MasterPageFile="/_layouts/customprofile.master" %>

The custom master page also requires a couple of css files to override and add styles to the SharePoint page.

And now after all our hard work - "The final product":

customprofilepage

You can download the sample code (including solution deployment) -> here.

Although I have only customized the SharePoint user info page you can do the same for the edit page - or any application page really.

I am considering doing a Part 4 with some advanced customizations such as having a custom action when closing the page (eg redirect) and modifying some of the form fields. Let me know if this is something that you are interested in.

For more information on Form Components, Rendering Templates and List Iterators have a look at the following resource:

http://msdn2.microsoft.com/en-us/library/aa544154.aspx

Wellington SharePoint User Group Meeting - October 25th

This month's user group meeting will be held on 25th Thursday at Microsoft New Zealand. This month is also the 1 year anniversary of the User Group. Seems like only yesterday that it was kicking off.

Tomorrow nights meeting is broked up into two parts:

"SharePoint Search - I didn't know MOSS Search did that" presented by Brendan Law.

and

Ask the Experts session with Myself, Chan Kulathilake and Jonathan Stuckey.

Hope to see you there!

Exam 70-631 - We all passed!!

Today 5 of us from the SharePoint team at Provoke went and sat the "Configuring Windows SharePoint Services 3.0" Exam ....

Great news -> we all passed!!

Congrats to Chan, Mark, Carlos and Flick.

I think the SharePoint server configuration exam will be next.

How to Customize the User Information Page (2/3)

Liam Cleary recently wrote a blog post on how to "Hide the My Settings link" which is part of the welcome menu. Although his solution is perfectly valid and probably quicker and easier than the alternative solution that I offer - It did have some issues.
Firstly he edited the welcome.ascx user control. Like editing an application page this will affect all sites for that instance of SharePoint.
Secondly this only covers the scenario where the user actually clicks on the "My Settings" link. There are many other access points to the User Information page. For example any list edit/display form will have a link to the page. Thats any instance where you see the following audit info:
auditinfo

So creating a custom "My Settings" link only covers half the problem.

The question then is - how to create a solution that doesn't involve editing shared resources and covers every possible link scenario??
The answer lies in the userdisp.aspx page. In the AdditionalPageHead placehoder tag you will find the following control declaration:
<SharePoint: DelegateControl runat="server" id="DelctlProfileRedirection" ControlId="ProfileRedirection" Scope="Farm" />

What we need to do is create a user control, that redirects the user to a custom page. The user control will the be activated via a feature.

Brief Steps:

  1. Create a custom user display page and place it in the LAYOUTS directory.
  2. Create a new User Control that has code to redirect the user to your custom page.
  3. Create a feature for the delegate control. This feature will cause your custom control to run in place of the SharePoint:DelegateControl declaration. The feature should be scoped to "farm".

I have kept the steps very brief as I have a sample solution with all the necassary code in it.
Download the sample code from here:
http://zac.provoke.co.nz/Samples/CustomUserProfile.zip

To run the sample, copy CustomUserProfile.wsp file and Deploy.cmd to your WSS server and run the following command from a prompt:
deploy.cmd http://yoursitenamehere

Once the feature is activated, navigating to My Settings page will redirect the user to userprofile.aspx.
redirectedprofile

Not a very useful custom profile page, but thats what part 3 is for :)

The only problem now is that the feature's scope is set to farm, so the user control will be run for all sites. To solve this you can create a second feature, and then before redirecting check for the features existance. This is also included in the sample solution.

Part 3 will show how to easily customise the actual User Profile page.

For more info on delegate controls have a look at the following resources:
http://msdn2.microsoft.com/en-us/library/ms470880.aspx
http://sharepointnutsandbolts.blogspot.com/2007/06/using-delegate-control.html

How to Customize the User Information Page (1/3)

This 3 part post series discusses how you would go about customizing the user profile page accessed from the "My Settings" link in the welcome menu.

That's this page here:

userprofile

Although it seems like a simple task, there is actually quite a lot to consider. I am also planning to demonstrate a number of useful SharePoint techniques along the way.

The first part is about application pages in general and why they cause headaches for designers trying to customize the look and feel of SharePoint.

Application Pages

One of the first things people want to do after installing SharePoint - is to make it look like anything but SharePoint.

If you have ever been involved in skinning a SharePoint/WSS site you will know the difficulties posed by application pages. These are the pages in the "_layouts" directory that are shared across all SharePoint sites. It is always recommended to NOT edit these files as all web applications will be affected by the changes.

This is not a problem for most application pages as they are generally only accessed by site administrators. There are however a few application pages that are viewable by all users. It can be very frustrating to find that after you have gone to all the trouble of skinning a SharePoint site only to find that a few pages still render that standard SharePoint blue.

Two commonly problematic pages are:

UserDisp.aspx

This is the user profile page shown in the above screenshot, it links to a number of other application pages such as UserEdit.aspx. The page is accessible by any authenticated user. It is also the focus of this post series.

SearchResults.aspx

The standard WSS search page. In MOSS there is also the osssearchresults.aspx page for the standard "This List" and "This Site" search scopes.

There are a few techniques that can be used to customize these pages. The easiest way would be to simply manipulate the pages in the LAYOUTS directory. Obviously any changes made are going to affect all your SharePoint sites.

It also presents a problem during deployment, how are these changes going to be packaged up to make releases easy? What if there are multiple front end servers? And what happens when a service pack comes out that has new versions of these pages? Its probable that your changes will be overwritten.

Luckily the creators of SharePoint had foreseen these issues and in most cases have provided a way to customize these pages safely. More about this in Part 2.

Part 2 will demonstrate how we can manipulate the My Settings Link

CKS Forms Based Authentication Pre-Beta Release!!!

After a few months of hard work we are finally making our first release.

If you want to download the solution and take it for a spin, go to the release page on codeplex:

http://www.codeplex.com/CKS/Release/ProjectReleases.aspx?ReleaseId=7675

The release page also covers off all the main features, with some basic instructions and descriptions, as well as some screenshots.

Here is a screenshot of one of the features I worked on:

ManageUsers

This release is mainly just the basics. However we have a bunch of exciting features and additions in the pipeline such as:

FBA configuration pages
A set of central admin pages that ease the configuration of FBA. This will mean people won't be having to dig around in web.configs anymore.

FBA User Import
This feature will allow a set of existing FBA users to be imported into SharePoint.

Rich Client capabilities
Normally the rich client interaction with programs such as MS word don't work, this feature will solve that problem.

Custom Master page designs
As part of the Internet/Extranet edition we will be providing a couple of snazzy master page designs.

MOSS functionality light up
We aren't too sure what this is going to consist of yet, but possibly something to do with MySites.

Any requests??

Setting Forms Based Authentication Session Timeout

When using FBA, session timeout is determined in the web.config. This is a standard feature of asp.net.

Example:
<forms loginUrl="/_layouts/login.aspx" timeout="30" />
(timeout is in minutes).


Setting the timeout in Central Admin will have no effect on Forms authenticated sites.

Synchronize User Profiles back to Active Directory

MOSS provides a great mechanism to easily import user profiles from AD. However there is no out-of-the-box functionality to get that information back to AD. This is often an issue if other applications use Active Directory to read account information.

Over the past few months I have looked at ways to provide a 2-way synchronization of this profile info. Here are two possibilities:

1/ Use the Shared Services User Profile Importer/Exporter. This allows user profiles to be exported into an XML file. From the XML file it is fairly simple to write some code that updates AD. Then it just needs to be scheduled to run on a regular basis. A custom SPTimerJob would seem like the right mechanism for the job. This does still require a lot of custom coding. One good thing is that the code for the profile exported is all available so you could just use what you need and avoid having to export as an xml file at all.

2/ Use the bamboo solutions webpart. While its not actually a webpart it does perform the job without having to write any custom code. Basically its a winform application that lets you create a template of mappings from SharePoint to AD. The template can then be used on a schedule to do regular AD updates. pretty slick, however it does come at a cost.

The "webpart" has just been released and is available at https://store.bamboosolutions.com/ps-45-5-user-profile-sync-web-part.aspx.