Weird behavior of Post Synchronous ItemUpdated event attached to libraries in SharePoint 2010

This blog post by fellow SharePoint MVP, Randy Williams has always been a good reference for me when working with SharePoint 2007 event receivers. I have decided to test Randy’s finding against SharePoint 2010 and extend his great work by taking into account the newly introduced “Post Synchronous” events.

The following table summarizes how Synchronous, Asynchronous and Post Synchronous events work with lists and libraries in SharePoint 2010.

List BeforePropoerties AfterProperties properties.ListItem
ItemAdding No value New value Null
ItemAdded No value New value New value
ItemAdded – sync No value New value New value
ItemUpdating No value Changed value Original value
ItemUpdated No value Changed value Changed value
ItemUpdated – sync No value Changed value Changed value
ItemDeleting No value No value Original value
ItemDeleted No value No value Null
ItemDeleted – sync No value No value Null

 

Library BeforePropoerties AfterProperties properties.ListItem
ItemAdding No value No value New value
ItemAdded No value No value New value
ItemAdded – sync No value No value New value
ItemUpdating Original value Changed value Original value
ItemUpdated No value No value Changed value
ItemUpdated – sync No value No value Original value
ItemDeleting No value No value Original value
ItemDeleted No value No value Null
ItemDeleted – sync No value No value Null

 

 

No value –> column value in the hash table was not available.
New value –> the new value for the column was available.
Changed value –> the updated value was available.
Original value—> the original value was available.
Null –> the item is not available.

 

As you can see, in the Post Synchronous ItemUpdated event attached to a library ( not a list), the properties.ListItem[“AField”] returns the original value (the value of a field before the update occurs) and there is no way to get the updated value. I’m not sure if this is a bug or by design, I’ll check and get back to you very soon.

Advertisement

Programmatically enforcing relationship behavior for lookup columns in SharePoint 2010

Adding lookup fields programmatically using feature is a common task in SharePoint 2007/2010. Normally, you would create the site column using a Field feature element. However, The lookup field definition requires the Id of the parent list and you have no way to determine this at design time, besides they will be different from one site to another. ( List Instances are different than Site Columns or Content Types; you cannot specify a list instance ID as the case with Site Columns or Content Types).

This dependency will force you to create Lookup columns using code that look up the parent List ID and uses it to create a new field object to define the site column.

I used to do this frequently in SharePoint 2007 but when yesterday when testing that for SharePoint 2010, I just asked myself, how can I programmatically enforce the relationship behavior ?

If you need more info about list relationships in SharePoint 2010, refer to this blog post.

This is straightforward using the UI from the column settings page and fortunately it’s as easy using code.

3

 

Consider the following example, I have two lists :

Parent List –> Employees
Child List –> Projects

I have a “Team Leader” field in the “Projects” list referencing the Employees List to specify the team leader of each project in the “Projects List”. To create a lookup field and enforcing the relationship behavior, see the following code snippet:

string teamLeaderFieldInternalName = projectsList.Fields.AddLookup(“Team Leader”, employeesList.ID, false);
SPFieldLookup teamLeaderField = (SPFieldLookup)projectsList.Fields.GetFieldByInternalName(teamLeaderFieldInternalName);
teamLeaderField.LookupField = employeesList.Fields[“Title”].InternalName;
teamLeaderField.RelationshipDeleteBehavior = SPRelationshipDeleteBehavior.Cascade;
teamLeaderField.Update();

The previous code will raise the following exception “This lookup field cannot enforce a relationship behavior because it is not indexed”. To fix you need to set the Indexed property of teamLeaderField to true as shown below :

string teamLeaderFieldInternalName = projectsList.Fields.AddLookup(“Team Leader”, employeesList.ID, false);
SPFieldLookup teamLeaderField = (SPFieldLookup)projectsList.Fields.GetFieldByInternalName(teamLeaderFieldInternalName);
teamLeaderField.LookupField = employeesList.Fields[“Title”].InternalName;
teamLeaderField.RelationshipDeleteBehavior = SPRelationshipDeleteBehavior.Cascade;
teamleaderField.Indexed = true;
teamLeaderField.Update();

You might also want to check the other members in the SPRelationshipDeleteBehavior Enum, I have copied the members along with their description from MSDN for easier reference below :

None: Nothing happens when a parent item is deleted and the child item is left pointing to the parent as an orphan.

Cascade: A cascade delete happens when deleting a parent item deletes all related children items of the related list.

Restrict: Restricts a parent item having any children items in the related list from being deleted.

Recycling list items using LINQ to SharePoint

Another interesting method that I found while investigating LINQ to SharePoint is the RecycleOnSubmit method.

context.Projects.RecycleOnSubmit(aProject);

context.Projects.DeleteOnSubmit(aProject);

If you want to move an item to the Recycle Bin, use the first method but if you want to entirely delete it use the second one.

And of course don’t forget to call context.SubmitChanges() to commit the changes to the content database.

Recursive and Folder-Scoped LINQ Queries in SharePoint 2010

As you might experienced in SharePoint 2007, a CAML query is by default non recursive. In other words, if you execute a CAML query, you will end up with items from the list root folder. This is still the same in SharePoint 2010. You have to define extra query options as shown below in case you want to query all folders and sub folders within a list (Recursive Query) :

