Thursday, November 29, 2007

Why event handlers are triggered twice?

A lot of people call me Mr Event Handlers (ok, that is not 100% correct. Currently I am the only one calling me that, but never mind), but today's article comes from a Friend who we will refer to as Antin.
Antin did some research on why event handlers behaved strangely in publishing sites and emailed me the results. He logged every event that happens when you check-in a file in a publishing site, and logged the thread of each call, along with the time, so he figured out the sequence.

I think his results are important for all of us writing event handlers - we need to know what is happening when. If you do find this helpful, post a "thank you antin" comment on this post, and I will make sure he know about it (enough encouragment and he may start his own blog, the lazy bugger).

The test results:
(In brackets will be thread number, then list item is old/new, then before properties is old/new, then after values is old/new) Change AND Check-in:
1. Updating (10; old; old; old)
2. Updating (10; new; new; new)
3. CheckingIn (10; new; new; new)
4. CheckedIn (15; new; new; new)
5. Updated (11; new; new; new)
6. Updated (1; new; old; old;)

Change AND Save:
1. Updating (10; old; old; old)
2. Updated (12;new; old; old)

Check-in ONLY
1. CheckingIn (9; new; new; new)
2. CheckedIn (11; new; new; new)
3. Updated (13; new; new; new)
4. Updated (10; new; new; new)

Publish ONLY
1. Updating (1; new; new; new)
2. Updated (13; new; new; new)

If you look at what happens for the save only and the check in only and the combination of new/old values it looks like it working like this:
1. ItemUpdating - from the Save event
2. ItemUpdating - from the CheckIn event (which should fire after the Updated from the Save)
3. ItemCheckingIn
4. ItemCheckedIn
5. ItemUpdated - from the CheckIn event
6. ItemUpdated - from the Save event

Tuesday, November 27, 2007

Avoiding CSS caching issues

I had a problem in several projects where we changed the CSS and deployed it to the load balanced server environment, and still the old CSS file was cached somewhere, and we couldnt roll out the changes to the users.
Another problem on the same line are browsers that cache the css files, and users do not see the changes we make to the css until we tell them to clear their browser's cache.

To resolve this, we took a trick from Microsoft - notice how Microsoft always links to the css with a version number in sharepoint? this is done to avoid caching when you put a new version.

My trick was to develop a custom web control (that I call the "CssInjector") that gets as a property the link to the css file, and renders that link with a random querystring. this forces the browsers (as well as IIS or other caching applications) not to cache the file.
The problem with this solutions is that it will have performance implications - slower loading of pages, so what I'd really like to do is what MS did - rely on a version number. However, I have yet to come up with the architecture that will let me manage version numbers in my solution package without having to manually setting the version every time. I thought of reading the version number from the CSS file itself, but that will introduce performance issues again - as the code will have to load and read the css file each time a page is opened.

So until I get a better solution, here is the code I am using for my web control:

using System;
using System.Web.UI.WebControls;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
namespace SharePointTips.SharePoint.WebControls{
public class CssInjector : WebControl
        private const string CSS_LINK_FORMAT = @"<link rel=""stylesheet"" type=""text/css"" href=""{0}"">";
        private string _CSSFileLink = "";
        public string CSSFileLink
            get { return _CSSFileLink; }
            set { _CSSFileLink = value; }
        protected override void Render(HtmlTextWriter writer)
            if (this.CSSFileLink.Length > 0)
                writer.Write(string.Format(CSS_LINK_FORMAT, this.CSSFileLink + "?k=" + GetUniqueKey(8)));
        public static string GetUniqueKey(int length)
            //create an array of acceptable characters
            char[] chars = new char[62];
            chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
            StringBuilder result = new StringBuilder(length);
            Random rnd = new Random();
            //create the random string in the specified length
            for (int i = 0; i < length; i++)
            return result.ToString();
And here is how I use it in the master page:
<%@ Register Tagprefix="SharePointTipsWebControls" Namespace="SharePointTips.SharePoint.WebControls" Assembly="SharePointTips.SharePoint.WebControls, Version=, Culture=neutral, PublicKeyToken=xxxxxxxxxx" %>
<SharePointTipsWebControls:CssInjector runat="server" ID="SharePointTipsCSS1" CSSFileLink="/_layouts/SharePointTips/SharePointTipsCustomCss.css" />

Wednesday, November 07, 2007

MVP Night in Vegas

Text to come...

Monday, November 05, 2007

SharePointPedia is live

Microsoft has just released a site built on sharepoint, that will hold information (links) for sharepoint. (The short link is
Check out Lawrence Liu post about this.

Sunday, November 04, 2007

First night in Vegas

I am there at last, Vegas for the sharepoint dev connections conference. It only took me 30 hours to get from home to here, and I landed only 12 hours after I left (confused? so am I...)

So far, Vegas stinks. I don't mean it sucks - I mean it stinks with cigarette smoke. Man, its like going back to eastern europe (or Amsterdam). One reason I love Australia so much is the anti smoking laws.

So just a reminder - If you want to meet, in two days (Tuesday) we are having the SharePoint by Day, SharePint by Night event, with all MVPs having a few drinks and talking sharepoint with everyone who will stop to listen. Must be funny!
See you there!