Tag Archives: development

Administrators! Stop before deploying that custom code!

Even with no development knowledge, there’s a simple and quick tool that SharePoint administrators can run before deploying a solution package or web part to get some idea on whether it could cause instability your farm! It’s SPDisposeCheck and is particularly useful to keep an eye on the work done by a third party or even internally, with no developer knowledge whatsoever.

The tool was released by Microsoft in early 2009 to help developers check for memory leaks in their code. However there’s no reason why an administrator can’t do the same. Memory leaks can cause performance problems and general instability in your SharePoint farm. This tool tells you of any potential problems, and here’s how to use it:

  1. Download SPDisposeCheck and install. By default this will copy SPDisposeCheck.exe to C:\Program Files\Microsoft\SharePoint Dispose Check.
  2. Examine the deployment file you have been given. If this is a WSP file, rename its extension to CAB and extract all DLL files. SPDisposeCheck also works on EXE files if you’ve been asked to run a console application.
  3. For each DLL or EXE, run SPDisposeCheck using the filename as a parameter. To be assured of no SharePoint memory leaks, check that the “Total Found” line is 0.

Here’s an example that shows a potential leak:

SPDisposeCheckOutput

If the tool finds some issues then you should query this with the developers. However as the tool itself states, this doesn’t necessarily mean there is a leak! Unfortunately it can report false positives depending on how the code has been written. Regardless, make sure you have an assurance that the tool is run as part of their release process and any flagged issues have been checked. The tool will never miss a problem with a false negative.

It’s as simple as that. Be sure to add SPDisposeCheck to your admin toolkit and don’t let those developers get away with dodgy code!

Showing the bulleted links list view

A user recently took quite a shine to this lovely bulleted view of links in the list view web part:

Bulleted link list view

They wanted all of their existing links list to be changed over to use this view. What makes this case more unusual is that this is actually the view displayed as “<Summary view>” in the web UI:

Links toolpart

After much fighting with the SPViewCollection on the list, I discovered this post on Ketul Patel’s blog. He showed that to get a reference to this ‘hidden’ view, it is necessary to use the mouthy method SPList.GetUncustomizedViewFromBaseViewId(). The list view web part can then be changed to use the markup for the summary view. (Note that the web part needs to be re-added to the page so that the changes take effect correctly.) Here is a method that does this all this:

public static ListViewWebPart ReplaceWithBaseView(
	ListViewWebPart listViewWebPart, SPList list,
	int baseViewId, SPLimitedWebPartManager limitedWebPartManager)
{
	string zoneID = listViewWebPart.ZoneID;
	int zoneIndex = listViewWebPart.ZoneIndex;

	SPView view = list.GetUncustomizedViewByBaseViewId(baseViewId);

	ListViewWebPart replacementWebPart = new ListViewWebPart
	{
		Title = listViewWebPart.Title,
		ListName = listViewWebPart.ListName,
		Hidden = false,
		FilterString = listViewWebPart.FilterString,
		SuppressWebPartChrome = listViewWebPart.SuppressWebPartChrome,
		ViewContentTypeId = listViewWebPart.ViewContentTypeId,
		ListViewXml = view.HtmlSchemaXml,
		ExportMode = listViewWebPart.ExportMode
	};

	limitedWebPartManager.DeleteWebPart(listViewWebPart);
	limitedWebPartManager.AddWebPart(replacementWebPart, zoneID, zoneIndex);

	return replacementWebPart;
}

In order to call the above method, it’s simply a matter of getting a reference to the web part page and the web part. The magic number for “<Summary view>” is 0. Here is the calling code:

SPList usefulLinksList = web.Lists["Useful Links"];
using (SPLimitedWebPartManager webPartManager =
		web.GetLimitedWebPartManager("default.aspx", PersonalizationScope.Shared))
{
	try
	{
		foreach (WebPart webPart in webPartManager.WebParts)
		{
			if (webPart.Title == "Useful Links")
			{
				ListViewWebPart listViewWebPart = (ListViewWebPart)webPart;
				ReplaceWithBaseView(listViewWebPart, usefulLinksList, 0, webPartManager);
				break;
			}
		}
	}
	finally
	{
		webPartManager.Web.Dispose();
	}
}

