There are 2 ‘features’ in SharePoint (MOSS2007) which have kept me busy for quite some time in my last project. Yes, you’ve read it right the first time, my latest project was a MOSS 2007 web portal. Of course these issues aren’t really quirks as the product behaves by design, but it has kept me busy for more time as I would bargain for.

First quirk:

For some reason I had to create a console application to query the SharePoint user list and delete the users. Normally this doesn’t pose a problem at all. However, this time the following error was thrown every time:

The Web application at http://your-website-here:80 could not be found. 
Verify that you have typed the URL correctly. 
If the URL should be serving existing content, 
the system administrator may need to add a new request URL mapping to the intended application.

Quite strange, as the website does exist, I even double checked it.

After doing some research on the matter it turns out you need to specify the Platform target for your application. Mine was set to Any CPU and had to be changed to x86. After changing this specific option the code was running correct.

image

Second quirk:

The other thing I ran in to was not having permission to do anything on my site collection. We were using the stsadm export and stsadm import commands to move SharePoint site applications between environments.

This means I was familiar with setting the proper permissions on the web application and site collection. However, this time it didn’t work. After having spent several hours on this problem I finally noticed a feature which I had never seen before. Apparently you can set a site lock when doing an export on a website. This makes sense as you don’t want your data to change much when doing this.

However, after doing an import, you also need to remove the site lock. If you fail to do so, no one can make changes to the content of the website. To fix this, you can use the stsadm command, like so:

stsadm -o setsitelock -url http://your-website/ -lock none

The full documentation can be found on MSDN/Technet. You can also check the current site lock with the getsitelock operation.

Because I’m a developer who loves a GUI I’ve also found the option in Central Administration. Navigate to the Application Management tab and search for the Site collection quotas and locks.

sp_sm

On this page you can select your site collection and set the lock status for it.

sp_quotas_locks

After setting it to the status Not locked and you press OK, your site should be editable again.

Even though this post references some prehistoric software platform, I do hope you find it useful.

Aan mij was de taak om een applicatie te schrijven welke informatie van SharePoint (Wiki sites) website kon wegschrijven naar HTML bestanden met een bepaalde opmaak.

Niks aan de hand, ware het niet dat ik op m’n Windows 2008 VM zowel MOSS 2007 als Visual Studio 2010 had geïnstalleerd. Bij het toevoegen van de benodigde references kwam ik er ineens achter dat ik de SharePoint 2007 DLL’s niet kon vinden in de lijst. Het is ook een bekend ‘probleem’, aangezien het ook op Connect staat geregistreerd als issue. Er staat ook dat het probleem is geëscaleerd naar het betreffende team, maar dat was al op 20 november 2009. Jammer dat dergelijke calls dan niet verder worden bijgewerkt, want blijkbaar is het antwoord gewoon ‘zoek het lekker zelf uit’.

Gelukkig kan ik dat ook prima zelf uitzoeken.
De dll’s staan namelijk gewoon in de map C:\Program Files\Common Files\Microsoft Shared\Web Server Extenstions\12\ISAPI. Door de Browse knop te gebruiken bij het Add Reference scherm kan dan gewoon, net als vroeger, de betreffende dll worden geselecteerd, bijvoorbeeld Microsoft.SharePoint.dll.

Het werkt dan allemaal prima, maar is wel jammer dat dit niet standaard wordt ondersteund. Het is al erg genoeg dat we met Visual Studio 2008 ook al niet met SharePoint 2010 kunnen werken.

Sinds gisteren draait m’n weblog niet meer op SharePoint (WSS3.0), maar op het nieuwe .NET CMS genaamd Orchard. Het lokaal installeren was heel eenvoudig met WebMatrix. Na installatie kon ik gelijk aan de slag met het systeem. Moet zeggen dat het allemaal goed in elkaar steekt en behoorlijk gebruikersvriendelijk is. Installeren van verschillende modules en thema’s kan met 1 klik worden gedaan in de web interface. Dat is wel even wennen als je van SharePoint af komt. Daar moet je eerst allerlei packages installeren, configuraties instellen, etc.

Tot nu toe ben ik dan ook behoorlijk tevreden over het geheel.

