Tuesday 29 April 2008

Considerations when referencing assemblies in your page layouts

This one came up in the office last week, and I thought it worthy of discussion. On one project we have, the page layouts use the ASP.Net Register directive to reference assemblies containing our controls. So we have several directives in the code similar to:

<%@ Register TagPrefix="psw" Namespace="OurCompany.OurClient.SharePoint.WebControls" Assembly="Parity.SharePoint.WebControls, Version=, Culture=neutral, PublicKeyToken=00000000000000" %>

These serve the purpose of telling the page layout about our controls assembly, and ensuring the designer can supply us with Intellisense for the controls and their members.

The question which then arises is "what happens when we update the shared assembly and we want to increment the version number? Surely we don't have to update and republish all our page layouts?" There are a couple of answers to this:

  • we could use assembly redirects in application config to avoid changing the page layouts. These entries would then tell .Net to load (for example) version of our assembly whenever version is requested. This would work, but would mean that we don't get Intellisense for any new/changed members added in subsequent assembly versions.

  • we could also avoid referencing common assemblies in this way completely, and centralize the reference in web.config instead

So instead of having an entry in each page layout, the 'Pages' section of web.config (in .Net 2.0 and upwards) allows us to reference assemblies containing controls in one central place, meaning any changes to the assembly name are simple to implement:

<add tagPrefix="psw" namespace="OurCompany.OurClient.SharePoint.WebControls"
assembly="OurCompany.OurClient.SharePoint.WebControls, Version=, Culture=neutral, PublicKeyToken=00000000000000" />
<!-- also works with short assembly name -->
<add tagPrefix="psw" namespace="OurCompany.OurClient.SharePoint.WebControls"
assembly="OurCompany.OurClient.SharePoint.WebControls" />

[Side note] - as I specify in the comment, it is possible to reference the assembly with the short name, but shops with a defined versioning strategy will want to avoid this since it's then not possible to have side-by-side versions of assemblies, one of the fundamental forward steps introduced with .Net.

However, it's not all clear cut. Unfortunately SPD isn't clever enough to resolve the assembly reference in web.config to provide Intellisense. I initially thought it was, but alas closing and re-opening shows that in fact something was cached. Visual Studio is sufficiently aware (if we were in a pure .Net scenario), but not SPD.

So it's a trade-off as far as I can see - either have the @Register directive in your page layout (with version numbers in it), or reference in web.config but lose Intellisense.

I wondered if it was possible to use the short assembly name in the @Register directive, but supply a 4 part assembly name in web.config for use at runtime. Unfortunately this doesn't work since .Net sees it as an ambiguous registration. So if you want to keep assembly version numbers out of your page layouts but keep Intellisense, one strategy could be to remove the @Register directives as part of your release process.

Or as an alternative final thought - which is more important, Intellisense during development or minimising running into this problem at release time? For my money, losing the inconvenience of Intellisense in SPD for controls in is a minor hassle, so referencing assemblies in web.config is a better approach.

Sunday 20 April 2008

5 things you didn't know about me

So a full year after it started, this tagging thing is still going on - my buddy Robin Meuré has tagged me to write about things you didn't know about me. I figure since I've not done this yet and I rarely write about anything personal, I'd make an exception and do it - so here goes. I think I'm actually supposed to write 8 facts, but 5 seems plenty to me :-)

  1. I'm completely addicted to breakfast cereal!

    I love muesli in particular, and for the last 10 years have got through at least two big bowls a day when not away from home. Those who have me on Messenger might know this from the Chris O'Brien : ICerealizable tag (developer's joke :-)) Bizarrely, my girlfriend Suzanne is a buyer for an organic muesli company, and so is able to bring lots of free stuff home, woohoo! Shortly after we met a couple of years ago, I remember in the pub my friends asking what she did as a job - when I told them, they didn't believe me ;-)

  2. I used to be a competitive cyclist.

    In my teens my life was dominated by cycling. I won lots of races when I was at my peak at around 18, and wasn't too far off getting into the GB team. Unfortunately my sporting career was cut short due to the combination of a couple of bad crashes in races and discovering girls and pubs. Guess I probably didn't have the dedication required to make it at the top level.

  3. I got into computers by accident.

    I studied business (and French!) rather than a classic Computer Science degree. The third year was a 'year in industry', and I'd talked my way into a prestigious placement in the IT department of large blue-chip. I hated it. I didn't understand the technology (IBM AS/400) and everyone spoke a language I didn't understand. After 5 months of unhappiness, it dawned on me that if I threw myself at it I'd probably understand it, and if I understood it I'd probably like it. I studied OS/400, Query 400, JD Edwards etc every evening, and 2 or 3 months later I absolutely loved it. I didn't want to return to university at the end of the year and was tempted when my employer said there'd always be a job for me there.

  4. I love travelling.

    My backpacking days are probably over, but I've been lucky enough to travel around South America, Australasia and Asia. The most recent trip was a solo trip to Nepal just over a year ago, and I got to trek to Annapurna base camp which is used for climbing expeditions in the area. At the higher altitudes it was getting down to -16 °C at night, and of course the simple lodges used for shelter at night have no heat! Those nighttime trips in the howling wind to get to the toilet were pretty memorable.   

  5. I'm a big Manchester City fan.

    Although I've lived in London for many years, I'll always support the 'other' team from Manchester and for better or worse, this was handed down from my father. If you speak to many people from Manchester, they'll always tell you real Mancunians support City. Unfortunately it's frequently a despondent hobby, and Colin Schindler had it right when he wrote his book 'Manchester United ruined my life'. However, I'm encouraged to read there is apparently an entire village of Manchester City fans somewhere in Sierra Leone!

