Thursday, 9 July 2009

Joel Oleson at the Perth SharePoint User Group

After a great showing from Greg Low last month, the Perth SharePoint User Group boys have pulled SharePoint superstar Joel Oleson on his way home from the NZ Community SharePoint Conference 2009.

Joel’s presentation is “Preparing for Upgrade to SharePoint 2010.” Here’s some pre-reading: http://www.sharepointjoel.com/Lists/Posts/Post.aspx?ID=238

This promises to be the local SharePoint event of the year so get your RSVP into SharePoint Sezai via the user group web site if you haven’t already and block out 12:30pm in your calendar!

Wednesday, 8 July 2009

YSlow for Firefox 3.5 Lives?

YSlow has been the tool for measuring page payload and providing the metrics you need to optimise web site performance beyond the web server. Shock horror when I recently upgraded Firefox to version 3.5 and couldn’t install YSlow.

Initial rumours confirmed the current version of YSlow doesn’t work with FF3.5 but also suggested development by Yahoo! had ceased. Meanwhile Google launched Page Speed—a likeable YSlow competitor (maybe?).

A recent posting from a Yahoo! dev would suggest YSlow will actually be updated but “the team has run into some integration issues with firebug 1.4.” If you want to install FF 3.x and 3.5 side-by-side, check out this guy’s article.

Monday, 6 July 2009

New Sites, New Widgets

Rottnest Island Authority Re-launch

The second-last site to be launched Home - Rottnest Islandon our fully branded, MOSS-based site provisioning platform went live last Thursday; I reckon it’s one of the best looking sites we’ve ever launched (the Rottnest Island photography helps, of course). Check it out: http://www.rottnestisland.com

Open Booking Exchange

On the subject of all things new, we’ve also launched a new online booking capability on westernaustralia.com. The system integrates with our existing search function and provides live availability information from V3’s Open Booking Exchange. The politics around this apparently simple change were massive; the technology side is relatively straightforward by comparison (web service calls from within SQL Server are as complex as this got from our end). If you’re a tourism operator, find out more.

Travel Planner

WACOM Travel Planner

We’ve also finally launched the online travel planner after nearly a year of work with a Sydney-based agency (who shall remain nameless). Luke was our man on the ground with this one and he did a great job integrating this things again and again and again.

The travel planner “helps visitors collect, organise and share their WA travel itineraries.” You can sign up from the westernaustralia.com homepage and add items from across the site to your travel wallet.

Sunday, 28 June 2009

SharePoint and SQL Server with Greg Low at PSPUG

Sezai’s been doing a fantastic job of attracting some high-end speakers to the Perth SharePoint User Group and we had the immense pleasure of attending Greg Low‘s presentation on SQL Server optimisation for SharePoint admins this month.

Greg is a god among men in my mind and one of those can’t-miss speakers; apart from being a SQL Server MVP and Microsoft Regional Director, he really knows his stuff and delivers a nuanced presentation. I’d seen Greg in Adelaide on previous occasions and since he’d made his way all the way to Perth just for us, there’s no way I’d miss him.

