All posts by Mike Hacker

Sogeti to offer SharePoint event

Sogeti will offer a course on how to successfully deploy Microsoft Office SharePoint Server 2007 on March 20. The presentation will include information on planning, governance, information architecture, and physical architecture. The course is intended for technology executives, business executives, vice presidents, CIOs, IT directors, architects and more.
 
The event will be held at Microsoft Corp.’s Southfield office, 1000 Town Center, Suite 1930, from 8:30 a.m. to noon.
 

Heroes Happen Here Launch Event

I will be at the Sogeti exhibitor booth for the Microsoft "Heroes Happen Here" launch event in Detroit, Michigan.    The event is March 18th at the Detroit Marriott in the Renaissance Center.
 
Register here and attend to take home a free copy of Windows Server 2008, Microsoft SQL Server 2008 and Microsoft Visual Studio 2008!
 
Stop by the Sogeti booth and register for your chance to win a Microsoft Zune!   Hope to see you at the launch event.
 
Update: This event has reached maximum registrations.  

“Source” is your friend

The content query web part in SharePoint 2007 is a great tool for rolling up information from subsites into a top level site.   However, sometimes the default look, feel and functionality just doesn’t fit the requirements.   
 
There is a great MSDN article on how to modify the XSL used by the content query web part to change the way it displays information.   In my case, however, it wasn’t the look that I needed to modify it was the functionality.
 
I used the content query web part to display a list of announcements from all of my sub-sites.   I set up the web part to display the announcements in a bulleted list, grouped by site.   This simple configuration met my initial requirements.     There was one navigation issue I noticed right away.   If the user clicked on the announcement title in the content query web part they were taken to the view form for the announcement which contains a close button.   When the user clicks the close button they are returned to the list where the announcement is stored, not back to the original top level site.    This simple navigation issue caused all sorts of confusion for the users of the system.   They expected the close button to take them back to where they had started.
 
This was actually a simple issue to resolve.   I used the methods outlined in the MSDN article to create a new section in the XSL for my new style template.  I based my new style template on the existing bulleted style.   I then made one simple modification to the anchor tag so that my destination url has a source attribute that specifies where the user came from when clicking on the link.   In this case it is /departments/it/default.aspx.
 
            <a href="{$SafeLinkUrl}&amp;source=/departments/IT/default.aspx" target="{$LinkTarget}" title="{@LinkToolTip}">
 
I saved the update XSL and checked it into SharePoint.    It was then just a simple process of modifying the settings of the content query web part to use the new template.    Now when a user clicks on one of the links they can return back to where they started by clicking on the close button.
 
There might be a way to dynamically set the source instead of the static method I used here.   However, this solution met my immediate needs.
 
 

STSADM Import Error – FatalError: The given key was not present in the dictionary.

On my journey to migrate a large amount of content from one SharePoint 2007 server to another I have run across several strange error messages during the import process.   I have been documenting them here in this blog in an attempt to help others and also to be used as reference material for myself in the future.
 
With my current project I have been able to import all of the content into the new server except for one single site.   I am getting the message FatalError: The given key was not present in the dictionary during the import process.   The error appears after a message indicating that it is attempting to import roles into the system.   So I am guessing that someplace on the original SharePoint server I have some sort of invalid security identifier, group or role.     
 
I am going to keep on digging into this and will update this post once I figure out some solution.
 
Update:  It looks like there was some corrupt security setting on a document library.  I reset the library to inherit permissions from parent and then the export / import process worked.   The good news is that the custom security was not really needed on that library any way so this doesn’t cause any problems.   I wish I had a bit more time to spend to find exactly what user / role was causing the problem.

More SharePoint Site Export/Import Fun

