I read Joel Oleson’s recent blog post called The Great Virtualization Debate: What to do? SharePoint 2010 for Laptops and thought I would chime in with a few comments.

So far my personal preference for developing SharePoint 2010 solutions on my laptop is to install it directly on Windows 7.  Unlike running it virtualized I can more efficiently use my very limited memory (4GB) and other system resources.   If I throw it up into a virtual image I am already limiting the SharePoint environment to 3GB or less plus there is the overhead of the guest operating system.   So by the time everything is said and done SharePoint is down to about 2GB of ram available.  This includes trying to run SQL, SharePoint and Visual Studio.    Not a good experience at all.

One argument Joel had against running SharePoint 2010 directly on Windows 7 is the downside of having the services eating up your RAM all the time.  I just noticed that Joel did update his original post stating that you can disable and stop the services supporting SharePoint when they are not needed, freeing up RAM and CPU resources.     This is exactly how I have configured my system.   When I need to work with SharePoint 2010 I kick off a PowerShell script that starts up all of the services in the proper order.  Within a couple minutes I am ready for some coding.   Once I am done I can run a 2nd script to shutdown the SharePoint services and recover all of the used RAM and processing power.   

I would make one note of caution here.  I have seen some scripts for disabling and shutting down services that I feel handle things in the wrong order.  I would strongly advise against stopping the SQL service before stopping the other SharePoint services.   The last thing we want is to end up with some strange state because SharePoint was doing a bunch of database insert / updates / deletes as we shut down SQL.    Sure SQL is transactional and that shouldn’t cause any problems… the transactions would either complete or be rolled back.   I guess maybe I am just a bit paranoid here and don’t want to end up losing a bunch of content.

Bottom line is, do what makes sense for your setup.  For me I don’t want to be dual booting my machine and losing access to my Outlook inbox or other applications just so I can do development.   I don’t want to eat up a bunch of memory using VirtualBox or some other virtualization product to host a guest OS with SharePoint on top of it.   I also don’t want to install a server OS and lose out on power management and other nice little features I have come to love in a desktop OS.   Developing for SharePoint directly on Windows 7 works very well for me.


Microsoft has replaced the Single Sign-On service in SharePoint 2007 with the Secure Store Service (SSS).  With this change also comes a pretty big overhaul of the API set.   If you have written any custom applications, web parts or utilities that used the SSO service in 2007 you may be required to rewrite or update your code to reflect these changes.  Currently there is very little information on the Secure Store Service API outside of the list of classes on MSDN.   I have, however, managed to write a simple sample console application that can retrieve the credentials of the currently logged in user for an application configured in SSS.

To use the following sample code you will need to add a reference to the following assemblies:

  • Microsoft.BusinessData
  • System.Web
  • System.Web.DataVisualization
  • Microsoft.Office.SecureStoreService.Server
  • Microsoft.SharePoint

The Microsoft.Office.SecureStoreService.Server assembly was not immediately available on my SharePoint 2010 beta installation.  After much searching I located it in a CAB file and had to extract it out in order to use it.  On my server it was located in C:\Program Files (x86)\MSECache\oserver2010\Global\Search\osrchwfe.cab.  Most of the other assemblies can be found in either the .NET tab of the references dialog box in Visual Studio or by browsing to c:\program files\common files\microsoft shared\web server extensions\14\ISAPI.  

Before using this code you will need to configure the Secure Store Service on SharePoint 2010 with at least one application.  To retrieve credentials you will also need to have set the credentials for the specified application and associate it with a user account that will be running this sample code.

Before running the sample code replace SERVERNAME with your own SharePoint 2010 server URL and APPLICATIONID with an application ID stored in SSS.  Also ensure that you have the target framework set to 3.5 and the platform target set to Any CPU in Visual Studio.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.Office.SecureStoreService.Server;
using Microsoft.BusinessData.Infrastructure.SecureStore;