There were some key take-aways from Greg’s talk I’m paraphrasing here for future reference… note I’m not a DBA and don’t necessary understand all of this—in other words, don’t apply this advice blindly without additional research!

  • The autogrow settings should be configured appropriately on both content databases and the tempdb—the SQL Server defaults are inappropriate. In general, this means turning off autogrow and managing database file size manually. Alternatively, autogrow can be left enabled for contingency but should be reconfigured to grow using an appropriate value (in MB, by ~100MB).
  • tempdb is rebuilt to the configured autogrow value every time the sqlserver process restarts; the start value should be large enough to avoid file system fragmentation.
  • Never, ever auto shrink a SharePoint database as it will only have to regrow again and may increase fragmentation.
  • Use DBCC CHECKDB but beware fixing problems may incur data loss.
  • Whack your disk subsystem using benchmarking utilities like SQLIO and Iometer. Reasonable latency falls between 5-15ms, for example.
  • Instant file initialisation allows SQL to write to files that have not been zeroed out by the OS, thereby avoiding the performance hit incurred by that activity. The MSSQLSERVER service account must be granted the SE_MANAGE_VOLUME_NAME right by virtue of being added to the Perform Volume Maintenance Tasks security policy.
  • Multiple HBAs can lead to write ordering and disk subsystem issues; SQL Server 2005 introduced page checksums to help with this issue but the feature is turned off by default; it should be enabled.
  • Virtualising database servers faced a lot of bad press in the past but those days are behind us. Hyper-V R2 and ESX are the way forward.
  • Don’t even think about SQL Server 2000.
  • The gap between SQL Standard and Enterprise is getting wider with SQL Server 2008.
  • As most SQL Server instances are disk and memory-bound, consider enabling table/row/page compression in 2008 to reduce IO and memory usage at the expense of CPU. You mileage may vary as this will obviously depend on the content to be stored as photos and Office documents are already compressed. Backup compression is also possible.
  • Configure databases with one file per CPU core.
  • Different databases have different IO profiles; tempdb should be hosted on a dedicated spindle (see http://technet.microsoft.com/en-us/library/cc262731.aspx for more info about locating the various SharePoint databases).
  • Ensure statistics are configured correctly.
  • Index fill factor should typically be ~70% for a typical SharePoint environment.
  • The default Windows Server 2003 sector size is too small; set it to 64k when formatting drives.
  • Clustering SQL won’t boost performance like mirroring will. Clustering happens at the server level whereas mirroring must be configured for every database.
  • If configuring a SQL alias, use TCP/IP.
  • Create a separate SQL Server instance if an existing database server’s collation doesn’t match SharePoint’s specific requirements. Changing an incorrect collation is a lot of work.

Wednesday, 24 June 2009

Can’t reinstall Flash after failed v10 update

The silly Flash player failed to update in IE8 the other day; clicking the Get Flash link would take me to the installer page but the “gold bar” would never appear for me tell IE to download and install the player.

Chrome and Firefox are easier to deal with as the Flash plugin is installed through Add/Remove Programs.

Although forum reply suggested resetting IE fixed the problem for him I’m not that kind of guy ;-). For the record, Tools > Internet Options, Advanced tab and click the Reset… button.

In my case I resolved the problem by running the Flash uninstaller from the Flash Player Support Center

http://kb2.adobe.com/cps/141/tn_14157.html

The MOSS setup account must be a member of db_owner role of the content database

One of the first things I normally do after creating a new web application and site collection is backup the content database using stsadm -o backup. If you're running in a least privilege scenario, however, there's an extra step required to configure access to the content database.

Whenever I'm working interactively with MOSS in an administrative capacity, I'm logged in as the MOSS setup account. This is the account used to install MOSS and create the farm; it’s also a member of the local admin and WSS_ADMIN_WPG groups, a member of the Farm Administrators group, and I've even got it configured as the primary site collection administrator for my content databases. In general, this account gives me the permissions I need to do everything I need to do while keeping my MOSS install functional.

Despite the wealth of permissions granted to this account, I was surprised when I tried running the stsadm -o backup command and came up against this error:

Cannot open database "WSS_Content_APP" requested by the login. The login failed.
Login failed for user 'domain\moss_setup'.

A similar, dodgier message was echoed in the Application event log.

To work around this, the setup account must be added to the db_owner role of the content database being backed up:

Navigate to the {WSS_Content DB}\Security\Roles\Database Roles\db_owner role and view its properties
Add the Setup account (eg. domain\moss_setup) as a Role Member

I've found no other role will suffice. Note in a least privilege scenario, the setup account should not be a member of the local admin group on the database server.

I'd love to know how to do this automatically whenever a new content database is added although I can understand why MOSS doesn’t do this for me… sort of ;-)

Database not found

While attempting to run the stsadm -o backup command as the MOSS setup user for the first time in a new environment today, I came across an error message in the application event log:

Event Type:    Error
Event Source:    Windows SharePoint Services 3
Event Category:    Database
Event ID:    3760
Description:
SQL Database 'WSS_Content_APP' on SQL Server instance 'MOSSSQL' not found. Additional error information from SQL Server is included below.

Cannot open database "WSS_Content_APP" requested by the login. The login failed.
Login failed for user 'domain\moss_setup'.

