Use SharePoint - Get a Gift

Submitted by Robert MacLean on Tue, 12/09/2008 - 10:36

Microsoft is conducting a survey for people who use SharePoint daily (I am guessing each week day is enough to count for this). This survey can be done remotely which means that in SA we can take part (unless there is some other rule which prevents us) and in exchange for participation we get a Microsoft hardware or software title.

If you are interested please email and insert SharePoint into the subject line.

Thanks to Mark Miller for the heads up!

SharePoint Survey Permissions: Part 2 - Allow anonymous users to vote on surveys

Submitted by Robert MacLean on Mon, 12/08/2008 - 10:07

Part 1, which covers permissions to allow users to vote but not edit the website, can be found here

For the second post I thought I would share the most confusing issue I have personally with SharePoint survey permissions: namely on web site where anonymous users will hit it how do you let them vote? Since they are not members of the site you need to do a few extra steps to get it to work. Before I continue I recommend you read the first post since I will refer back to some parts of it.

The first thing is if you go to the permissions you need to give anonymous users permission, but there is no anonymous user option like we had with the domain group NT AUTHORITY\AUTHENTICATED USERS previously. However if you have configured anonymous access correctly you will find a menu option under settings which allow you to configure Anonymous Access.

Settings –> Anonymous Access.

You may find that it doesn’t work straight away, as in my case, because everything is set to read-only. So you can’t give the anonymous users permissions :(

Read-only settings

To solve this, you need to go to the advanced settings for your survey and set Read Access to All Responses, and click OK. Now don’t worry that you may be sharing information, you will turn this off again in a moment.

Survey advanced settings.

Now if you go back to the anonymous access settings section of the permissions those options has they are no longer read-only! You can now set up anonymous access to your survey and click OK,

Settings now available

Now, if you want to, you can go back to the advanced settings page and set the Read Access to Only their own. Note: The anonymous settings you set are not lost, they are just set to read-only and your survey is available to anonymous users.


SharePoint Survey Permissions Part: 1 - Respond to a survey but do not edit site content

Submitted by Robert MacLean on Mon, 12/08/2008 - 09:49

Part 2, which covers permissions for anonymous users can be found here

Survey’s are a nice feature of SharePoint, however their security is not the easiest to understand. I thought it was just me which didn’t take to it straight away, but seeing Veronique's post on Information Worker made me think it is not just me. So for this post I will answer her question which I am summarizing as: How do you enable a user to respond to a survey but NOT edit the site (the survey sits in) content?

First off we need a survey:

Creating a new survey.

On the settings you need to click the permissions for the survey:

The survey settings page.

On the list permission settings click Actions and then Edit Permissions. At which point you will be asked to confirm you want to create unique permissions for the survey, in short it will not inherit from it’s parent security permissions in the future.

Actions –> Edit Permissions on the survey permissions.

The confirmation prompt.

For my example survey, I am assuming you want to let all users who logged into the site to complete the survey. So for that you need to find the NT AUTHORITY\AUTHENTICATED USERS domain group. Now click on it and make sure you give them Contribute and click OK. Now get back to the survey settings page.

The user listing.

Managing user permissions.

Now click on advanced settings on the settings page.

The settings page.

The advanced settings page allows you to configure who can see what responses and what they can edit. Note: Edit here means changing their votes after they submit, not editing the survey or web site. The fact they have contribute means they can add (submit) votes.

Advanced survey settings.

Once you have done that your survey should be able to be completed by the users, but because we created unique permissions for the list/survey they won’t be able to edit the site which contains the survey.

VS2010 and SharePoint

Submitted by Robert MacLean on Thu, 11/27/2008 - 08:50

There are three sources for information which I have found valuable for VS2010:

  • First is the video from PDC about a lap around VS2010: Great high level introduction to what it will be.
  • Next is Willy’s series on VSTS 2010 which he just finished.
  • Last is for the SharePoint people, is the InfoQ article on it: – which had some serious highlights:
    • "These tools will replace the much-derided SharePoint Designer
    • “Visual Studio will be able to building and debug SharePoint projects. "F5 Just Works!"”
    • “A new Packaging Explorer will exist that supports editing Packaging and structuring the SharePoint Features and WSP file.”

Unfortunately the VS2010 bits we have available currently (if you want a copy let me know) includes everything from the video and Willy’s posts but does not include the WSS items. In fact the forthcoming CTP will not even include them :(

Clean landing page

Submitted by Robert MacLean on Tue, 11/11/2008 - 17:05

I mentioned that your SharePoint site should be clean and simple and have search on it. Well what does that mean visually? Trust Michael O’ Donovan to provide the perfect screen shot in his last post, well actually not in his last post but in the attachments on his last post:


This is clean (duh), it’s easy to use (people can find the content easily), search is there (and has focus because it’s in the centre) and it’s familiar (remind you of any search engines).

SharePoint Search Tips and Tricks

Submitted by Robert MacLean on Tue, 11/11/2008 - 16:44

I thought I would share some tips and tricks for improving the search experience with SharePoint:

In any company you will have people of different backgrounds and skills using SharePoint, and one of the first issues is that search isn’t fine grained enough, and that users either don’t know or don’t feel comfortable with advanced search features to get it fine grained. To make “normal” search easier just add Faceted Search. If you are interested in what that is go and check out the site.

Next improve usage by lighting up SharePoint search to the browsers. Well what does that mean? It means that when you go to a website with a modern browser it “detects” the search functionality and allows you to add it to the build in search functions in your browser, so you can search the SharePoint site from your browser without even going to it first! It does this using an open standard called Open Search. To do this you first need to define an XML file which tells the browser what to do. Example:


Really simple, basically just the name and the encoding. The magic is handled by replacing the tag in the URL ({searchTerms}) with what the user is searching for. That file needs to be uploaded to a location on the SharePoint site where it can be read by users. The next step is exposing it to the browsers, to do this you just need to add a line to the header tag in your master page:

   1: <link rel="search" type="application/opensearchdescription+xml" href="/search/searchdefination.xml" title="BB&amp;D Portal" />

Now the browsers will see the tag and light up the search facility! This is really helpful for improving adoption of search.

Next up it would be great to search multiple locations and you can thanks to a feature in SP 1 called federated search. Where your search query actually calls other web sites for results and places them in a special section of the site, defined by a web part. As I am personally interested in a lot of technologies I think it would be great to have federated search to: Wikipedia, Linux.Com, Java.Sun.Com, MSDN.Microsoft.Com and TechNet.Microsoft.Com, like shown on the left.

What you may notice is that MSDN already has support for federated search, but the rest don’t! So how do you get around that? Well Live.Com also does has support for federated search and it also has support for limiting results to a specific site. So all that is needed to do is to create a search provider configuration for and limit it to the specified website. You can download the sample providers I created below:


The last tip is to implement a very clean landing page for the site with a search box on it. As the new landing is cleaner and smaller than the it meant the initial feeling of SharePoint is it is that it is quicker and more responsive and so it also will improve adoption. To get the search box to search properly using just a tiny bit of HTML + JavaScript which looks like this (assuming you have a textbox with ID called query), this will create the button:

   1: <input type="button" width="100px" height="" value="Search" onclick="window.location='/pages/SearchResults.aspx?k='+document.getElementById('query').value+'&s=All%20Sites';">

Slide.Show and SharePoint: Part III - Deploy and final config

Submitted by Robert MacLean on Fri, 11/07/2008 - 08:30

This is a multi-part series. The other parts can be found at

In part II, I wrote about how to get the data out of SharePoint in a dynamic way using a custom ASP.NET web page which did the hard work for us. The last part of this series is getting that code to work on the SharePoint server. The first step is to create a folder on the server where you will put these files (available at the end of the post). This should be outside your SharePoint directory, something like c:\inetpub\wwwroot\addons would be a good place. Next you need to create a virtual directory on your SharePoint site in IIS which points to that folder. The defaults for the virtual directory will be fine, however from a safety point of view I would recommend it runs in it’s own application pool.

If you just created a ASP.NET application though and put it in there it would fail because the web.config file from SharePoint does some odd things. To get around that you need to few things to it. First clear all the inherited assemblies away (see line 6 below), this has the downside that all the defaults from the machine.config also disappear so you need to add the ones you need back (lines 7 to 13). Next you need to clear all inherited httpModules (see line 19) and lastly you need to increase the trust of this application to full (line 21). Since this is on a virtual directory this has the advantage that you are not messing with the SharePoint config and your SharePoint server will continue to run happily.

   1: <?xml version="1.0"?>
   2: <configuration>
   3:     <system.web>
   4:         <compilation debug="true">
   5:             <assemblies>
   6:                 <clear/>
   7:                 <add assembly="System, Version=, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
   8:                 <add assembly="System.Drawing, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
   9:                 <add assembly="System.Web, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
  10:                 <add assembly="System.Web.Services, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
  11:                 <add assembly="System.Xml, Version=, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
  12:                 <add assembly="System.Core, Version=, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
  13:                 <add assembly="ListMonkey"/>
  14:             </assemblies>
  15:         </compilation>
  16:         <authentication mode="Windows"/>
  17:         <customErrors mode="Off"/>
  18:         <httpModules>
  19:             <clear/>
  20:         </httpModules>
  21:         <trust level="Full"/>
  22:     </system.web>    
  23: </configuration>

That is really all the config you need for the application to run, however don’t forget the config for Slide.Show to run we looked at in parts 1 and 2.

Next up is briefly looking at how the application works. Firstly override render method of the ASP.NET page. In there I do a lot of validation of the inputs which are provided in the query string. This is also an opportunity to set defaults if certain values are not provided. Next, and very importantly, I set the output to be text/xml (this tells the client, in our case JavaScript what to expect). To do this I do:

   1: Response.ContentType = "text/xml";

Then I call the lists web service of SharePoint which returns the results, which are parsed and rendered to XML (I am unfortunately using XMLNode still when I wrote this, instead of the beautiful XElement stuff… but I digress) and to the screen using:

   1: Response.Write(outputDocument.OuterXml);

This XML is in the format Slide.Show expects and so it’s configuration system we setup last time can just use it! All of this gives us a real time integration into SharePoint with Slide.Show!!! :)

As promised the files are available for download. It has occured that the download gets corrupted for some reason, if that is the case I recommend using this download, which is compressed with 7-Zip. NOTE: I have not tested this beyond my own simple tests and your mileage may vary. If you have problems please post a comment here I and will respond.

The files also include the source if you are interested to see what late night coding after months of no coding produces (may not be my finest work… looking over it as I wrote this I felt the need to refractor grow).

Blog Aggregator for SharePoint

Submitted by Robert MacLean on Wed, 10/22/2008 - 15:33

The new S.A. Architect site has some dynamic content on the home page, namely the S.A. Architect Community Leads section and the S.A Architect Events section which both use this cool web part from Zlatan, which in a nutshell allows me to specify a number of RSS feeds and a tag to filter on and displays the content. This means that the community leads do not need to cross post or post twice when they produce content for the site. They simply need to make sure they have the right tag associated and the post will appear. This also means that content that is no relevant to SA Arch does not appear. Very cool stuff and big thanks for Zlatan for it.

WSS and audience targeting - Part II

Submitted by Robert MacLean on Wed, 10/08/2008 - 19:36

Today is NOT my day for things just working. Besides the demo gods eating every demo I did today and presenting me with excrement to work with, I found out that the super cool WSS audience targeting is broken on every browser except IE :( There is no use in complaining so silver lining is that I do get a chance to solve the problem and learn something new about browsers.

First off is that XmlHttpRequest is supported by all browsers, the XML DOM implementation is not compatible so even though you can get the data you can’t work with it easy. The cause is that Firefox or Chrome do not support selectNodes or selectSingleNodes methods or IE has unique methods which no other browser supports (depending which camp you are in). selectSingleNode is what I use to parse my results! To solve this I found some code at which adds the methods to the JavaScript classes! This is great in theory but it didn’t work because I have a default namespace being returned by my XML! The code I found didn’t work as selectSingleNode always returned null because it needed the namespace prefix on the XPath (i.e. /default:user) which IE can’t work with. So that meant not only implementing a new resolver which I found out about on, it also meant doing a check and doing two XPath queries.

Something I didn’t mention in the first post is security and how secure or insecure this method is. Your biggest attack vector on this is that it runs client side and that the LoadXmlDoc method or even just the length check on the username can be changed easily so that it shows the content for logged in users to users who are not logged in! Basically it is not secure, but it doesn’t mean it opened a security hole because so you need to think about what is shown.In my case I made sure what is show is the bare minimum, just links to other pages. If an attacker gets the link they shouldn’t it does not worry me because the change password page, which signed in people can click to, is protected by WSS’s security. So even if someone were to try and access it they would get denied! The page itself also has security on it to help prevent security issues. The point I want to emphases is that this is NOT a security model, but a model for a better user interface. 


<script type="text/javascript">
    // Created by RMacLean - for comments email
    // Partially from
    // Partially from
    // Partially from
    // Partially from
    // check for XPath implementation
    if (document.implementation.hasFeature("XPath", "3.0")) {
        // prototying the XMLDocument.selectNodes
        XMLDocument.prototype.selectNodes = function(cXPathString, xNode) {
            if (!xNode) { xNode = this; }
            var oNSResolver = document.createNSResolver(this.ownerDocument == null ? this.documentElement : this.ownerDocument.documentElement);
            function resolver() {
                return '';
            var aItems = this.evaluate(cXPathString, xNode, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
            var aResult = [];
            for (var i = 0; i < aItems.snapshotLength; i++) {
                aResult[i] = aItems.snapshotItem(i);
            return aResult;
        // prototying the Element
        Element.prototype.selectNodes = function(cXPathString) {
            if (this.ownerDocument.selectNodes) {
                return this.ownerDocument.selectNodes(cXPathString, this);
            else { throw "For XML Elements Only"; }
        // prototying the XMLDocument.selectSingleNode
        XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode) {
            if (!xNode) { xNode = this; }
            var xItems = this.selectNodes(cXPathString, xNode);
            if (xItems.length > 0) {
                return xItems[0];
            else {
                return null;
        // prototying the Element
        Element.prototype.selectSingleNode = function(cXPathString) {
            if (this.ownerDocument.selectSingleNode) {
                return this.ownerDocument.selectSingleNode(cXPathString, this);
            else { throw "For XML Elements Only"; }
    // Provide the XMLHttpRequest class for IE 5.x-6.x:
    if (typeof XMLHttpRequest == "undefined") XMLHttpRequest = function() {
        try { return new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch (e) { }
        try { return new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch (e) { }
        try { return new ActiveXObject("Msxml2.XMLHTTP") } catch (e) { }
        try { return new ActiveXObject("Microsoft.XMLHTTP") } catch (e) { }
        throw new Error("This browser does not support XMLHttpRequest.")
    var xmlhttp;
    function loadXMLDoc(url) {
        xmlhttp = new XMLHttpRequest();
        if (xmlhttp != null) {
            xmlhttp.onreadystatechange = state_Change;
  "GET", url, true);
        else {
            alert("Your browser does not support XMLHTTP.");
    function state_Change() {
        if (xmlhttp.readyState == 4) {// 4 = "loaded"
            if (xmlhttp.status == 200) {// 200 = OK
                var username = "";
                if (xmlhttp.responseXML.selectSingleNode('//user') == null) {
                    username = xmlhttp.responseXML.selectSingleNode('//myns:user').getAttribute('username');
                else {
                    username = xmlhttp.responseXML.selectSingleNode('//user').getAttribute('username');
                if (username.length > 0) {
                    // user logged in
                    document.getElementById('resultText').innerHTML = '<P><A href="/memberPages/changepassword.aspx">Change Password</A></P>';
                else {
                    // anonymous
                    document.getElementById('resultText').innerHTML = '<P><A href="/Pages/signup.aspx">Signup</A><BR><A href="/Pages/forgotpassword.aspx">Lost Password</A></P>';
            else {
                alert("Problem retrieving XML data");
<span id="resultText">Loading...</span>

Podcasting Kit for Sharepoint + Sub Site = It can be done

Submitted by Robert MacLean on Mon, 10/06/2008 - 23:03

Recently I aged about a hundred years due to my intension to deploy the August 2008 release of the Podcasting Kit for SharePoint on a sub site due to the fact that there is so much hard coded into it (you can vote on that link for the work item to be done to fix this) that expects it to be at the root. Being stubborn and trying to show my elite SharePoint skills to all around me, I did not let little things like hard coding values stop me. No, I gave up a few years of my boyish good looks to get it working and in the end I did :) It’s not elegant but it works and should tide you over until the fixed release comes along.

First off let me say how great the August release is compared to the July release, it’s great. I actually don’t think you could’ve got this to work on the July release, there is that much cleanup and streamlining in it. One of the things they did was streamline the documentation from a monolithic single beast to a lot of smaller edible chunks. This is also a double edged sword for first timers because it means you go through the install doc and think you are done… when you aren’t, but I shall cover that later on.

For the tale assume the following facts:

  • SharePoint is deployed to a site available at http://intranet
  • We want the Podcasting kit to be available at http://intranet/sites/multimedia
  • I have created a life jacket file which contains versions of all the files I changed and may be of use to you. Note I have not tested it so it may not work. Best case is a simple find and replace and upload and you are in business, but worst case you need to follow the steps to get your files done. Download the life jacket file HERE
  • I am insane and this could all be wrong and my mind has made me believe it works.

Now I want to tell my tale of heroism at defeating bugs so that future crazy people don’t need to do this themselves. If you have the August 08 install guide and are following along (good idea, since that’s what I am doing to write this) I assume you have done your prerequisites and have a site collection as a sub site (i.e. http://intranet/sites/multimedia) and are at Installation Method #1 (Easy Method). Easy method that in itself should be the sign of the devil which awaits, because anything labeled easy never is. What you need to do is run the install to the root site (i.e. ssm.exe install PKSFull.xml http://intranet) and then uninstall it (i.e. ssm.exe uninstall PKSFull.xml http://intranet). I know it seems pointless but the installer doesn’t clean up well and leaves a few files behind (The key stuff it leaves is CSS’s, XSL’s and some JS files), and having these files at root helps us later on. Now run the installer again but now to your site collection (i.e. ssm.exe install PKSFull.xml http://intranet/sites/multimedia).

The next steps in the guide of the ratings DB, media encoder and feature activation work as documented. The user interface steps also work as expected but make sure you “fix” their links to have your site collection. So for a few examples:

  • SmartPhone access make the URL /sites/multimedia/mobilepages/pksmobilehome.aspx
  • Upload Podcasts make the URL: /sites/multimedia/PKS Podcasts/NewForm.aspx?RootFolder=%2FPKS%20Podcasts&Source=/sites/multimedia/pages/pkshomepage.aspx

a1Moving swiftly along the master and welcome pages instructions should work fine and that leads us to the first big hurdle the SmartPhone page because this is where the hard coding comes in. See the PKS uses a special web part called the Content Query Override web part, which is like the out of the box Content Query web part but allows you access to all the properties you couldn’t normally get to. However the PKS team set these up on their side and when you import it you are assured of doom and destruction if you are on a sub site. One of the properties that is hard coded is the path to the web URL for the site.  If you simply open the pksmobilehome.aspx page, find the weburl tag and change it to be your site path (in my case /sites/multimedia) prior to uploading the file, as per the document, you will be fine and continue through the document happily following the sections on Profiles, Silverlight 2.0, Rating and Commenting, External File Store, and Media Encoder Service to bring yourself merrily to the Pages section.

Before heading into the pages section we need to fix up the XSL files so they point correctly. You can find these in All Site Content –> Style Library –> XSL Style Sheets. Best is to switch to explorer view get all the files out of there and open them all up in text editor which allows Find & Replace across multiple files (I used Visual Studio, how developer of me) to fix the URL’s up. There are hundreds of the URLs so I suggest doing find and replace to fix it. As I said earlier all changed files are in the life jacket file, which includes these. It may be easier to use mine since you just need to search for /sites/multimedia and replace it with what ever your URL is. Use it, don’t use it, whatever. Once done re-upload the files and then make sure you check each file in as a major version.

The reporting page works great but you will find you are stuck at the podcasterdetail.aspx page because you can’t actually get to those settings. Once again this has to do with the fact that this web part is the content query override webpart. This one is a little worse than the mobile page because it has been pre-configured and is incorrect. To solve it, prior to editing the settings export the web part and save it to disk then open it up in your favorite text editor and make sure all the paths are correct, those being:

  • ItemXslLink
  • WebUrl
  • MainXslLink
  • ItemXslLinkOverride
  • MainXslLinkOverride
  • Xsl

Once you have done that you can upload the web part (either to the web part gallery or direct on the page) and you should be able to work with it successfully now.

Moving to the podcastdetail.aspx make sure you set the URL correct for the Xslt Override Location on the Content Rating-Review Results web part. You can/should skip the 9 to 15 (about the content editor web part which shows the edit link) since it references a JS file I have yet to be able to find and fix so it will point to the wrong URL and it will not work. If you do fix this please let me know. Setting up the web connections on the page should be fine and so should the search. If you do not have the metadata properties, like in my case, please read the troubleshooting guide. It’s likely you assumed too much and thought life was easy… easy install and all ;)

That should take you to the end of the guide, but not the end of the of our tale. If you recall I mentioned the double edged sword of splitting the documentation well the next step is not obvious. You should now go through the How To Apply Security Settings file and follow that because if you don’t you will have lots of crap. You should also be aware of a bug in the PKS which can prevent any non-admin like people from viewing/downloading content see here for details on that.


a3Right, now that the security is sorted we can get back to getting the site working as a sub-site. The next step is to fix the configuration so go to All Site Content and go to Content Rating Configuration Settings. You were here earlier and find the item you copied from before (the one that is a GUID@GUID) and make sure the value points correctly. Now head back to All Site Content and go to PKS Configuration Settings and set the various values in their to point to the correct URLs, this includes:

  • DownloadTracking.Location
  • ErrorHandling.InvalidMediaFile.Image
  • ErrorHandling.NoVideoStream.Image
  • Thumbnail.Custom.Images (not you have multiple URL’s in the value here, make sure you get them all).


Now you have the main page pkshomepage.aspx which suffers from the same issue as the podcasterdetail.aspx page in that the content query override webpart is incorrectly configured. You can follow the same procedure as before (export, edit, upload) to solve it.

At this point everything should look like it works fine, but there is a bug lurking under the covers. Anytime anyone watches a video it will increment the download count which is stored on the file entry in the PKS Podcasts list, this update of the list item causes the File URL to change and even though originally it pointed correctly to /sites/multimedia/_layouts/MSIT.customfiles/Download.aspx?…  it gets updated to point to the root site again, in other words /_layouts/MSIT.customfiles/Download.aspx?…

Before: a4

After: a5

I am not sure all the circumstances around the bug (it doesn’t seem to effect admins). To solve this I wrote a quick ASP.NET page which will redirect requests back to the correct URL, the file is in the life jacket file and is called downloads.aspx. Now if you have a different sub site path (i.e. not /sites/multimedia like me) then you need to open that file up in a text editor and change the URL as needed.


Important Notes:

  • YOU DO NOT NEED VISUAL STUDIO FOR THIS. The file is a single ASPX page with the code in it, the server will compile automatically at runtime.
  • The fact it points to a file called realdownload.aspx is correct.

Now get on to your SharePoint server (if you aren’t there already) and navigate to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\template\layouts\MSIT.CustomPages. This folder should have a single file called download.aspx, which you will rename to realdownload.aspx and copy the download.aspx file from the life jacket file into this folder. So all requests will hit the custom file which will redirect them back to the correct file. This should fix up the issue caused by the bug.

Now finally at this point you are actually done! You can now go through the documents on workflow and series and get all your content up and (hopefully) enjoy your Podcasting kit!

I want to thank a few people who helped me along in getting this right namely Michael Gannotti, Zlatan Dzinic, and of course the PKS team who responded to my posts on the site!