namespace SSSTEST
{
    class Program
  
{
        static void Main(string[] args)
        {
            //Retrieves the current users application username and password.
          
SecureStoreProvider prov = new SecureStoreProvider();
            using(SPSite site = new SPSite(http://SERVERNAME))
            {
                Console.WriteLine(site.RootWeb.CurrentUser.Name);
                SPServiceContext context = SPServiceContext.GetContext(site);
                prov.Context = context;
                string appID = "APPLICATIONID";
                try
              
{
                    SecureStoreCredentialCollection cc = prov.GetCredentials(appID);
                    foreach (SecureStoreCredential c in cc)
                    {
                        IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(c.Credential);
                        string sDecrypString = System.Runtime.InteropServices.Marshal.PtrToStringUni(ptr);
                        Console.WriteLine(sDecrypString);
                    }
                }
                catch(Exceptionex)
                {
                    Console.WriteLine("Unable to get credentials for application "+ appID);
                    Console.WriteLine(ex.Message);
                }
                Console.ReadLine();
            }
        }
    }
}


If you are creating a console application for use with Microsoft SharePoint 2010 you need to ensure that your target platform is Any CPU or x64 for your project.  If the target is x86 you will receive an error The web application at {url} could not be found when creating a new SPSite object.

To change the target platform: select project from Visual Studio menu, choose {project name} properties.   From the properties window select the build tab and set the platform target to Any CPU or x64.


I had written a simple web part for SharePoint 2007 that generates a directory listing of all sites a user has permissions to view.   This web part makes use of the SharePoint search web service to quickly retrieve a listing of sites which are security trimmed to the logged in user.

I decided to test that web part in my new SharePoint 2010 beta development environment and immediately ran into a very cryptic error message: System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail].   That was it… no real details to help debugging the problem.   I jumped into the ULS logs for SharePoint 2010 and found a little bit more information:   Exception from HRESULT: 0×80040E01.

I did a few searches and ran across a post on MSDN forums where a person indicated they were getting an error with the same HRESULT when trying to run a search query.   The suggestion was to reduce the RowLimit parameter.   In my instance I wasn’t using RowLimit but I was using <Count>1000</Count> in my CAML string being passed to the QueryEx method of the search web service.   I reduced the count to 500 and tested my web part.   This time it worked perfectly.

It appears that SharePoint 2010’s new resource throttling may be kicking in when I set the count level higher even though I had only 2 items being returned in my query.   SharePoint 2010 puts on the breaks and throws a cryptic exception just because I asked for a maximum of 1000 items even though only 2 would have been returned.

I am hoping that this error message will be enhanced in the RTM version of SharePoint 2010 so we can more easily debug the issue.  I would also like to see documentation on the throttle limit and how an administrator could change that limit if necessary. 


One of the more confusing and incorrectly named settings option for a document library is “manage checked out files”.  At first glance you probably think that this feature will allow you to see every file that is checked out and to whom.  That was my first reaction and as I soon learned it is the wrong assumption.

First this link really doesn’t have any use if you don’t have the library set to require check out when editing files.  When requiring a file to be checked out prior to editing a rather interesting thing happens when a user chooses to upload a file to the document library.   The file is first uploaded into the library and marked as checked out to that user.  The user is then prompted to enter in required metadata and then he must click on the check-in button to make the file available to other users.    If the user uploading the file does not check the file in then it is left in a rather strange state.    The file is in the document library, however, no one except the person who uploaded the file can see it… including administrators!    

A couple of interesting side effects occurs as a result of this.  As an administrator you will see that the number of items displayed in a document library or returned as available using the SPList.Items.Count API may not equal the item count shown on the view all site content page (or with the SPList.ItemCount API).   If you notice that the counts do not match you should use the manage checked out files option to view the files that have been uploaded but not checked in.   As an administrator or document library owner you can take ownership of the files and either check them in or delete them.

Microsoft must have also decided that naming the feature “manage checked out files” was confusing.   In SharePoint 2010 Beta they have renamed the feature to “Manage files which have no checked in version".  

I have seen several posts on Microsoft’s MSDN forums about administrators trying to delete a custom document content type but the administrator keeps getting an error stating that the content type is still in use.   In almost every one of these posts the administrator states that all of the documents have been associated with a new content type and the old one is no longer in use.   What most of these individuals didn’t do is check the “manage checked out files”.  The administrator will most likely see that a file was uploaded into the library and by default associated with the content type he is trying to delete.   The administrator can take ownership of this file and either delete it or modify the content type association and check the file in.   Once this has been accomplished the administrator should be able to delete the old content type from the document library.

Hopefully this brief overview of the manage checked out files feature of a document library will save a SharePoint administrator a bit of time.


I am happy to say I am now running SharePoint 2010 Beta on my Windows 7 laptop.   I used the handy guide from Microsoft called “Setting Up the Development Environment for SharePoint Server“ for step by step instructions.

There was, however, one small problem.  During the configuration wizard I received the following nasty message:

Failed to create sample data.
An exception of type Microsoft.Office.Server.UserProfiles.UserProfileException was thrown.  Additional exception information: Unrecognized attribute ‘allowInsecureTransport’. Note that attribute names are case-sensitive. (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\WebClients\Profile\client.config line 56)
Microsoft.Office.Server.UserProfiles.UserProfileException: Unrecognized attribute ‘allowInsecureTransport’. Note that attribute names are case-sensitive. (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\WebClients\Profile\client.config line 56) —> System.Configuration.ConfigurationErrorsException: Unrecognized attribute ‘allowInsecureTransport’. Note that attribute names are case-sensitive. (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\WebClients\Profile\client.config line 56)
   at System.Configuration.BaseConfigurationRecord.EvaluateOne(String[] keys, SectionInput input, Boolean isTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult)
   at System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult, Boolean getLkg, Boolean getRuntimeObject, Object& result, Object& resultRuntimeObject)
   at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
   at System.Configuration.ConfigurationSectionCollection.Get(String name)
   at System.ServiceModel.Configuration.ServiceModelSectionGroup.get_Client()
   at Microsoft.Office.Server.UserProfiles.MossClientBase`1.GetServiceBinding(String endpointConfigurationName)
   at Microsoft.Office.Server.UserProfiles.MossClientBase`1.GetChannelFactory(String endpointConfigurationName)
   at Microsoft.Office.Server.UserProfiles.MossClientBase`1.get_Channel()
   at Microsoft.Office.Server.UserProfiles.MossClientBase`1.ExecuteOnChannel(String operationName, CodeBlock codeBlock)
   at Microsoft.Office.Server.UserProfiles.ProfilePropertyServiceClient.ExecuteOnChannel(String operationName, CodeBlock codeBlock)
   — End of inner exception stack trace —
   at Microsoft.Office.Server.UserProfiles.ProfilePropertyServiceClient.ExecuteOnChannel(String operationName, CodeBlock codeBlock)
   at Microsoft.Office.Server.UserProfiles.ProfilePropertyServiceClient.GetProfileProperties()
   at Microsoft.Office.Server.Administration.UserProfileApplicationProxy.RefreshProperties(Guid applicationID)
   at Microsoft.Office.Server.Utilities.SPAsyncCache`2.GetValueNow(K key)
   at Microsoft.Office.Server.Utilities.SPAsyncCache`2.GetValue(K key, Boolean asynchronous)
   at Microsoft.Office.Server.Administration.UserProfileApplicationProxy.InitializePropertyCache()
   at Microsoft.Office.Server.Administration.UserProfileApplicationProxy.Provision()
   at Microsoft.SharePoint.PostSetupConfiguration.EvalModeProvisionTask.ProvisionServiceApplicationsAndProxies()
   at Microsoft.SharePoint.PostSetupConfiguration.EvalModeProvisionTask.Run()
   at Microsoft.SharePoint.PostSetupConfiguration.TaskThread.ExecuteTask()

