Microsoft Learning Gateway Templates

The Microsoft Learning Gateway on CodePlex is a collection of site definitions/templates and web parts designed to kick start a school or district portal. In fact the documentation tells you to set up your school as though you are a district even if being installed in a single school.

My recommendation is NOT to use the site definitions, even though I am the project co-ordinator.  Firstly, let me say that I think that the web parts in the project are useful and have value, so it’s just the definitions I have an issue with.

Why is this?

There’s 2 reasons: actual problems and their lack of value.

The problems

1.    Complex Site Definition

The school site definition is complex. It builds a hierarchy of about 6 sites with each site having 1 to 3 pages. The problem with this is maintainability. There is a growing consensus that site definitions should be as minimal as possible, with most of the work done by features and custom provisioning code if there is a need for an automated build.

The problems with site definitions is that there is no guarantee that they will work when upgrading SharePoint and you can’t modify them once they are deployed.

Problems with upgrading could happen with a service pack or especially a new version – SharePoint 2010 is almost here. Microsoft is pretty much going to guarantee that sites based on the built in definitions upgrade and they will be working hard to minimize problems with custom definitions. However there’s no way they can catch all problems in templates they’ve never even seen. And the more complex the template, the more likely that there will be problems.

For a more in depth treatment see Do you Really Need to Create Custom Site Definitions? by Joel Oleson and You don’t need to create site definitions by Andrew Connell.

Strictly speaking this isn’t a current problem, but could be a huge problem for you when you upgrade if your entire site is based on a definition which doesn’t upgrade well. Whether this is an acceptable risk is then down to the value the definitions provide.

Having said that the 1.1 release modifies the existing templates to support the latest version of SLK and by doing this, it puts the templates in a unsupported state (in Microsoft terms).

2.    Publishing Pages or Not!

The second problem, and this is a real existing problem, is with the pages on the sites. The sites are publishing sites, will all the associated publishing functionality including the Pages library to store the site pages. And this is where the MLG pages are stored. The problem is that the MLG pages are not actually publishing pages.

Publishing pages are special pages which inherit from a specific class and are basically a combination of a page layout from the page layout gallery, and the values of field controls. The MLG pages are just standard web part pages. You can see this by clicking on View All Content and then selecting Pages under Document Libraries. You will see that the Page Layout column is blank. If you try creating a page in the Pages library, the first thing it does is ask you what page layout you want to use.

How is this a problem, they pages all seem to work? Well SharePoint treats the Pages library in a special manner, but it does accept having the web part pages in their with no problem except for one thing. When you come to Edit the page and save it, you get an error about the page being updated in the meantime. You can then save again and all is well. I accept that this seems fairly minor, especially as there is a workaround. But it does confuse people, who question why it happens, and it certainly isn’t going to help with the uptake of your Gateway if there’s obvious errors in it.

3.    Site Collections

Finally, the last major problem is that the school sites are all created in the same site collection. Although this seems to be a good idea on first look, making it easy to share and collaborate, further down the line it start becoming a problem. Having schools in separate site collections is much easier to maintain and backup. You can set quotas on the site collections and move them between databases if they become too big. It’s easier to maintain users and groups as they are scoped at the site collection level and there are many other advantages. There also isn’t really a problem in collaboration between site collections.

The lack of value

What value do the MLG site definitions give? They allow the quick creation of a school gateway by someone with limited SharePoint knowledge. However, it is a bare-bones start. No-one is going to use it just as it’s created. Before it’s used, at a minimum the following needs to happen:
1.  Brand the site. One of the most complex and difficult parts of SharePoint to get right.
2.  Add useful content.
3.  Add more sites to make it usable. For example in the default layout you need to add your class sites. You may want to add departmental sites for your staff to add content to.
4.  Add all your users.

By themselves, none of these are particularly difficult, except the branding. However, the fact that they still need to get done, negates the usefulness of a speedy school creation.

It is also easy to create the layout manually instead of using the site definition. I would recommend a school to do this. Not only will it allow you to get the site layout exactly as works for your school, but you will then be completely familiar with how it is set up. And if you don’t know much about SharePoint, the mere fact you site up the site from scratch means that you will understand it and SharePoint much better. If you already know SharePoint well, the time taken will only be marginally greater than using the site definition. This way you not only get a site better suited to you, you get more experience of SharePoint and don’t have any of the problems detailed above as you will be basing it on an out of the box template. In a later post I will describe how to replicate the school site manually.

The one case where having a site definition is useful is if you are hosting many school sites. And by many I’m talking over 50 if not hundreds of sites. In this case hand building each school does become an issue. However, if you are hosting that many then you really ought to be investing in getting your own templates created, targeted at your and your schools’ needs and branding and not using a generic, brand less, minimal functionality one which at the end of the day are what the MLG definitions are.

Read More

SharePoint bug in SPWeb.AllRolesForCurrentUser