So that's me. Some other people I'd like to tag who I don't think have done this are:

Monday 14 April 2008

Accelerate your InfoPath managed code development

Like most developers, I'm always looking for ways to speed up the code/test/get feedback cycle. There are many ways to do this in SharePoint development, and I guess a typical example would be to do application pool recycles rather than full IISResets. Along similar lines, anyone who has spent time doing Visual Studio/WF workflow development in SharePoint would hopefully have discovered the DEPLOY QUICK parameter on the build script MS supply - this will simply GAC the updated workflow assembly rather than perform a full deployment of the workflow Solution/Feature. This alone will probably shave many hours off a significant workflow project.

When working with InfoPath forms which have managed code, we need to deploy as an administrator-approved form rather than publish directly to a list or content type. The process is:

  • publish the form to the filesystem
  • upload the form via 'Manage form templates' in Central Admin

In the background, the last step actually wraps the form .xsn and associated assembly in a Solution and Feature, and deploys throughout your farm. Understandably this is S-L-O-W for development, so I started looking at ways to speed this up. Interestingly the assembly doesn't get deployed to the GAC or web application bin directory, but resides solely in the folder for the Feature (click image to enlarge):

Nevertheless, instead of publishing the form we can do the following:

  • compile VSTA/VSTO project
  • copy .dll (and .pdb if we're in debug mode) over the ones in the Feature folder
  • recycle app pool

This will then load the updated code. Note because we've only deployed the updated code to the local machine, only form sessions on the local machine will be affected (I'm assuming you're not using a load-balanced URL in dev) - this has a nice side-effect of isolating your changes from other developers in the farm until you're ready to release them.

I'm interested to know how InfoPath accomplishes the trick of loading assemblies from this location at run-time -there are no custom 'probing' entries in my web.config (instructions to tell .Net to probe custom locations for assemblies) so I'm assuming it's done via reflection.

If you have your own tips for speeding up SharePoint development which aren't commonly-known, I'd be interested to hear...

Sunday 6 April 2008

Recipe for successful use of Content Deployment Wizard

So my tool, the SharePoint Content Deployment Wizard has been available for some time now and I've been monitoring the feedback and issues people have raised closely. The current version is labelled 'beta 2' but I'm happy with the stability of the current codebase, so will probably re-label it as 'release 1.0' soon (following some feedback on the psychological aspect of the beta label :-)).

Only a small number of people have raised issues, and any problems have almost exclusively been related to the underlying Microsoft code used by the tool rather than the Wizard itself. I should probably be happy about this, but in reality if some people get errors from the tool it doesn't really matter why it happens. The good news is that it seems Microsoft are finally getting some issues with the Content Deployment API sorted at their end. This is a key point in my list of guidance I'd give to anybody running into any errors from the Wizard. Note that the first two apply to use of standard Content Deployment using Central Admin also:

Tip 1 - Service Pack 1 and hotfixes matter

Service Pack 1 fixed many issues with Content Deployment. Unfortunately it also broke some things which had previously been fixed with pre-SP1 hotfixes. It took me a while to realize this, but it's definitely the case. Probably the most common issue in this area is the 'Violation of Primary Key' error. There are reports of being able to work around this by modifying versioning settings on certain libraries, but MS have now released a hotfix very recently which seems to solve the problem for good on SP1 environments. At the moment this is by special request only - the KB to ask for is KB950279. This forum thread discusses this, and it worked for us. Interestingly I spoke to Tyler Butler (Program Manager for Content Deployment) at SPC2008, and he indicated Content Deployment in SharePoint is likely to get "significantly more stable in the next 30-60 days". I'm guessing this hotfix is what he was referring to, or at least part of it.

Tip 2 - always start from a blank site template an empty site created from STSADM -o createsite on the destination

The official guidance currently states that Content Deployment requires that the target site has been created from the 'blank' site template - this is detailed in KB article 923592. However, a better way detailed by Stefan in the comments below is to create an empty site using the STSADM -o createsite command. This is not the same as a site created from the blank template, and is the safest way to create sites which will use Content Deployment or the Wizard. What this means is that even if you're creating a site based on say, the publishing site template in development, any other environments which you wish to deploy content to should be created in this way. Notably, for publishing sites the publishing Feature should also not be enabled for the first deployment - this will be taken care of for you when the first deployment happens. You'll receive the same 'object already exists' error otherwise.

Tip 3 - pay attention to the 'retain object IDs' option

Generally the right option here is to select that you do want to retain the object IDs, and this should be done from the very first deployment - the only exception is when moving webs/lists to a different part of the site structure (reparenting). However, it's important to note that mixing use of Content Deployment or the Wizard with STSADM export/import is likely to cause problems as noted by Stefan in his recommended 'Content Deployment and Migration API - avoiding common problems' post.

A more comprehensive write-up of options available with the Wizard is available at 'Using the SharePoint Content Deployment Wizard'. Also note that's not it as far as the tool goes - in addition to extra functionality such as item-level reparenting and incremental deployment, I hope to refactor the code so that the Wizard would be scriptable from the command-line.

And special thanks go to my colleague Nigel Price for working through the hotfix situation, much appreciated :-)