After a quick search on Twitter I found a recommendation to just remove the allowInsecureTransport attribute from the client.config file.  I found 2 references to the attribute.  After removing the attribute and then restarting the wizard everything completed successfully.

It is still too early to tell if that change will have a negative impact on some other aspect of the environment.  So far SP2010 seems to be running well.   If I have any problems appear I will post them here.

UPDATE: It appears that there is an issue with WCF and Microsoft is going to provide a hotfix.  They recommend that you do not modify the XML files.  

I did notice that making this change did allow the software to install but Search fails to return results.  There have been posts that you can make a similar modification to the C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\WebClients\SearchService\client.config file and search will start working.  I have yet to try this.

If you do make changes you do so at your own risk.  I have backed up any XML files I have modified so I can return them to their original state.

UPDATE 2:  Microsoft has just posted an update for Windows 7 and Windows Server 2008 R2 that resolves this issue.  For me I stopped all SharePoint services, installed the hotfix, and then restarted the services.   Now search is working fine in my environment.   You can download the patch from here: http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=23806


Microsoft just posted Office 2010 and SharePoint 2010 on MSDN and TechNet.  Time to build up the development machines and start trying out the Visual Studio 2010 Beta 2 development integration.

Don’t forget, you can now install SharePoint 2010 on a 64bit Windows 7 machine (or Vista) for development purposes.   Make sure you follow the instructions located at http://msdn.microsoft.com/en-us/library/ee554869(office.14).aspx.   You need to manually download and install a set of prerequisites and make a change to an installation configuration file.