Debugging file locking in the GAC

Do you ever find that your solution files have been “successfully deployed” according to SharePoint, yet the updated code isn’t taking effect? Perhaps you are trying to debug but breakpoints aren’t being hit when normally there’s no problem. Yet for some reason rebooting the server fixes the problem…

If that’s the case, the reason is probably file locking, most likely to occur if you have assemblies that need to be deployed to the Global Assembly Cache (GAC). If you ever find yourself in this situation, download a copy of the excellent Process Explorer tool, and follow these steps to verify:

  1. Start Process Explorer on the server affected.
  2. Press Ctrl+F, or in the menu click Find, Find Handle or DLL…, or just click the binoculars icon on the toolbar:Process Explorer toolbar
  3. Type the name of the assembly DLL and click Search.
  4. Under the Handle or DLL column, look for any assemblies located in the path C:\WINDOWS\assembly\temp. These lines tell you what process is locking the assembly.
OWSTIMER.EXE is the culprit

OWSTIMER.EXE is the culprit!

The C:\WINDOWS\assembly\temp folder is Windows’ equivalent of “assembly purgatory” where the assembly will sit until Windows can deploy it. If the currently deployed assembly cannot be overwritten as it is already locked by a process then the DLL will stay there until the process releases the lock or ends, or until Windows is restarted (also ending the process).

One example where this problem can occur is when a WSP solution containing custom e-mail event receivers is upgraded. The timer service, OWSTIMER.EXE, executes event receivers via the Windows SharePoint Services Incoming E-Mail job. As the OWSTIMER.EXE process isn’t restarted when a solution is deployed, it will always hold onto the lock for the DLL containing the event receivers. The solution is to restart the Windows SharePoint Services Timer service on each web front end server. If you’re finding this problem in development, WSPBuilder v1.06 adds a “Recycle the Windows SharePoint Services Timer” option.

This problem can also occur when using Visual Studio if certain combinations of add-ins are installed. You can again check this by using Process Explorer and verify if DEVENV.EXE is the locking process. If so, take a good look at the add-ins you actually need. Regularly restarting Visual Studio is very frustrating and will severely cut your productivity!

Programmatically retrieving the name of an SSP

This was asked on the new Stack Overflow programming questions site recently (which you should really check out and start using if you don’t already!). Getting the SSP name is something that I’ve needed to do to build the SSP URL for impersonating access to the Project Server PSI. I used to think that the URL had to live in a config file. Then after some digging into Project Server’s behaviour with the help of Reflector, I discovered Microsoft use the SharedResourceProvider class in the Microsoft.Office.Server.Administration namespace. Who knows why, but this class is marked internal so reflection is required to access it, and therefore accessing it is not supported. We should be on relatively safe ground if MS products such as Project Server use it however…

The following code retrieves the name of the SSP for the current site collection.
[sourcecode language='csharp']
SPSite site = SPContext.Current.Site;
ServerContext serverContext = ServerContext.GetContext(site);

PropertyInfo srpProp = serverContext.GetType().GetProperty(
“SharedResourceProvider”,
BindingFlags.NonPublic | BindingFlags.Instance);
object sharedResourceProvider = srpProp.GetValue(serverContext, null);
PropertyInfo srpName = sharedResourceProvider.GetType().GetProperty(
“Name”,
BindingFlags.Public | BindingFlags.Instance);

string sspName = (string)srpName.GetValue(sharedResourceProvider, null);
[/sourcecode]

From there the URL to the PSI web services within the SSP directly becomes the following (and the port number is always the following on every server):
http://servername:56737/SSPName/PSI/ or

https://servername:56738/SSPName/PSI/

