Wednesday, June 22, 2011

Event receiver, item permissions and form submission error

I had to open a SharePoint list for anonymous users to add items. The solution was to allow anonymous users to have "add" permissions on the list, design an InfoPath form for them to add the data, and fire an event receiver on the item added event to remove permissions for anonymous users on the item.. (In our case, anonymous users should not be able to see any item that was added to this list).

When I implemented this solution, InfoPath form would throw the error "Item was not found" after form submission. However the item was added successfully and the event receiver had also done its job.

Reason
The reason is pretty obvious. The event receiver had fired immediately after the item was added and removed all permissions on the list item, before InfoPath could complete its work. So, I thought delaying the event receiver by 10 seconds or so using "Thread.Sleep" would solve the issue. But that was not the case. I also observed a strange behavior where the InfoPath form itself waited for 10 seconds before throwing the same error again.

Resolution
The resolution was to execute the event receiver code in a separate thread as shown below:


         public override void ItemAdded(SPItemEventProperties properties)
        {
            EventFiringEnabled = false;
            try
            {
                Thread setPermissionsOnItem = new Thread(RunCodeInThread);
                setPermissionsOnItem.Start(properties);
            }
            catch (Exception ex)
            {
                //Log exception here
            }
            EventFiringEnabled = true;
        }

        private void RunCodeInThread(object objProperties)
        {
            Thread.Sleep(10 * 1000); //Halt for 10 secs to allow infopath form to complete
            try
            {
                SPItemEventProperties properties = (SPItemEventProperties)objProperties;
                // do the event receiver job here
            }
            catch (Exception ex)
            {
                //Log exception here
            }
        }

This solved the problem. The InfoPath form completed its processing immediately and the event receiver also worked fine. (A delay of 10 seconds is too much in most cases. You can reduce it considerably, but be sure to test it. I tried executing this code, without using Thread.Sleep and it worked 8 out of 10 times on an average)