Good luck and have fun!


Organizations that deploy Microsoft Office SharePoint Server 2007 for collaboration often find that the number of site collections and subsites grow very quickly.  It seems like it doesn’t take long for end users to figure out how flexible and easy SharePoint is for creating simple “applications”.   Even with a good taxonomy and solid governance plan there is little that can be done to hold back the growth of a SharePoint environment.    This growth can make it complex and confusing for users to navigate to their sites.   One option is for the SharePoint administrators to manage a complex navigation hierarchy that supports every site in the farm.   Another option is for the users to use search to locate their sites, however, many users still seem to prefer browsing over search.   One solution I created to help address this is a personalized site directory.   This directory lists out all of the sites under a specific web application that the user has permissions to view.    This display is in alphabetical order based on site titles.  The display also has visual clues to show the relationships between sites and subsites.

To create this site directory I looked at many options.  The first and most obvious one is to use the SharePoint API to enumerate all of the sites in a web application and then look for the sites that the currently logged in user has permissions to view.   This could work, but would be very slow and processor intensive.   The option I elected to go with was using a custom query to the SharePoint search engine and then process the results.   Why search?  Simple, search is security trimmed.   I do not have to perform any additional logic to make sure I only locate sites that the user has permissions to view.  Search is also very fast.

My original version used SharePoint Designer and a DataView web part to submit a query to the SharePoint search web service.  An XSL stylesheet was then applied to the XML returned from the query to render the directory.   The problem with this was that the resulting directory listing was not in alphabetical order and maintaining visual clues about relationships between parent and child sites was difficult and did not always work properly.

I revisited my original idea and came up with a custom SharePoint web part that still uses a search query but then applies much more in depth logic to properly order and display links to the SharePoint sites.    So how did I create the personalized SharePoint site directory?

The first step is creating the proper query to send to the SharePoint search web service.   Below is an example query.   The variable server should contain the domain name of the web application you wish to use as the basis for the directory.  An example would be:  my.domain.com