I wasn't careful when I first read the message and only read the first line. As MOSSSQL is actually a SQL Server alias to a physical server and this is the first time I've used aliases, I initially wondered if the backup command or stsadm was unable to deal with alias. That's silly, of course, because I've never told MOSS which physical server is underlies the alias and it only knows about the alias.

I'm not sure exactly how MOSS and SQL together track down the WSS_Content_APP database but the crux of this error message lies in the second part as flagged by SQL Server. In my case, the moss_setup account required access to the content database--but that's another blog post.

MOSS Calculated Columns

The Microsoft Office Online site has some useful pages relating to calculated columns, formulas, and formatting in SharePoint. I can't help but wonder if this is yet another Microsoft pseudo-language but the reference may come in handy.

Sunday, 21 June 2009

Access is denied. Check that the Default Content Access Account has access to this content

I ran into this error in the crawl log for the Local Office SharePoint Server sites content source:

Access is denied. Check that the Default Content Access Account has access to this content, or add a crawl rule to crawl this content.

I had configured the default content access account within the search administration and granted Full Read access to the same account from Central Admin\Application Management\Policy for Web application; the site to be crawled also had an include crawl rule configured. As a test, I also added the default content access account to the [SiteName] Visitors group with no effect. Oddly enough, some of the site content was being crawled (well a single document anyway) but I just don’t like error messages ;-)

The environment in question is a Windows 2003 SP1 machine with MOSS 2007 SP2 and .NET 3.5 SP1. It’s a dev environment and it’s also configured with the Active Directory and DNS roles and runs SQL Server 2005 SP2. Site-wise, MOSS is hosting a single test site configured to use a host header on port 80 with a DNS A record pointing to 127.0.0.1. And therein lay the problem…

Apparently Windows 2003 SP1 introduces a “loopback check security feature […] designed to help prevent reflection attacks.”

http://support.microsoft.com/kb/896861

The KB article also describes two work arounds for the problem, the first being to list the host names mapped to the loopback address (127.0.0.1) and the second disabling the security check.

Method 1: Specify host names

Specify the host names that are mapped to the loopback address:

  • Click Start, click Run, type regedit, and then click OK.
  • In Registry Editor, locate and then click the following registry key:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0
  • Right-click MSV1_0, point to New, and then click Multi-String Value.
  • Type BackConnectionHostNames, and then press ENTER.
  • Right-click BackConnectionHostNames, and then click Modify.
  • In the Value data box, type the host name or the host names for the sites that are on the local computer, and then click OK.
  • Quit Registry Editor, and then restart the IISAdmin service.

Method 2: Disable the loopback check

  • Click Start, click Run, type regedit, and then click OK.
  • In Registry Editor, locate and then click the following registry key:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
  • Right-click Lsa, point to New, and then click DWORD Value.
  • Type DisableLoopbackCheck, and then press ENTER.
  • Right-click DisableLoopbackCheck, and then click Modify.
  • In the Value data box, type 1, and then click OK.
  • Quit Registry Editor, and then restart your computer.

Note: In my case this took effect without resetting the server; although other suggestions recommended restarting IIS, I didn’t have to do that either.

Thursday, 18 June 2009

SSP Access Denied

It's quite easy to be face with an Access Denied screen after creating a Shared Service Provider (SSP) but it's not always so easy to fix the problem.

In most cases, treat your SSP admin sites like any other SharePoint site and ensure the correct users have been granted the necessary access permissions (yoursite/ssp/admin/_layouts/settings.aspx and then People and Groups). You'll generally want to access the SSP site to configure these permissions using the account used to create the SSP in the first place; if that fails, try the account used to run the IIS app pool of the SSP admin site. If that fails, read on...

Before diving in I want to mention this issue has been covered before in various places with the most notable items being Faraz Khan's post; the post includes a plausible explanation of the problem provided by "Scott" in the post's comments. A social.technet thread also points to the same post and some some additional solutions are reported. When I encountered this problem I found both sources cumbersome to wade through and difficult to decipher so I'm summarising the steps I took to fix the problem.

Also, a disclaimer of sorts. SharePoint and MOSS are finicky beasts so while the solution described below may seem to work, I expect a better solution would be to delete the problem SSP after creating a replacement and making it the default SSP (see below to find out what’s causing the problem before you recreate). I’m not certain the solution described won’t introduce new problems (but so far so good in the proof-of-concept environment I’ve built).