I am slowly making more progress in my quest to export sites from an Enterprise SharePoint Server and import it back into a Standard SharePoint Server.   As you saw in my last post I ran into a problem caused by having lists email enabled.    Since then I have written several small console utilities to help track down problems in the original sites I am exporting.
One of the tools I created helps me hunt down all of the lists that are email enabled.   The utility walks the site hierarchy and looks for any list that has an assigned email address.   If one is found it writes out a comma seperated line that includes the list name, list’s default URL and the email alias used for incoming mail.   This allows me to quickly log all of the information so I can use it later to re-enable the incoming mail feature on the new SharePoint server.    Once the utility gave me the list of sites that are email enabled I could quickly disable them temporarily for the export.
Another tool that I wrote that came in very handy was one that would search for Enterprise SharePoint features that are not supported on the Standard edition of SharePoint.   Like the last tool, I would run this at the command line and receive a list of all the sites I will need to check for enterprise features.   This saved a ton of time.   I checked each site and noticed that 99% of the sites never really used the enterprise features, they just had them enabled on the site.   So a simple process of disabling the enterprise features on these sites took care of that problem.   I did have one site that was using Excel services but after speaking with the site owner we determined it really wasn’t needed.   Now all of the sites should easily import into the standard version of SharePoint.
One last issue that I had was an error during import that indicated a required template was missing on the new SharePoint server.   I wrote another command line utility that searched the site hierarchy looking for any sites that were based on this rogue template.   After running the tool I found that one site was based on this template… and after reviewing the site it was determined to have been just some left over test that one of the Windows administrators had been playing with.    So our solution was to just delete that site.
After spending a few hours writing simple utilities and doing a lot of clean up on the original SharePoint server I was able to successful export and then import all of the sites into the new server.      Mark up one small victory.
Next steps will be to review the export and import logs for any outstanding issues that may have cropped up.   I think I may have a problem with importing survey content.  I noticed there was a message in the import log that said something like  “the user can only answer the survey once”.    I am guessing there is some other setting I will need to modify on the original SharePoint server prior to doing the export that may resolve that issue.   But more research and digging is needed before I take any action.
Once all of the issues are resolved I will be ready to do this whole process for real during a weekend.   When that occurs I will be moving all of the content and then making some DNS changes so all of our users will see the new SharePoint server the next time they log in.    I am hoping that all of this pre-work, testing and trial runs pay off so I have a smooth cutover.   Wish me luck!

STSADM Import – FataError

Recently I have been tasked to migrate a significant amount of content from a SharePoint 2007 Enterprise server to a SharePoint 2007 Standard server.    I decided that the simplest way would be to use the STSADM -export command on the source server and then import the content on the destination server using the STSADM -import command.   Sounded simple, but in practice became very difficult.
The first issue I encountered was related to the different features enabled on the enterprise server vs. the standard server.   I disabled all of the enterprise features (that I could find) on the source server and then proceeded with the export.   During the import process I kept getting errors indicating that some of the features are not found on the destination server.  Although I thought I had disabled all of the enterprise features the export still contained some references.    I re-ran the export again but this time using the -nofilecompression parameter.  This creates a directory with all of the export files.   In this directory I found a file called Requirements.xml.   This contains a list of all of the templates and features that are required by the sites and content exported from the source server.   I noticed that there were still references to enterprise features in this file although I had already disabled the enterprise features on the server.   To resolve this I manually removed the XML nodes related to the enterprise features that were preventing the import process to occur.   When I ran the import process on the destination server I no longer received errors related to missing features or templates.
The next issue I encountered was the following error during the import process
FatalError: Error in the application.
at Microsoft.SharePoint.SPList.UpdateDirectoryManagementService(String oldAlias, String newAlias)
This error appeared on a calendar that was in one of the sites being exported.   After a bunch of digging, testing, and trial/error process I found out that the error was being thrown on lists or libraries that are email enabled.   I disabled the incoming email functionality on these lists on the source server, re-ran the export process.   When I imported the content on the destination server I no longer received the FatalError message.
To make sure everything on the destination server is configured properly I noted down the lists and incoming email addresses that were on the source server so I could reconfigure the destination server with the same settings.
I hope this helps someone else who runs into a similar export/import process.

SharePoint 2007 “Warm Up”

I was running into an issue where the initial connection to a SharePoint 2007 server was taking between 20 to 40 seconds. Once the first page of the SharePoint site loaded the server had a very acceptable response speed. So what was causing that initial delay each morning? The answer is actually quite simple if you understand the basics of ASP.NET. The first time a user visits an ASP.NET application, such as SharePoint, the framework performs some compiling and caching on the server. This compiling and caching requires a bit of time to accomplish and once completed the application will respond much quicker.