string query = "<QueryPacket xmlns =\"urn:Microsoft.Search.Query\" Revision =\"1000\">";
  query+="<Query><Context><QueryText language =\"en-US\" type =\"MSSQLFT\">SELECT Title, url, contentclass";
  query+="FROM SCOPE() where (ContentClass ='sts_web' or ContentClass ='sts_site' or ";
  query+="contentClass ='sts_listitem_850') and site ='" + server + "' and isDocument =0</QueryText>";
  query+="</Context><Range><StartAt>1</StartAt><Count>1000</Count></Range></Query></QueryPacket>";

 

This query uses contentClass to limit the results of the query to just publishing and team sites.   The <Count> parameter limits the maximum number of sites to return to 1000.   This could be adjusted if you have more sites to list, however, I would be very careful trying to display that many sites on a single web page.

Once the query is executed we receive a DataSet that contains a single DataTable with the query results.   As you can see by the query we only receive back title, URL and contentClass.   Before we can display our directory we need to figure out a way to relate each of the rows so we can display the parent / child relationship between sites and subsites.    To build this relationship I start by adding 3 new columns to our query results DataTable:

dt.Columns.Add(new DataColumn("id", typeof(System.Int32)));
dt.Columns.Add(new DataColumn("parentid", typeof(System.Int32)));
dt.Columns.Add(new DataColumn("origURL", typeof(System.String)));


The id column will hold a unique identifier for each record.   The parentid will hold the unique identifier of the parent record and the origURL will be used to hold the original URL to the site.    Once we have added the new columns we need to populate the id column with data.    I also store the original url in the origURL field and then modify the URL field slightly so I can more easily figure out parent / child relationships based on that URL.

            for (int i = 0; i < dt.Rows.Count; i++)
            {
                dt.Rows[i]["id"] = i + 1;
                dt.Rows[i]["origURL"] = dt.Rows[i]["URL"];
                dt.Rows[i]["URL"] = dt.Rows[i]["URL"].ToString().ToLower().Replace("/sites", "");
                dt.Rows[i]["URL"] = dt.Rows[i]["URL"].ToString().ToLower().Replace("http://" + server, "");
            }

After populating the id and origURL fields and making a few modifications to the URL field we can begin to update the parentid field.  This is accomplished by looping through all rows in the DataTable and using the select method on the DataTable to locate the parentid for each record.

     for (int i = 0; i < dt.Rows.Count; i++)
        {
            if (string.IsNullOrEmpty(dt.Rows[i]["url"].ToString()))
                dt.Rows[i]["parentid"] = 0;
            else
            {
                string parentURL = dt.Rows[i]["url"].ToString();
                parentURL = parentURL.Substring(0, parentURL.LastIndexOf("/"));

                DataRow[] rows = dt.Select("url='" + parentURL + "'");
                if (rows.Length == 1)
                    dt.Rows[i]["parentid"] = rows[0]["id"];
                else
                {
                    rows = dt.Select("url=''");
                    if (rows.Length == 1)
                        dt.Rows[i]["parentid"] = rows[0]["id"];
                    else
                        dt.Rows[i]["parentid"] = 0;
                }

            }
        }

 

Now that we have a DataTable that contains all of our sites, including parent / child relationships we can create a recursive method for displaying the records in alphabetical order.   The method shown below first creates a DataRow array that contains all of the children for a specific parentID.   LINQ is then used to sort the child records based on Title.   Finally we loop through each of the rows in the sorted array and display the links for the sites.

      private void showDirectory(DataTable dt, int parentID, int level)
      {
          DataRow[] childs = dt.Select("parentid=" + parentID.ToString());
          level++;

          var sortedRows = from p in childs orderby p["title"] select p;

          foreach (DataRow child in sortedRows)
          {
              Controls.Add(new LiteralControl("&nbsp;".Repeat(level * 3)));
              if (level<3)
                  Controls.Add(new LiteralControl("<b><a class='ms-navheader' href='" + child["origurl"].ToString() + "'>" + child["title"].ToString() + "</a></b><br>"));
              else
                  Controls.Add(new LiteralControl("<img src='/_layouts/images/navBullet.gif' alt='' border='0'>&nbsp;<a class='ms-navitem' href='" + child["origurl"].ToString() + "'>" + child["title"].ToString() + "</a><br>"));
              showDirectory(dt, Convert.ToInt32(child["id"]), level);
          }

      }

 