To setup, let's assume the following:

  • You've created a new SSP named Default SSP
  • As part of the SSP provisioning process, you've created a new SSP admin site with an app pool named Default SSP
  • The app pool of the SSP admin site account is configured to use the SSP_APP account
  • The SSP itself is configured to run as the SSP_SVC account
  • When you try to access the site using the account used to create the SSP, the SSP_APP app pool account, or the SSP_SVC service account, you receive an Access Denied error; you can however access /ssp/admin/_layouts/settings.aspx as the SSP creator
  • Inspecting the Default SSP app pool, you find the identity is set to run as SSP_SVC instead of SSP_APP as specified above. Changing the identity back to SSP_APP sticks for a few seconds but quickly reverts to SSP_SVC.
  • Nothing is reported in the event logs

According to legendary "Scott", the problem occurs because the application pool configured for use by the SSP's admin web application has the same name as the SSP itself (Default SSP). Apparently MOSS independently creates another app pool named after the SSP and running with the SSP credentials (SSP_SVC) for use by the “Office Search site”. The Office Server Web Services web site does have a child web application named Default SSP that is also configured to use the Default SSP app pool. It makes sense that since an app pool with the same name already exists, MOSS either recreates it or magically updates it on a scheduled basis.

To resolve the problem:

  • From IIS Manager, right-click the app pool intended for use by the SSP admin site (eg. Default SSP)
  • All Tasks -> Save Configuration to a File… and specify a location where you can easily find the output file
  • Open the saved .xml file in notepad and change the two references to “Default SSP” (or whatever you’ve named your SSP/SSP admin site account):
    1. The Location attribute of the IISApplicationPool element - change Default SSP to Default SSP App
    2. The Location attribute of the IISInheritedProperties element - change Default SSP to Default SSP App
  • Save the file
  • Right-click on the Application Pools folder in IIS Manager
  • New -> Application Pool (from file)...
  • Locate and select the file, click the Read File button, select the configuration, Ok
  • Configure the Default SSP web site to use the new app pool (Properties -> Home Directory tab, Application pool drop down)
  • Repeat for the /images and /inc applications below the _layouts child site (Default SSP/_layouts/Images, inc)
  • Reset IIS for good measure

You’ll now have two application pools, Default SSP and Default SSP App. Don’t delete the original as it’s still in use by Office Server Web Services web site and may get recreated anyway.

Wednesday, 10 June 2009

IE8 Slow to Load, Slow to Create New Tabs

I don’t use IE much ‘cause I’m a huge Chrome fanboy and Firefox is the obvious tool of choice for most things web dev. That said, with integrated authentication IE just works better with SharePoint and TFS to the point where I’m pretty much forced to leave it set as my default browser.

I had very high hopes for IE8 and the latest version of the IE Developer Toolbar; I now feel let down. Apart from the default install being horribly slow to load and create new tabs (I timed it around 8-9s), I’ve found the IE Dev Toolbar to be less intuitive and very ugly compared to the old standalone IE Dev Toolbar and of course Firebug.

The one thing I really love is the ability to force new windows and pop-ups into new tabs—again because of the way SharePoint won’t let you right-click/open in new tab when viewing a page and the TFS web interface sprawls new windows.

I’m on an ancient XP machine that sucks at everything so at first I thought the speed was just me. Googling “IE8 slow” however quickly pointed me to Ed Botts’ post that suggests registering a specific DLL and rebooting. I’m not alone after all, I thought to myself, and promptly registered the DLL and rebooted with no change.

I gave up for a while at that point until I came back to the issue today. Raphael’s post countering Ed Bott’s post, which I’d also read previously, is now full of comments suggesting different remedies. One particular comment suggested disabling add ons and Java in particular.

So I dove in and disabled all of my unused add ons, noting the load time value against the Java item. I imagine Doing so fixed the problems and I can load new tabs in roughly half a second.

IE8 Slow Java

I hate Java apps and generally have no need for the add on so I guess I’ll just leave it disabled. The same commenter mentioned also indicated updating Java to the latest version didn’t help.