I’ve finally tracked down the bug in SPWeb.AllRolesForCurrentUser. This has been mysteriously failing for some users in some set ups when using the SharePoint Learning Kit as discussed on the CodePlex forums.

When this happened to a customer, I was able to debug it and found out the problem. I can now re-produce it at will and it’s definitely a bug in SharePoint.

The problem occurs when the user is a member of a large number of SharePoint groups. To retrieve all the roles, SharePoint makes a call to the database. In normal circumstances this call is along the lines of

SELECT DISTINCT ra.RoleId FROM RoleAssignment AS ra 
WHERE ra.ScopeId = '67FD4879-2097-4B98-9771-5A6E9D11F0E9' AND ra.PrincipalId IN (3,1 )

where 3 and 1 are the IDs of the groups and the guid (67FD4879-2097-4B98-9771-5A6E9D11F0E9) is the ID of the site. This call is retrieving all the role assignments on this site for all the groups that the user is a member of.

Now when the user is a member of a large number of groups the SQL generated is:

SELECT DISTINCT ra.RoleId FROM RoleAssignment AS ra 
WHERE ra.ScopeId = '67FD4879-2097-4B98-9771-5A6E9D11F0E9' AND ra.PrincipalId 
IN (SELECT DISTINCT ra.RoleId FROM RoleAssignment AS ra WHERE ra.ScopeId = '67FD4879-2097-4B98-9771-5A6E9D11F0E9' AND ra.PrincipalId IN (839,1840,1841,.......,2611,2612,1 ) 

The …….. is where I’ve removed about 740 group IDs.

I’m not sure what’s happening here in the SQL generation, but the "SELECT .. FROM .. WHERE .. IN(" bit is repeated twice leading to invalid SQL. Apart from being a nonsense statement there are 2 opening braces and only 1 closing brace. The code is obviously getting confused by so many groups. My initial thought was that it allocated a buffer for the string generation, but it wasn’t big enough, but that doesn’t explain the 2 sets of SELECT … .

This is easy to reproduce. All you need to do is create a large number of groups with the current user in, and then call AllRolesForCurrentUser, not forgetting to delete them all afterwards or you’ll quickly clutter up your server. I found 800 is enough to make it fail for me, different environment may need more. A sample test class is shown at then end.

In normal use, no user is going to be a member of this many groups – for a start membership of this many is going to need to be automated. However, the best use of SLK requires a site per class and in a reasonably sized Secondary school, this can easily be over 1000 members. Then it’s generally only the administrator who is affected if his account has been used to create the sites, and only if you have a group per site for membership purposes.

I don’t normally create groups for class sites anyway. The maintenance screens for groups are just not very user friendly – you have to manually page through the lists to find a group – and it makes the year roll-over a pain. My preference is to give the users explicit permissions on the class sites rather than through groups, something I’ve discussed before.

using System; 
using System.Collections.Generic; 
using System.Globalization; 
using System.IO; 
using Microsoft.SharePoint; 

namespace SharePointTest 
  public class AllRolesTest 
    public static void Main() 
      //Url to a SharePoint site. Any site but don't do it on a live server. 
      string url = "http://salamanderdemo/sites/mis"; 
      //The username of the user you are running as. I could have programmatically found this out, but it 
      //wouldn't have added anything to the example 
      string userName = "DEMO\\Administrator"; 

        using (SPSite site = new SPSite(url)) 
          using (SPWeb web = site.OpenWeb()) 
            SPUser user = web.SiteUsers[userName]; 

            // This call should succeed 
            SPRoleDefinitionBindingCollection allRoles = web.AllRolesForCurrentUser; 
            Console.WriteLine("First AllRolesForCurrentUser worked."); 

            List<string> names = new List<string>(); 
              //Create all the groups 
              for (int i = 0; i < 800; i++) 
                if (i%100 == 0) 
                  Console.WriteLine("Added {0} groups.", i); 
                string name = Guid.NewGuid().ToString(); 
                web.SiteGroups.Add(name, user, user, name); 

                // This call should fail 
                allRoles = web.AllRolesForCurrentUser; 
                Console.WriteLine("AllRolesForCurrentUser succeeded, try adding more groups."); 
              catch (SPException e) 
                Console.WriteLine("AllRolesForCurrentUser failed."); 
              int i=0; 
              foreach (string name in names) 
                if (i%100 == 0) 
                  Console.WriteLine("Deleted {0} groups.", i); 
      catch (Exception e) 

Read More

SharePoint Learning Kit : Limit Assignments Shown to This Year’s Assignments

By default the SLK Assignment List Web Part shows all assignments ever associated with a learner or instructor. Now that schools are starting to get to the point where they will have been using it for more than one academic year, they do not want the previous year’s assignments showing.

Fortunately there is a built in way in SLK to handle this. The items shown in the web part are completely configurable and are described in the SlkSettings.xml file associated with a site collection.

As an example let’s view the web part for a test instructor.


As you can see he has 8 active assignments. Now we decide that we want to only display assignments which have a start date greater than 01 June 2009.

So first of all we download the SlkSettings.xml through the "Configure SharePoint Learning Kit" page in central administration, change it and then upload it again (click for a larger view).


The change you need to make is to add the following line to the ActiveInstructor query.

<Condition ViewColumnName="AssignmentStartDate" Operator="GreaterThan" Value="2009-06-01" />

The image shows where it should go (click for a larger view).


What this does is add a new condition to the query so that it only brings back assignments whose start date is greater than the Value. You need to use the start date rather than the due date because I haven’t found a way to bring back assignments with due dates greater than the value, and ones without a due date. If I add a condition for due date in, none of the assignments without a due date are returned. As the start date is a mandatory field this is not a problem.

Once you’ve made the change and uploaded the new settings file back up, this is what the web part looks like.


As you can see the four assignments whose start date were less than 02 June 2009 are not returned. They are still present in the other queries though as so far we have only altered the active query for instructors. To complete the job you will need to add the condition to all the queries for instructors, learners and observers.

Finally, if you would like to display assignments outside of those dates somewhere in your portal, you can have different instances of the web part display different queries by defining custom query sets in the settings file. I’ll leave that until another time if there’s a demand for it though.

Read More

Google Chart API

I’ve just been using the Google Chart API to create charts in some web parts. If you haven’t come across it before it’s a fantastic free tool for charting. For example the 2 images which follow come straight from Google using data embedded in the url.

All you need to do to include a chart is include an image element in your html pointing to the Google chart servers with the appropriate parameters. You do of course need an internet connection for this to work as the images are retrieved directly from Google.

You can control everything about how the chart is built and displayed and 9 different types of charts available. I think that this is a valuable addition to your toolset. To see more details go to the Developers Guide.

As an example I’ll work through an example with some of the data I was using, lesson attendance data.


This is generated with the following image element.

<img src=”×125 &chco=008000,FFFF00,FF9900,FF0000,0000FF&chdl=Present|Late|Authorised%20Absence|Unauthorised20Absence&chba=a&chxt=x,y&chxl=0:|Psy|Bus|Inf|Phy||1:|0|25|50 &chds=0,50 &chd=t:4,21,22,0|0,0,0,0|0,0,0,0|1,16,7,0” />

It looks complex, and until you get the hang of the parameters it can be, but going through each parameter in turn it turns out to be remarkably easy to use.


This is the type of chart, in this case a vertical bar type.


The size of chart in pixels


The chart colours in hex format. Only hex format is supported.


The chart labels


Auto-size the chart columns if they don’t fit, By default each column is 25 pixels wide.


Defines the axes for the rest of the axis labelling.


Any axes labels. The digit followed by a : indicates it’s for that positioned axes in chxt. So this futher splits down into

0:|Psy|Bus|Inf|Phy meaning for axis x use the values Psy, Bus, Inf & Phy

1:|0|25|50 meaning for axis y use the values 0, 25 and 50


This defines the scaling of the graph. Be default the scale is 0 to 100 so for this data where the maximum is 37, it would all be squashed in the bottom half of the image. Another thing to bear in mind is that values smaller than the ranges will not appear and values greater than the maximum will be truncated to the maximum.


This is the actual data. The t indicates the type of data, in this case text with data scaling as we’ve included the chds parameter. The possibilities are

  • Text: Float number 0 – 100
  • Test with data scaling: Any positive or negative number
  • Simple encoding: Integers 0 – 61. Each value represented by a single alphanumeric character. This is the shortest data string, but is very limited.
  • Extended encoding: Integers 0 – 4095. Each value represented by two alphanumeric characters.

Read More

Delete Multiple Web Parts From a SharePoint Page

If you ever need to quickly delete multiple web parts from a SharePoint page, there’s a quick and easy way.

Just add ?contents=1 to the end of the url, directly after the .aspx. If there’s already a query string there (the bit after the ?) then delete it and replace with contents=1.

For example to delete multiple web parts from http://cmis/sites/mis/default.aspx use http://cmis/sites/mis/default.aspx?contents=1.

You can then select multiple web parts and hit delete to get rid of them all at once.


This is also useful for getting rid of web parts which cause fatal errors on the page and closed web parts.

Read More

Memory Leaks in My Planner Web Part

Just spent an evening hunting down and fixing memory leaks in the MLG My Planner web part. The code was opening SPSite and SPWeb objects and then not disposing them. Level 101 error by whoever wrote it!

The layout of the code is a bit bizarre. There’s the main web part project, and 6 other supporting projects, all of which are required by the web part, but not used by another other project. They each only contain 1 or 2 files. This is totally unnecessary and leads to having to ship 6 extra dlls. When I get a bit more time to work on it I’ll have to combine them all into one dll.

Read More