As you looked through the showDirectory method you might have noticed the .Repeat method being called on the string “&nbsp”.   This is an extension method that I wrote to return the original string repeated the number of times specified in the parenthesis.  In this case I am repeating a non-breaking space character so that the text is indented 3 characters for each level of the site hierarchy.  Shown below is the Repeat extension method used.    It could probably be made more efficient by using a StringBuilder object instead of using the += operator.

public static string Repeat(this string instr, int n)
{
    var result = string.Empty;
    for (var i = 0; i < n; i++)
        result += instr;
    return result;
}

 

Important note: With .NET Framework 3.5 SP1 all requests to a webservice located on the same server as the calling application may with a 401 unauthorized error.   There is a good article on blogs.iis.net that explains the issue and how to resolve. 

Download example code here

The example code is intended to show how you could implement a similar directory.  The code may not compile or work as is in your environment.


In service pack 2 for Microsoft Office SharePoint Server 2007 a new operation called PreUpgradeCheck was introduced for the STSADM command.  This operation uses the Microsoft Best Practices Analyzer to identity any issues that will need to be resolved prior to upgrading to SharePoint 2010.

Running the command is simple.  At a command prompt type:  stsadm –o preupgradecheck

This command will not make any modifications to your SharePoint farm.  Once the command is complete you will be presented with a nice HTML report.  The report contains a lot of great information and should probably be stored with your disaster recovery plan.

During a recent run of this command on a production server I received a “Failed” message on the InvalidDatabaseSchema check.   This means that the database schema for one of the content databases did not match the original SharePoint schema.    I was very surprised to see this since no one except for the DBAs had access to the server and no one should have been modifying the databases directly.

I opened up the LOG directory in the SharePoint hive and located the latest PreUpgradeCheck log file.  About 1/2 way down the log I found an entry related to the specific error.  It indicated that an extra table called “sysdiagrams” was found in the content database.    I immediately had my ah-ha moment.   Someone who had access to the server either accidentally or intentionally went into the Database Diagrams folder for the content database in SQL Server Management Studio (SSMS).  When they did this SSMS stated that one or more objects were missing that were required to use database diagramming and asked if they should be created.   Clicking “yes” would immediately create the sysdiagrams table.

To resolve the issue and return the database schema back to the original state I user SSMS and opened up the System Tables section of my content database and deleted the sysdiagrams table.    I went back and ran the PreUpgradeCheck and this time I got a clean report. 

Note: Do not make any modifications to database tables unless you have a full backup and you are confident you could recover in case of an unexpected issue.  Making modifications directly to SharePoint database tables which change the schema from the out of the box configuration may invalidate any support agreements you have with Microsoft.


Sogeti principal consultant, David Giard, has an online technology show called “Technology and Friends”.   David is approaching his 60th episode and to recognize him for all of his great work I wanted to highlight a few of the videos he did with our local Sogeti consultants.    Make sure you check out his public speaking schedule where you can have a chance to see David live and possibly end up in one of his videos!

Sai Naik
Sogeti consultant Sai Naik describes the advantages of SharePoint and where it is a recommended solution.

David Truxall
Principal consultant David Truxall discusses the art of debugging and dives into WinDbg and other tools to debug production issues.

Jesse Murray
Principal consultant Jesse Murray shares his opinions on how to implement SharePoint solutions “the right way”.

Mike Hacker
Director Mike Hacker discusses issues around single sign-on.

Grok Talk Online – Debugging with WinDbg
First Sogeti Grok talk to be recorded and hosted online. 

Check out even more great videos produced and edited by David Giard.