It seems like each new IE8 tab fires off its own process so I can see how add ons would need to be loaded every time a new tab is created but compare the listed load time of 2.49s versus the others at 0.01s and it’s both shocking that IE will allow this to happen and Sun think they can get away with this.

Friday, 22 May 2009

Windows Memory Limits

Different versions and architectures of Windows support different limits on memory. http://msdn.microsoft.com/en-us/library/aa366778.aspx concisely describes those differences from Windows 2000 onwards.

Thursday, 21 May 2009

SharePoint on SharePoint – Under the Hood

The SharePoint Team Blog just announced they’ve launched the www.microsoft.com/sharepoint site on SharePoint itself with a large sprinkling of Silverlight. The post mentions the use of the publishing feature and SEO optimisation so I thought it would be interesting to see if I could find any really cool, secret WCM optimisations. I’m disappointed and can’t suggest modelling your own internet-facing MOSS site on this site :-(

  • Looking at the site URL alone I can tell this is a MOSS site: /pages/default.aspx. I was hoping to see the /pages directory magically vamoosed from the URL and I’d hardly say Default.aspx is SEO-friendly.
  • The total page weight, according to YSlow, is 538.5KB, which translates into a load time of 13.81s from Western Australia and a grade of F (despite waiting for the Silverlight banner to load the page load time didn’t feel too bad but reloading with an unprimed browser cache was sluggish but I have little doubt they’re running off a CDN)
  • The JavaScript and CSS aren’t minified and both init.js and core.css are loaded in their entirety.
  • The number of resources requested by the page is significant and there’s been no apparent effort to merge CSS and JS files
  • The page viewstate equates to 62KB of the overall page weight while another 68KB pertains to inline Silverlight load script stuff

The single neat-o thing about this site (let’s say apart from its content and this is a technical blog) is the way hitting the Login link or trying to hit /_layouts/settings.aspx redirect to the Live login form. It would be interesting to know if they’re actually using Passport authentication on this site.

Sunday, 17 May 2009

Run an internal URL hashing/redirect service with Google Short Links

Google Labs recently made the Google Short Links application available to the Google Apps platform. Short Links is a promising little feature that enriches the Apps system by allowing you to shortcut and/or hash URLs and serve those redirects directly from your Google Apps domain. As a useless example, checkout http://go.mediawhole.com/blog ;-)

Like most things with Google Apps when you’re running your own domain name, setting up is simply a matter of picking one or more hostnames and a creating a corresponding CNAME entry in your DNS server (see my post on how to get setup—it’s easy, I promise!). The choice of hostname is arbitrary; in my case I chose http://go.mediawhole.com and http://bookmarks.mediawhole.com. If you do add multiple hostnames note you still only have a single collection of short links. My line of thinking is to use go.mediawhole.com for public-facing redirection and bookmarks.mediawhole.com for private use.

In addition to creating short, hashed URLs for use in Twitter and other space-constrained applications (print articles/ads/etc), you can also create friendly URLs that may be easier for your visitors to remember. As an example, http://go.mediawhole.com/michael will redirect you to my Blogger profile. Short Links handles both internal and external links (links pointing to pages on your own domain and pages on external domains).

Link administration is simple through the UI: as you might expect, all you have to do is specify the short link and paste in the target URL; alternatively, just pop in the target URL and Google will generate a new hash. You can also make individual short links public or keep them private—presumably for use only by your logged on users. Obviously you need to be careful about deleting a link once it’s been created and published as redirection will be removed for that link and your users won’t end up where they expect—a nice enhancement would include the ability to configure a default short link for cases like this.

Google being Google you can of course search your short links and viewing the list of short links you’ve configured will specify a usage count for each link—providing some rough analytics.

Saturday, 16 May 2009

Starting with SharePoint for Administrators

Whether you’re a newbie admin holding together a one man shop or a seasoned technical veteran, when you find yourself lumped with rolling out Windows SharePoint Services 3.0 and/or MOSS 2007 do yourself a favour and read this brief white paper on some of the more important considerations:

The above paper is about twenty pages and it’s a quick read that should help you step forward on the right foot. If nothing else, each of the topics presented links to additional TechNet and MSDN material and the paper is a valuable index from that perspective.

Like it or not, effective administration is pivotal to the success of the entire project from the very beginning right through the support phase and beyond; seemingly harmless mistakes made during the initial install can lead to major long-term problems. Like everyone else “doing SharePoint”, generic Windows/SQL Server/ASP.NET experience will get you started but you’ll still be faced with a very steep learning curve, depending on what you’ve been asked to accomplish. Bear in mind the SharePoint paradigm will not always sit right with conventional experience and may clash with existing corporate IT policies. SharePoint will challenge and frustrate you on many different levels, while at times seeming to throw common sense out the window.

Re-learning everything you know now isn’t strictly necessary to build a SharePoint environment :-) but the size and power of the SharePoint ecosystem does require a massive, sustained learning effort that will increase your professional maturity very quickly.