qry.ViewAttributes = “Scope=’Recursive'”;

And if you want to scope your query to a certain folder :

qry.Folder = list.ParentWeb.GetFolder("Folders DocLib/2008");

What about LINQ to SharePoint ?

The default behavior is the same, however if recursive querying is the desired behavior, you can use the ScopeToFolder method from your EntityList<T> object.

Note the following queries:

var q = dc.Projects.Where(p => p.DueDate < DateTime.Now.AddMonths(1));
var q = dc.Projects.ScopeToFolder("", true).Where(p => p.DueDate < DateTime.Now.AddMonths(1));

The first one executes against the list root folder while the second one is recursive. You might be wondering about the empty string that I’m passing to ScopeToFolder method. Well, let’s see what MSDN says about the parameters that the method expects.

public IQueryable<TEntity> ScopeToFolder( string folderUrl, bool recursive )

folderUrl –> The URL of the folder.
recursive –> true to include items in subfolders; false to exclude them.

That’s it, if you want to scope your LINQ query to a specific folder, pass the folder URL as the first parameter to the method & “true” if you want the recursive behavior of the query. In the second query, I just wanted the recursive behavior and I didn’t want to scope my query to any folders so I passed an empty string, this does the trick.

Hope this helps!

Enabling the developer dashboard programmatically in SharePoint 2010

This is a question that I received during the Egyptian community launch of SharePoint 2010 and Office 2010. The following snippet does the trick!

SPWebService contentService = SPWebService.ContentService;
           SPDeveloperDashboardSettings developerDashboard =
             contentService.DeveloperDashboardSettings;
           developerDashboard.DisplayLevel = SPDeveloperDashboardLevel.On;
           developerDashboard.Update();

The guy who asked me this question wanted to create a farm-scoped feature to easily toggle the developer dashboard instead of using Windows PowerShell or STSADM command line utility. He also promised to share his feature with me once he finishes it.

If you cannot wait and you want to do it yourself, it’s very easy thanks to Visual Studio 2010 and the new SharePoint project and item templates that ships with it. Just open up Visual Studio 2010, create an empty SharePoint project, add a farm-scoped feature, add an event receiver to the feature, copy the code above to the FeatureActivated method, deploy your solution and there you go!

130

 

1

Using Lambda Expressions with RunWithElevatedPrivileges

Elevation of privilege, a feature that was added in WSS 3.0 & MOSS 2007, enables you to programmatically perform actions in code by using an increased level of privilege. The SPSecurity.RunWithElevatedPrivilegesmethod enables you to supply a delegate that runs a subset of code in the context of an account with higher privileges than the current user.

For some reason, I have never seen a code snippet that uses a lambda expression instead of the anonymous method syntax so I thought of showing you how to save some typing by using Lambda.

Commonly used syntax:

SPSecurity.RunWithElevatedPrivileges(delegate()
{     // Do things by assuming the permission of the "system account".
});

 

Much easier syntax:

SPSecurity.RunWithElevatedPrivileges(()=>
{     // Do things by assuming the permission of the "system account".
});

When I asked the following question on Twitter : “Why do people still use the anonymous method syntax rather than Lambda Expressions with SPSecurity.RunWithElevatedPrivileges() ? #SharePoint”

I got the following answer from Todd Bleeker : “Delegate syntax has been around a lot longer. Lambda is still confusing and even scary for most. <Todd />”

I totally agree with Todd, but guys if you are not comfortable with LINQ and lambda expressions, you should familiarize yourself with them before diving deep into developing SharePoint 2010 solutions.

As you all might know, Now in SharePoint 2010 you can use LINQ syntax to retrieve items from your lists instead of using CAML queries. Microsoft has included a LINQ provider for SharePoint in the Microsoft.SharePoint.Linq namespace, some classes in this namespace are responsible for translating the LINQ Queries to CAML ones which are eventually translated into SQL. You can still write CAML Queries and fetch items in the old ways but LINQ can really make your life easier specially when it comes to joins.

SharePoint 2010 Community Launch in Photos

Last Wednesday, May 12th was a special day. We had fun celebrating the Egyptian community launch of SharePoint 2010 and Office 2010. I have presented about “Visual Studio Tools for SharePoint 2010”, people were really excited to learn that they no longer need third-party tools for developing SharePoint Solutions. Finally Visual Studio 2010 is enough along with its great extensibility features!

I would like to extend a special thank-you to AvePoint and USPJA for sponsoring the event.

Here are some photos from the event:

13 14  13

16

 

 

USPJ Academy Launch May 17

<Cross Post from USPJA web site>

We are just about ready with the initial parts of the USPJ Academy platform. As such, on May 17, we’re launching the first features of the platform and invite students who have received and accepted a seat in the early access program to join us to begin learning SharePoint.

The first features launched are the library, the forums, and the faculty blog. These features are vital to understanding initial user needs for USPJA and will provide a rich environment in which students can prepare for their upcoming classes.

The official inauguration event happens on May 31, and classes begin on June 1.

</ Cross Post from USPJA Web Site >

For more information about USPJ Academy, see what SharePoint Tech Report wrote about it in April’s newsletter :

11