This does seem overly complex so if someone out there has a better solution please add it as a comment to this blog or update the answer on Stack Overflow.

Internal name vs display name

Anyone that’s done a reasonable amount of work with the SharePoint object model will soon come across its flaws. The one that I regularly come up against is when working with the SPField object that represents list columns.

There are inconsistencies throughout the object model when attempting to retrieve an instance of an SPField, its value, or perform various other operations. In some cases the display name is required, or the internal name, or both! Even worse, rarely does the SDK document what is required to find your field. Unpredictable behaviour can also result in the cases where it checks for display name and internal name, because what if you have two fields with the same display name?!

Here’s just a few frustrating examples:

  • SPFieldCollection.ContainsField: Internal name or display name
  • SPFieldCollection.Item[string]: Display name
  • SPViewFieldCollection.Exists: Internal name

Tom, another SharePoint developer, has made a list with more examples here. He also details the inconsistencies around when an exception is thrown – yet another place to get caught out.

One of the most important things in an API is consistency so it behaves like you would expect. I’m sure how Microsoft can fix this without introducing breaking changes so maybe we will have to live with this for a long time yet. If in doubt, as always, Reflector is your friend.

Project Server ItemSwapper control

ItemSwapper hasn’t been documented by Microsoft so its behaviour may change between service packs – use at your own risk!

With the 2007 version, Project Server is now a SharePoint application. One of the best things about this is the nifty stuff you get out of the box as part of SP. Custom controls are a highlight, of which there are many that can be used in your custom Project Server solutions. Even better is that Project Server 2007 comes with some cool controls of its own which you can use in any solution running within Project Server. My latest discovery is the handy ItemSwapper.

ItemSwapper

ItemSwapper

This might look familiar to you from popular administration pages such as “Manage Queue” or “Manage Groups”. Just by popping one of these on your page, you get a pretty flawless interface to selecting projects. It’s also speedy and has some great features both client and server side. It’s great to use in a web part used for selecting report parameters, so that’s what we’re going to build in this post!

First of all, let’s have a look at two other custom controls used by ItemSwapper. There is the ItemSwapperLabel (extended from System.Web.UI.WebControls.Label) which renders the text above each list, and ItemSwapperSelect (extended from System.Web.UI.HtmlControls.HtmlSelect) which renders the list itself. Data binding is done with ItemSwapperSelect and the ‘parent’ ItemSwapper control renders all of these controls for you.

The ItemSwapper control refers to the two select lists as the ‘alpha’ and ‘beta’ lists (originally designed for Greek Project Server?). In our example the beta list will be blank for us to add projects into, so we only want to initalise the alpha list. Looking at the code, our CreateChildControls method contains:
[sourcecode language='csharp']protected override void CreateChildControls()
{
alphaSelect = new ItemSwapperSelect();
alphaSelect.Multiple = true;

projectSwapper = new ItemSwapper();
projectSwapper.ID = “projectSwapper”;
projectSwapper.TrackBetaListChanges = true;
projectSwapper.AlphaSelect = alphaSelect;
projectSwapper.LblAlphaList.Text = “Available Projects”;
projectSwapper.LblBetaList.Text = “Selected Projects”;
projectSwapper.DisplaySelectedItemText = false;
projectSwapper.ShowBetaUpDownButtons = true;
projectSwapper.ShowRestoreAllButton = true;
projectSwapper.ShowRemoveAllButton = true;
this.Controls.Add(projectSwapper);
}[/sourcecode]

This should be pretty self-explanatory (we will discuss the ID and TrackBetaListChanges properties later in this post). Now let’s perform a data bind in our OnLoad method:
[sourcecode language='csharp']protected override void OnLoad(EventArgs e)
{
if (!Page.IsPostBack)
{
DataTable projects = DataLayer.GetProjects();
projectSwapper.DataSource = projects;
projectSwapper.DataTextField = “Name”;
projectSwapper.DataValueField = “Uid”;
}
}[/sourcecode]