Wat wel vervelend is, is dat er momenteel alleen een import (en export) kan worden gedaan met het BlogML formaat. Op zich mooi dat die functionaliteit wordt aangeboden, maar zelf vond ik het nogal lastig om hier even snel een export voor te maken vanuit SharePoint. Het verkrijgen van de posts, comments en overige zaken is wel prima te doen, echter moet het dan ook in het valide BlogML formaat worden geplaatst. Dit is op zich ook prima te doen, maar ben er halverwege maar mee gestopt omdat ik teveel zaken onduidelijk vond. Heb alles dus maar ge-copy-paste. Het is iets meer werk, maar zo’n 300 posts zijn nog prima te overzien. Gelukkig heb ik weinig tot geen comments, waardoor eigenlijk alleen de posts over moesten.

Afgelopen week was ik aan de slag met het ontwikkelen van een export applicatie voor een bepaalde Wiki website binnen SharePoint. De bedoeling was dat alle inhoud van de Wiki site als HTML en XML moest kunnen worden geëxporteerd om zo te kunnen gebruiken in andere systemen.

Een dergelijke applicatie ontwikkelen is inmiddels geen probleem meer en ging dus ook aan de slag zonder de code continu te testen. Pas toen ik dacht klaar te zijn kreeg ik een foutmelding bij het openen van de SPSite, iets als (code kopie van StackOverflow)

System.IO.FileNotFoundException : The site http://website/ could not be found in the Web application SPWebApplication
Name=SharePoint - 80 Parent=SPWebService.
at Microsoft.SharePoint.SPSite..ctor(SPFarm farm, Uri requestUri, Boolean contextSite, SPUserToken userToken)
at Microsoft.SharePoint.SPSite..ctor(String requestUrl)

In de gelinkte post van StackOverflow staat ook gelijk wat het probleem is.

Het probleem bij mij was namelijk dat de geïnstalleerde Sharepoint 2007 versie 64-bits was. De console applicatie (en later de WPF applicatie) werd gebuild als een 32-bits assembly. Blijkbaar mag een 32-bits assembly niet met een 64-bits Sharepoint praten. Als je er over na gaat denken, klinkt dat ook wel logisch, echter had ik er op dat moment nog niet bij stil gestaan.

Dit geldt trouwens alleen maar voor externe applicaties. Wanneer je een webpart, feature, timerjob of iets anders maakt dat 'in' SharePoint werkt, dan geldt dit probleem niet. Bij gebruik van WSP Builder moet dan wel de 64-bits cablib worden gebruikt, waarschijnlijk om dezelfde reden als die ik nu zelf heb ondervonden.

Het standard menu van Sharepoint 2010 is op zich prima voor interne sites, echter bij een publieke website wil je hier wel het een en ander aan styling toepassen. Het standaard menu uit Sharepoint 2007 is gelukkig helemaal verbeterd en is tegenwoordig een stuk beter te stylen.

Het menu wordt gedefinieerd als een SharePoint:AspMenu. Dit is eigenlijk gewoon een asp:AspMenu met enkele uitbreidingen voor Sharepoint. Je kunt hier zelf niet van overerven, aangezien het een sealed class is. Er zijn her en der wel oplossingen te vinden waar men uiteindelijk toch in staat is geweest om de code van het menu over te erven. Wanneer er alleen wat gestyled moet worden is dat niet direct nodig, hoewel ik denk dat het toch wel handig kan zijn.

Omdat je eigenlijk werkt met een asp:AspMenu, kun je dus ook je eigen templates maken. Van onze designer had ik de opdracht gekregen dat het menu als hieronder moest worden gerenderd:

<ul class="">
	<li class="selected_menu_item"><a href="/default.aspx" class="link">home</a> </li>
	<li><a href="/Pagina/zwanger.aspx" class="link">zwanger</a> </li>
	<li><a href="/Pagina/baby.aspx" class="link">baby</a> </li>
	<li><a href="/Pagina/peuter.aspx" class="link">peuter</a> </li>
	<li><a href="/Pagina/schoolgaand_kind.aspx" class="link">schoolgaand kind</a> </li>
	<li><a href="/Pagina/puber.aspx" class="link">puber</a> </li>
	<li><a href="/Pagina/jong_volwassene.aspx" class="link">jong volwassene</a> </li>
</ul>