The compiling and caching always occurs after an IISRESET is issued or the application pool is recycled for an application. In the case of my SharePoint installation, the application pool recycles every morning at around 1am. This means that the first person to hit the SharePoint site in the morning always experiences what they perceive as poor performance of the server. After that initial page hit the system performed with very acceptable speed. I did a few searches on the internet to see how others are resolving this issue. One solution I saw was to schedule a "warm up" script to automatically do an HTTP get request against a couple pages on the SharePoint site. This looked very promising; however, I was soon disappointed when the script appeared to not have any impact on the performance of my server. I soon figured out the reason is that the script was doing an anonymous HTTP get request and my SharePoint site required user credentials to log in. This gave me an idea… how about creating a simple .NET console application that can perform an HTTP get request using credentials.

So I set off to create the utility. The initial version was quite basic. It accepted 3 parameters; a URL, a username and a password. The utility would make a get request based on the URL and would do that using the provided credentials. This was a good start, but I was a bit worried about security. I really didn’t want to have a username and password sitting visible in a "warm up" script on the server. I went back and modified the utility so that a user could register a URL with its username and password. This information is stored in an XML configuration file with the password encrypted. Now the utility can run and perform a HTTP get against the SharePoint site without exposing the password in plain text on the server’s file system. Very cool stuff.

I took the utility, registered my SharePoint server URLs and passwords and then created a simple batch file to call the utility. This batch was then scheduled on the server to run in the mornings on a daily basis. Since implementing this script and utility the users have been very happy with the performance of SharePoint.

I have zipped up the utility I created and have placed it on my server for download. Feel free to download and use the utility in your environment.

A note about security: although the password is encrypted in the XML file it is still not 100% secure. You should apply appropriate permissions on the directory where this utility resides to prevent non-administrators from gaining access. You assume all responsibility for any security vulnerabilities, problems, or damages caused by using the utility.

So how do you use this utility? Unzip it into a directory, open up a command prompt, switch to the directory where the utility resides and then execute the command httpgetwithpwd. This will provide you with an overview of the options. Most likely the first thing you will want to do is to register a URL with its username and password. You do this with the following command:

Httpgetwithpwd [URL] [username] [password]

Replace [URL],[username] and [password] with the appropriate values.

Now to have the utility do an HTTP request,just call the utility with the URL. For example:

Httpgetwithpwd http://mySharePoint.com

This will do an HTTP get for the specified URL using the stored username and password.

You may be wondering where the URL, username and passwords are stored when you register them. An XML file will be created in the same directory as the utility that contains the URL information. You can open this file and see that the password is encrypted.

It may be tempting to register several URLs and then copy the configuration XML file to another server to use with the httpgetwithpwd utility. Be aware that this will not work. The encryption locks the configuration file to the server it was created on. Using the configuration file on another server will result in an invalid password being passed to during the HTTP get process.

This utility was created in a very short time span and doesn’t have a robust error handler and it won’t prevent you from registering a URL multiple times. Be smart about how you use the utility and it will work well for you.

MySite link back to portal

I have seen a lot of people looking for a simple way to create a link on the mysites pages within SharePoint 2007 back to the main portal site.   The issue is that the MySites are in a seperate site collection within the portal, therefore the navigation does not carry over.

Here are a few solutions I have seen:

  1. Write some code and deploy a feature which causes the mysites to use a different master page that has your new link on it.   This is ok, but seems to be troublesome to get working.   It also is overkill when you just want to get a single link back to the portal working.
  2. Use the personalization site links option in the shared services provider administration page to add a link back to the portal.   This does get you back to the portal but has a nasty feature which causes the navigation on your portal to look all screwy.   This wonderful feature is the addition of the MySiteView=1 parameter being tacked to the end of any URL.
  3. Users could create a site portal connection back to the main portal.   But this requires the user to have a good understanding of SharePoint.   Since this is a manual process most end users are not happy with this idea.
  4. Create an automated scheduled process using the SharePoint APIs to automatically add the site portal connection.  (haven’t really looked into this, but I am guessing it would be possible).

So none of those solutions really were simple or gave the results I needed.    I came up with a simple solution that requires just a little bit of work using SharePoint designer.  (download a free trial if you don’t have it).

1. Download the redirect.aspx page located here.

2. Using SharePoint designer import the redirect.aspx page into the root of your Portal.

3. Open up SharePoint central administration and go to the shared services section.