At a minimum, beware administering SharePoint will cover:

  • Windows Server
  • Active Directory
  • IIS
  • ASP.NET
  • SQL Server
  • XML
  • SharePoint farm management
  • SharePoint Designer

From there, a “standard” WSS/MOSS rollout can involve:

  • Integration with LOB applications
  • Virtualisation
  • SAN management
  • Backup and restore
  • Content deployment
  • Load balancing
  • High availability
  • Database clustering
  • Reverse proxies/caches and content delivery networks
  • Security
  • SSL certificate management and distribution
  • Kerberos
  • Code access security
  • XSL, CSS, Javascript, C#, TSQL
  • Solution deployment
  • Remote debugging
  • Performance overhauls
  • Antivirus
  • SMTP
  • Exchange
  • InfoPath Forms
  • Excel
  • Office applications (Word, PowerPoint, Outlook, Project)
  • [Your technology here]
  • [This space for rent in 2010]
  • [What did I miss?!?]

I’ve watched great admins balk at the overheads and oddities required of a SharePoint deployment, moving through the various phases of shock (ignore), denial (disbelief), anger (hate), depression (confusion), and finally acceptance (hope—SP1?!, resignation). If you’re moving through one of these phases or have come out the other end (or you’ve already deployed SharePoint and are starting to realise what’s involved), read this paper.

Friday, 15 May 2009

Blocking SharePoint Designer from Accessing Your Site

In a recent TechEd discussion panel comment, my favourite SharePoint MVP Eric Shupps mentions the ability to block SharePoint Designer from connecting to a SharePoint server and modifying content.

Why is SharePoint Designer a bad thing?

  • It’s free; every man and his dog can download it, potentially install it, and potentially break your sites
  • It can potentially be used against production—which if you follow a regimented deployment process is all wrong as changes can be made any ol’ time
  • It customises (or ghosts, if you prefer) pages thereby severing the link between the artefacts you’ve conscientiously built into a solution package and featurised;  uncustomising these artefacts may not be possible, depending on the changes that were made, or you’ll need another way to fix things up.
  • Artefacts created by SPD are created in the content database and can’t be moved easily between environments (eg. from dev to UAT to prod)
  • It modifies your files and injects stupid attributes that only it cares about
  • It’s buggy and it sucks and crashes and it’s too complicated for business analysts and too wrong for developers and it’s FrontPage rebranded and so on.

Eric’s comment got me digging and I found this new tool on CodePlex that installs a feature allowing admins and content editors to disable access to a site using SPD. Although a site definition can be altered directly to limit access by SPD this won’t affect existing sites, can’t be unlimited at any point in the future using any obvious mechanism, and is all a bit weird.

No SharePoint Designer is implemented as an HTTP Handler so it doesn’t touch the content database or much of anything. It’s still early days but definitely a “watch this space” kind of effort.

An alternative tool uses AD groups to limit access and this approach uses group policy to simply block SPD from running (and this MSDN blog entry is comprehensive if nothing else!).

Resources:

http://www.msteched.com/online/view.aspx?tid=efa154e2-6c06-4a76-ab3c-e9d71ebf0ff2
http://nospd.codeplex.com/
http://support.microsoft.com/default.aspx/kb/940958
http://blogs.msdn.com/sharepointdesigner/archive/2008/11/25/locking-down-sharepoint-designer.aspx

Thursday, 7 May 2009

Collapsing multiple using statements