Tijdens m'n ASP.NET tijd had ik al geleerd dat je in het asp:AspMenu gebruik kunt maken van het ItemTemplate blok. Het enige dat ik hoefde te doen is de header en footer (de UL-elementen) boven en onder het menu te plaatsen.

Uiteindelijk is er deze code uit gekomen:

<ul id="main_menu_ul" class="">
	<sharepoint:aspmenu id="TopNavigationMenuV4" runat="server" enableviewstate="false"
		datasourceid="topSiteMap" accesskey="<%$Resources:wss,navigation_accesskey%>"
		usesimplerendering="true" useseparatecss="false" orientation="Horizontal" staticdisplaylevels="1"
		maximumdynamicdisplaylevels="1" skiplinktext="" cssclass="s4-tn">
		<StaticSelectedStyle CssClass="selected_menu_item" />
			<StaticItemTemplate>        
				<li>            
					<a href="<%# DataBinder.Eval(Container.DataItem, "DataPath") %>" class="link">            
						<%# DataBinder.Eval(Container.DataItem, "Text") %>
					</a>
					</li>    
			</StaticItemTemplate>
	</sharepoint:aspmenu>
	<sharepoint:delegatecontrol runat="server" controlid="TopNavigationDataSource" id="topNavigationDelegate">    
		<Template_Controls>        
			<asp:SiteMapDataSource ShowStartingNode="False" SiteMapProvider="SPNavigationProvider"
			id="topSiteMap" runat="server" StartingNodeUrl="sid:1002"/>        
		</Template_Controls>
	</sharepoint:delegatecontrol>
</ul>

In principe is dit precies wat ik wilde. Alle menu elementen in een li-element stoppen en dat alles in een ul-element.
Bij het bekijken van de pagina leek alles ook goed te gaan, afgezien van een jQuery functie. Bij nadere inspectie van de broncode kwam dit omdat het Sharepoint:AspMenu zelf allerlei elementen aanmaakte met 'nuttige' informatie, hier kon de jQuery functie niet tegen. Omdat het ook niet netjes is om een verschillende elementen binnen een ul-element te hebben moest er dus iets anders worden ontwikkeld.

Omdat je niet een header- en footer template kunt definiëren met een AspMenu kon ik dit eigenlijk al niet meer gebruiken. Gelukkig bestaan er meerdere ASP.NET controls waar gebruik van kan worden gemaakt wanneer je een datasource hebt, zoals een asp:Repeater.

Met een asp:Repeater kun je wel een header- en footertemplate definieren en levert geen onnodige tabellen of andere elementen op. Nadeel van de repeater is wel dat het lastig is om meerdere niveaus te definiëren.

In dit specifieke geval is het niet zo'n enorm probleem dat er maar 1 niveau kan worden gebruikt, omdat er meerdere menu's onder elkaar komen te staan, welke dus allemaal hun eigen asp:Repeater kunnen gebruiken met een eigen datasource.

De code die ik gebruik voor het vullen van het menu is als volgt:

<asp:Repeater ID="TopMenu" runat="server" DataSourceID="cjgSiteMap">
	<HeaderTemplate>
		<ul id="main_menu_ul" class="">
	</HeaderTemplate>
	<ItemTemplate>
		<li><a href="<%# Eval("Url")%>" class="link">
			<%# Eval("Title")%></a></li>
	</ItemTemplate>
	<FooterTemplate>
		</ul>
	</FooterTemplate>
</asp:Repeater>
<asp:SiteMapDataSource SiteMapProvider="CombinedNavSiteMapProvider" ShowStartingNode="false"
	StartFromCurrentNode="false" StartingNodeOffset="0" StartingNodeUrl="sid:1002"
	EnableViewState="true" ID="cjgSiteMap" runat="server" />

Bij de submenu's gebruik ik gewoon een StartingNodeOffset die hoger is, of een van de andere navigation providers welke beschikbaar zijn binnen Sharepoint, een overzicht van 2007 is hier te vinden: http://ktskumar.wordpress.com/2008/04/14/sharepoint-navigation-providers-part-1/ (deze werken over het algemeen ook in Sharepoint 2010).

Het resultaat is het onderstaande voorbeeld:

Ik ben nu blij dat het AspMenu niet naar behoren werkte, aangezien er nu een veel mooiere oplossing is geïmplementeerd voor deze website.