Preventing users to add a beer that already exists in the beer list (or, how to work with the ItemAdding event)

I have a good crowd here in Sydney. They keep me busy with lots of interesting questions. I still have no news though regarding my bags so I went again to the shops and bought the things that a man needs abroad (socks, underwear and some shirts) J.

Anyway, question from a student was: 'How can we using an event handler to prevent a user from adding an item in a list that is already there?'

Take one of the beer lists (let's go for the German beers):

Can I prevent that a new beer titled Adler Pils Premium is added to the list? The ItemAdding is of course the event you want to work with to solve this. Unfortunately, there are some issues with the ItemAdding. You do not have access directly to the title of the beer when it is keyed in by the user and your code is executed. The ListItem property is null and both the AfterProperties and BeforeProperties seem to be empty. After a quick search, I found a couple of interesting postings about it. Best one (and excuse me if somebody else has done it before) is a posting of a Chinese guy (forgive me not being able to translate your name J). He got me started working out the following code:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.Collections;

namespace BeerDuplicationPrevention
{
public class BeerDuplication: SPItemEventReceiver
{

        public override void ItemAdding(SPItemEventProperties properties)
        {
            string title = string.Empty;
            foreach (DictionaryEntry de in properties.AfterProperties)
            {
                if (de.Key.Equals("Title0")) title = de.Value.ToString();
                SPQuery qry = new SPQuery();
                qry.Query = "<Where><Eq><FieldRef Name='Title0' /><Value Type='Text'>" + title + "</Value></Eq></Where>";                
                SPList list = properties.OpenWeb().Lists[properties.ListId]; 
                SPListItemCollection results = list.GetItems(qry);
                if (results.Count > 0)
                {
                    properties.Cancel = true;
                    properties.ErrorMessage = "Dude.. this beer already exists!";
                }
            }
        }
    }
}

The AfterProperties can be consulted in your code by looping over it via a foreach. A small CAML query (created with the new CAML Builder J) finishes it off. Again, credit to all of you who researched this before, but I thought it was a good idea to do an additional posting on this.