Multiple, nested using statements are extremely common when developing against the SharePoint API to ensure the various objects at work are disposed of correctly:

using (SPSite site = new SPSite ("http://server")){
using (SPWeb web = site.OpenWeb())
{
str = web.Title;
}
}

Under the hood, the CLR transforms both using statements into two try/finally blocks—one nested inside the other—where the relevant object is disposed in each finally block. Handy but these multiple using blocks still leave the code that does all the real work of your application indented far into the page. Add some if statements, loops, or RunWithElevatedPrivileges calls and you’re halfway across.

To clean up ever so slightly, the two using blocks in the example above can actually be combined or stacked with a single block (a single set of braces and a single level of indentation):

using (SPSite site = new SPSite ("http://server"))
using (SPWeb web = site.OpenWeb())
{
str = web.Title;
}

The end result is the same at the MSIL level: two try/finally blocks nested one inside the other (check ildlasm.exe) but you regain one level of indentation.

System.Random not so random in a loop

When you need to generate a random number System.Random comes to mind:

int randomNumber = new Random ().Next ();

All well and good but did you know new Random () actually generates a sequence of random numbers and Next () simply returns the next random number in the sequence? The Random class could have been named more accurately as RandomSequence but I digress…. One more thing, did you know the random sequence is generated using a seed value and that if you specify the same seed value when constructing a new Random object you’ll get the same sequence of random numbers? And finally: did you know if you don’t specify a seed value, the seed value is initialised using the system clock which naturally “has finite resolution.”

If you answered no to all of the above and you need a random number go read the doco. If you’re an attentive reader, you’ll read this:

…using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers.

Which sucks because that’s exactly what happens if you use the above code in a loop on a machine that can execute that loop more than once before the clock ticks over. If that happens, the same seed value will be use and calling Next () on the new Random object will return the same value it did last time.

The easiest way to work around this is to instantiate your Random object outside the loop and then call Next () on that instance in the body of the loop:

Random randomSequence = new Random ();

for (int i = 0; i < 10; i++)
{
randomSequence.Next ();
}

If that doesn't suit, consider passing the Random constructor a seed value that increments with each iteration of the loop (the MSDN documentation suggests there may be performance implications if you create a new Random object repeatedly so watch out).

For what it’s worth, today we were dealing with this exact problem in the context of an anonymous method passed to the List<T>.Sort () delegate. The IComparer<T>.Compare () method supplied to Sort () only accepts two parameters (those to be compared).

int Compare( T x, T y)

As a developer, it’s easy to assume the anonymous method only has access to its parameters. In actual fact, variables in the “outer scope” are captured and made available to the delegate until the delegate referencing the anonymous method itself goes out of scope and become eligible for garbage collection:

The local variables and parameters whose scope contain an anonymous method declaration are called outer or captured variables of the anonymous method.

Read more about closures if you're interested...

What this means is that our anonymous method can access the Random instance declared in the outer scope:

Random randomSequence = new Random ();

list.Sort
(
delegate (string x, string y)
{
return x == y ? 0 : randomSequence.Next (-1, 1);
}
);

There’s some extra stuff going on here because the result returned must conform to the IComparer<T> interface in that it must return –1, 0, or 1 but the code in bold calls out the use of the outer variable within the anonymous method.

Wednesday, 6 May 2009

Can’t Minimise a Full Screen Remote Desktop Connection

Ever get stuck in a full-screen RDP session where the little yellow bar isn’t pinned and just won’t slide down?

Control + Alt + Break will restore the window.

Tuesday, 5 May 2009

Creating child sites under a Publishing Portal

Every time I create a new site collection I regularly forget to enable the use of different site templates below the top-level site. Invariably that means I’m limited to using the Publishing Site with Workflow template—fine for most of what I do despite the “with Workflow” bit adding extra hassle but I usually end up thinking you can’t create sites using other templates a child sites below a Publishing Portal.

Well that’s just silly—the extra site templates simply need to be made available through Site Settings –> Page layouts and site templates. Select the individual templates you want to make accessible or select Subsites can use any site template and you’re off. No features to activate in one of four different locations, no config to change, easy unless your memory is like sieve.

Ps. Zabi has posted a nice visual walkthrough showing you exactly how to make this change.