Wednesday, January 31, 2007

Synchronous List Event Properties

Some people have posted (for example here) about not being able to access the properties of a list item in a synchronous list event (e.g. ItemAdding). Maybe this was fixed in the RTM but I'm not seeing this problem - the properties are actually there - they'll show up in the AfterProperties collection, although they can sometimes be a little hard to spot. One trap to watch out for is that the keys in the hashtable correspond to the fields' internal names, so that, for example, any spaces will be encoded as "_x0020_". To be safe, it pays to use a syntax something like the following:

string myFieldValue = Convert.ToString(properties.AfterProperties[properties.ListItem.Fields["My Field Name"].InternalName]);


An example of iterating through the SPItemEventDataCollection:
public override void ItemAdding(SPItemEventProperties properties)
{
    base.ItemAdding(properties);
    foreach (DictionaryEntry dictionaryEntry in properties.AfterProperties)
    {
    }
}

6 comments:

Keith Mann said...

Would it be possible for you to post some complete code (e.g., an entire ItemUpdating method)? I've tried what you suggest for obtaining field values but everything comes back null. Thanks in advance.

txs8311 said...

Keith, the ItemAdding example I posted should work if you change it to ItemUpdating. If you create a test custom list (which will include a default Title field), and then debug, stepping through the foreach loop - you should see that there is a dictionary entry with key "Title" and a value of the change you made in the list.

RafaelV said...

Exactly what I needed!! Thank you so much for posting this tip; now I can stop banging my head against the wall.

Dimitri Dhuyvetter said...

There is a difference between Lists and Document Libraries in this, check out http://www.synergyonline.com/blog/blog-moss/Lists/Posts/Post.aspx?ID=25

ItemAdding and ItemAdded don't contain properties in a Document Library, but do in a List. That might be why you didn't encounter the problems others described.

Joel said...

I would like some more help on implementing this solution, but am not quite sure how to write the code.

My requirements are simple:

set title=name
rename each document (by appending the ID) so that it has a unique name (thus not blocking subsequent uploads of documents with the same name).

Situation
-users only upload documents via the web interface
-after uploading they must fill out additional fields
-many might have the same name

I have been using a workflow, but this creates problems since I have to pause while the users input the additional fields (otherwise it will error out). Sometimes the workflow does funny things (like change some of the fields the users have input to random numbers) or does not even initiate. It is definitely not the cleanest way to accomplish the task.

I would like to use an event receiver. I don't think I can use ItemAdded since users will be inputing more fields. Paul Galvin mentioned overcomming this (http://paulgalvin.spaces.live.com/Blog/cns!1CC1EDB3DAA9B8AA!655.entry) but I'm not sure how. Therefore, I would like to use ItemAdding, but don't know how to do that.

I don't know any c#, but here is what I have scraped together from various sites:

public override void ItemAdding(SPItemEventProperties properties)
{
properties.AfterProperties["Title"] = properties.AfterProperties["FileLeafRef"];
string FileName = properties.AfterProperties["FileLeafRef"].ToString();
if (FileName.Length > 20)
FileName = FileName.Substring(0, 19);
string NewFileName = FileName + properties.AfterProperties["ID"];
properties.AfterProperties["FileLeafRef"] = NewFileName;
}

I'm sure my syntax is off, and this is my best guess at what the internal names are and how to reference them.
Any help would be appreciated!

txs8311 said...

Hi Joel,

I don't think ItemAdding is going to help you out in this case. There are only a few fields that are passed in the AfterProperties (e.g. vti_filesize, vti_parserversion). So finding the file name (FileLeafRef) would be tricky (it might be possible to obtain it through the HttpRequest object, but I haven't tried this). You can't update the file name in ItemAdding or ItemUpdating either (it won't error out, but it creates a new property called FileLeafRef instead of updating the actual column).

The solutions I've seen online are to rename the file after it has been created (ItemAdded event receiver - the file has already been created when your users see the meta data fields to input).

A workflow can do this or you could use a variation on the code you referred to. I'm not sure about the problems you're having with workflow. Sometimes looking in the SharePoint event log (with trace level set to verbose) can give some insights if you're not able to use Visual Studio.

Todd