This will now render fine, but the finishing touch is a workaround to what I would call a bug. If you set ShowRestoreAllButton to true, this will display the “Add All” button. However it is important to know that this button is greyed out unless the user has selected an item first, meaning that will need two clicks to add all projects to the other list. I don’t know why Microsoft would have done this, but to get around it, add the following code to our OnPreRender method:
[sourcecode language='csharp']protected override void OnPreRender(EventArgs e)
{
alphaSelect.SelectedIndex = 0;
}[/sourcecode]
Have a look at the work so far as the ItemSwapper should now render!

Now let’s make use of the items chosen in the lists. First of all we’ll need a button in our web part for users to click on and start the report generation. We’ll also need at least one hidden field that will contain the selected items for us to use on the server side. Note that there is quite a bit of data we can get from the ItemSwapper JavaScript object, such as a count of items for both lists, text labels of chosen items for both lists, and values (e.g. project GUIDs) of chosen items for both lists!

To be able to do retrieve the data on the client side there are two key properties we need to set when creating the ItemSwapper which I touched upon earlier: ID and TrackBetaListChanges (or if you care about the alpha list, TrackAlphaListChanges). We need to use JavaScript to get a reference to the ItemSwapper object and setting ID lets us use document.getElementByID() to do this. (Surprisingly and fortunately, ID doesn’t get mangled in usual SharePoint fashion when rendered.) Setting TrackBetaListChanges sets a property on the JavaScript object to, well, track beta list changes.

So going back to CreateChildControls(), let’s add the following code and connect our server code to the client:
[sourcecode language='csharp']chosenProjectValues = new HiddenField();
this.Controls.Add(chosenProjectValues);

createButton = new Button();
createButton.Text = “Create”;
createButton.Click += CreateButton_Click; // server-side processing done in this method
createButton.OnClientClick = String.Format(“SaveItemSwapperValues(‘{0}’, ‘{1}’);”, projectSwapper.ID, chosenProjectValues.ClientID);
this.Controls.Add(createButton);[/sourcecode]

Everything’s ready now on the server side. We just need to create the SaveItemSwapperValues JavaScript function. Put this JavaScript wherever is standard for your projects.
[sourcecode language='jscript']function SaveItemSwapperValues(itemSwapperClientID, chosenValuesClientID)
{
var chosenValuesField = document.getElementById(chosenValuesClientID);
var itemSwapper = document.getElementById(itemSwapperClientID);
chosenValuesField.value = itemSwapper.GetBetaListValuesAsString();
}[/sourcecode]

That’s it! Now when your server-code hits CreateButton_Click(), you should find a nice comma-separated list of project GUIDs in the Value property of your hidden field that can be used to generate reports!

But it’s nice to take things a bit further… Our Create button is always active, even when no projects are in the chosen list. Well then, behold! The ItemSwapper contains JavaScript event handling functionality! Add script that runs on startup such as this:
[sourcecode language='jscript']var itemSwapper = document.getElementById(‘projectSwapper’); // ‘projectSwapper’ should be passed as a parameter and not hard-coded
itemSwapper.OnAlphaListChange = ChosenProjectsChanged;
itemSwapper.OnBetaListChange = ChosenProjectsChanged;[/sourcecode]

Then add the following with the SaveItemSwapperValues function:
[sourcecode language='jscript']function ChosenProjectsChanged()
{
var itemSwapper = document.getElementById(‘projectSwapper’);
var createButton = /* how you get this reference depends on your environment */
if (itemSwapper.betaListItemCount == 0)
{
createButton.disabled = true;
}
else
{
createButton.disabled = false;
}
}[/sourcecode]

Now we’re talkin’ – a smart ItemSwapper. And that’s not all, there is heaps of handy JavaScript goodness you can hook on to if you’re able to navigate to this file and have a look: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\PWA\LIBRARY\ItemSwapper.htc.

Last but not least, none of the ItemSwapper controls are sealed so you are free to extend them with your own functionality!