4. Click on the personalization site links option

5. Click new to add a new link back to your portal from the MySites. For the URL enter: http://[servername]/redirect.aspx?URL=http://[servername] (replace [servername] with the name of your portal server)

6. Add a proper description for the link, specify the owner of the link and then click OK.

Go take a look at your mysite and you will now see the link back to your portal. If you do not see the link wait a few minutes and try again. It can take a little while for SharePoint to update the mysite navigation.

A quick warning about this solution: I have only tested this with Internet Explorer. It also requires that JavaScript be enabled on the browser.

I have received feedback that you could also have the redirect code done on the server side so that JavaScript is not an issue.   In that case you would need to take the code behind for the aspx redirect page, compile it with a strong name and deploy it to the server’s GAC  (global assembly cache)

MOSS and Office XP

It has been a while since I have posted anything out here on the blog. I guess it is about time I add a little bit of new content. J

I recently had a situation where a client wanted to utilize the document libraries in MOSS to provide version control and searching. They also wanted to have a unique ID automatically created for each document. This ID must be displayed in the footer of every document, added to the library, AND they must be able to filter the document library by that ID. So far the requirements could be met with little difficulty with the use of Word 2007… but the issue is that they only have Office XP. They do have plans to upgrade to Office 2007 within the year but they needed this solution to work now.

One of the first challenges we ran into was creating a unique ID for each document. It seemed like a simple task since each record in the document library is automatically given an ID by SharePoint. We thought we could easily read that information and use it for filtering. We were wrong. You cannot filter or create custom searches using the ID property of a document. For the final solution we created a new numeric column in the document library called DOCUMENTID. We quickly wrote a small C# console app that made the DOCUMENTID field hidden so that when users check in a document they are not prompted to enter in this value. The next step was to write a simple event handler that we attached to the document library that upon document check-in would grab the ID field from the document library and store it in the DOCUMENTID field. We now have a unique ID that can be searched.

Now that we have a unique ID in the DOCUMENTID field, how do we go about showing this in the footer of the document? To accomplish this task we created a custom Word XP template that has a bit of VBA code in the document load event. We can then on document load read this property and just add the text into the footer of the document. Very simple really.

Having a template is not an issue since the users will always click on the "NEW" button in Sharepoint whenever they wish to create a new Word document. It is interesting to note that the new DOCUMENTID field is a property that also gets embedded into the word document when it is checked into our document library. This happens automatically and requires no coding or special action to occur.

One of the other challenges we had is that when you check in a document using Office 2007 into a version controlled document library you are asked if you want to create a major version, minor version or overwrite the existing minor version. In Office XP you do not get this dialog. In fact the document does not get checked in until the user returns to the website and manually checks in the document. Our client felt that their users may not remember to return to the document library to check in the document. So the requirement was added that upon closing of the document in Office XP a window must appear asking the user to save the document (if not already saved) and then if the document is checked out ask the user if they wish to check in the document as a major version, minor version, overwrite the existing minor version or to keep the document checked out.

Since we have already created a modified Word template for this project we decided to enhance this template with even more VBA code and a custom form. One section of the VBA code checks to make sure that the user saved the document prior to displaying the custom check-in form. The check-in form then asks the user if they would like to check in the document as a major version, minor version, overwrite an existing minor version or keep the document checked out. After the user makes a selection and clicks on an "accept" button the VBA code takes over. If the user selects to keep the document checked out Word XP closes and no further actions occur. If the user selects a check-in option then we utilize a MOSS webservice (using MSSoap.SoapClient object) , passing in the proper check-in parameters, to check the document in. Word XP closes once the document has been checked into MOSS.

As you can see with a little bit of creativity you can integrate even older applications into Microsoft Office SharePoint 2007. I am not able to provide C# or VBA code samples for this article but I am sure with the information presented above you can quickly create a solution that meets your clients needs.

Visual Studio 2005 for Database Professionals

Visit Sogeti (and myself) at the Visual Studio 2005 for Database Professionals launch event in Detroit, Michigan on December 5, 2006. This is a free event where you can learn how Visual Studio Team System improves development team collaboration and increases application quality with better control over database changes and automated database testing.

Visit http://www.teams-deliver.com/ to register.

Also check out the partners page where you will see a brief overview of Sogeti.