Reflection in .NET

In one of my projects there was more than one visual studio solution and a requirement of the infrastructure team was to reduce the number of solutions to exactly 1.
The choice was either to create one solution once, or create a tool with which the solutions are used as input to create a single solution containing all solutions.

We decided to create a tool that builds a wspbuilder structure and copies the files to the correct positions. Why? Developers can keep developing using their usual structure and the requirement is met.

For those projects that were created using the SharePoint Extensions for Visual Studio there was another problem, because during the creation of a WSP, VSE manipulates certain references (GUIDs) in the describing xml-files.

To remedy this, we of course needed to resolve those refrences ourselves. For GUIDs that reference classes reflection needed to be used for resolution of the full qualified class name.

Using the methods Assembly.Load(string), Assembly.Load(AssemblyName) worked fine until I forgot to retract the deployed solution and renamed a class. The result was, that the wrong name was resolved and on deployment the right class was not found, because the wrong name was referenced.

The problem was – you might have guessed – the assembly that was reflected was the one in the Global Assembly Cache (GAC), not the one in my project folder (newer version) although the assembly was referenced using an absolute path string.

So I needed to change the reflection mechanism. There is a static method on Assembly called ReflectionOnlyLoad(string). It reflects the assembly at the correct position, but you cannot search for classes and methods (which you can do if you use one of the Load methods) until you also reflect the assemblies that are referenced (recursive).

The two bool-flags of an Assembly-object GlobalAssemblyCache and ReflectionOnly help you differentiate between the usual case (you reference an assembly and it is used, because no version is in the GAC) and the special case (the GAC assembly version is used instead of the real assembly).

So this is what I did to make it work:

...
Assembly assembly = Assembly.LoadFile(fullName);
if(myAssembly.GlobalAssemblyCache)
{
    myAssembly = Assembly.ReflectionOnlyLoadFrom(fullName);
}
...
...
AssemblyName[] names = myAssembly.GetReferencedAssemblies();
 if (realAssembly.ReflectionOnly && names.Length > 0)
 {
   foreach (AssemblyName assembly in names)
   {
     Assembly tmp = Assembly.Load(assembly.FullName);
     if(tmp.FullName != null)
     {
       Assembly.ReflectionOnlyLoad(tmp.FullName);
     }
     else
     {
       throw new Exception(
        "Could not load assembly " +
        "with assemblyName '" +
        assembly.FullName +
        "' for reflection purposes of receiverClass '" +
        receiverClassGuid + "'.");
     }
   }
 }
...

Leave a Comment

UniqueFieldReceiver using CAML

A nice example of how a small requirement can be come a big SharePoint task is the unique field problem.

The requirement would be best explained as analogy to the unique constraint on relational databases. If you want a field to be unique you need to make sure, that each element that is inserted has a different value.

I solved this by creating an event receiver for events

  • SPEventReceiverType.ItemAdding
  • SPEventReceiverType.ItemUpdating

You would expect this to be straight forward. You take the SPItemEventProperties.AfterProperties SPItemEventDataCollection (because ItemAdding and ItemUpdating are synchronous events) and check if an item exists with this property. If this is the case you terminate the insert / update action.

This is not that simple. The only properties included in the AfterProperties SPItemEventDataCollection are those that are in the add (/HttpEncodedListName/NewForm.aspx) / edit (/HttpEncodedListName/EditForm.aspx) forms. So choose the field and set the properties of the field (SPField.ShowInNewForm = true, SPField.ShowInEditForm = true) accordingly.

SPField.StaticName == “Title” is a good choice.

The next thing to consider is that you of course need an elevated web or you will only get those items that the current user can see.

...
SPSecurity.CodeToRunElevated =
(
  delegate
  {
    using(SPWeb web = properties.OpenWeb())
    {
      // your code here
    }
  }
);
...

You need to make a difference between inserting and updating. Inserting is a tad easier.
All you have to do is send the caml query to the database asking whether an item exists.

public static bool Exists(SPList list,
                        string fieldName,
                        string fieldValue,
                        string fieldType)
{
  string queryString =
    string.Format("<Where><Eq><FieldRef Name=\"{0}\" />" +
                  "<Value Type=\"{1}\">{2}</Value></Eq></Where>"
                   fieldName,
                   fieldType,
                   fieldValue
    );
  SPQuery query = new SPQuery { Query = queryString };
  SPListItemCollection result = list.GetItems(query);
  if(result.Count > 0)
  {
    return true;
  }
  return false;
}

For the updating event you have a little more to consider. First of all: Did a “true” update on the field itself take place or are the two values (before / after) identical?
In this case you need to take the ID of the item into consideration. Either you check before / after images or you correct the caml query accordingly. This does not work however for the inserting action, because then the ID of course does not exist yet.

<Where><And>
  <Neq>
  <FieldRef Name="ID" /><Value Type="Counter">{3}</Value>
  </Neq>
  <Eq>
    <FieldRef Name="{0}" /><Value Type="{1}">{2}</Value>
  </Eq>
</And></Where>

{3} should be set using the id of the existing item (which to ignore).
You can also work on the SPListItemCollection, which I do not recommend for performance reasons (keep communication data (between database and front-end server) as small as possible) though.

This is essentially it. Make an exception for lookup and datetime fields when comparing before and after images.

The rest should be straight forward.

Adding your new eventreceiver to lists is done like this:

public static void Add(SPWeb web,
                       string assemblyFullName,
                       string classFullName)
{
  SPList list = web.Lists["MyExistingList"];
  list.EventReceivers.Add(SPEventReceiverType.ItemAdding,
                            assemblyFullName,
                            classFullName);
  list.EventReceivers.Add(SPEventReceiverType.ItemUpdating,
                            assemblyFullName,
                            classFullName);
}

Leave a Comment

Iteration versus Catching Expected Exceptions

Most SharePoint objects (Microsoft.SharePoint.dll) contain typed collections to store the references to other objects (example: SPList.Items is an SPListItemCollection). The problem is, that these collections implement methods for retrieving objects from these collections that throw ArgumentExceptions if the key-value (unique value: i.e. title, GUID, id, index) does not retrieve a valid element.

If you have a typical update method that has to check if the underlying object exists you will do it using one of the following two possibilities:

public static SPList GetElementTry(SPWeb web, string listName)
{
    SPList list = null;
    try
    {
       list = web.Lists[listName];
    }
    catch(Exception) {}
    return list;
}

public static SPList GetElementIterate(SPWeb web, string listName)
{
    SPList list = null;
    string listName = listName.ToLower();
    SPListCollection lists = web.Lists;
    foreach(SPList list in lists)
    {
        if(string.Equals(list.Title.ToLower(), listName))
        {
            return list;
        }
    }
    return list;
}

The problem now is: which one is better from a performance and design point of view?

I read somewhere that in Java (I used to develop in Java) if you want a basic metric (and this is a strong abstraction from reality, if it is even applicable) you can say the creation and throwing of an exception costs about 400 times more than a basic comparison (and again, please correct me if I’m wrong in this assumption).

The SharePoint magic number of storage / items / lists / objects: 2GB // 2000.

When you compare this to 400, then you will probably end up saying: I can optimize iteration a little bit so I’ll use this, because it seems more elegant, but I would rather have an internal method that does this for me and instead of throwing an exception it returns null.

Well we’re not in happy-land so you have to make a decision.

Something I would not do though is implement a method ElementExists that does the same thing as the Get-method and instead of returning null / the element it just returns true/false. You can check for null in your code instead, if you encapsulate with a boolean value you need to call your method twice. This is only sensible if you do not need to use the object further.

On how to iterate, check this blog.

Leave a Comment

Binding on ISecurableObject

I have a static method static void Bind(ISecurableObject iSecurableObject, SPRoleDefinition roleDefinition, SPPrincipal principal) I use whenever I want to add a new permission to either SPWeb, SPList, SPListItem objects.

Binding permissions works something like this:
You take an object that has unique role assignments and add to the role assignments of this object a tuple of (SPRoleDefinition, SPPrincipal), where a role definition is a pre-defined permissions mask like read, write or administrate and a principal is the super type of group and user.
Every ISecurableObject contains a collection of SPRoleAssignments. This allows more than one SPRoleDefinition per SPPrincipal. The SPRoleDefinitions can be merged together. This works because of the permissions mask (can be realized as bit mask, every 1 overwrites a 0 (logical OR).

My function works like this:

public static void Bind(ISecurableObject iSecurableObject,
                        SPRoleDefinition roleDefinition,
                        SPPrincipal principal)
{
    if(!iSecurableObject.HasUniqueRoleAssignments)
    {
        BreakInheritance(iSecurableObject);
    }
    SPRoleAssignment assignee = new SPRoleAssignment(principal);
    assignee.RoleDefinitionBindings.Add(roleDefinition);
    try
    {
        iSecurableObject.RoleAssignments.Remove(principal);
    }
    catch(Exception) {}
    iSecurableObject.RoleAssignments.Add(assignee);
}

Whoever finds the bug is pretty damn good. :-) (in my opinion).

The problem is that if you have a list, and it has items with unique permission sets, the different principals have an automatic limited permissions. If you have more than one item and the principal has permissions on both items, the permission on the prior item is deleted, because the role assignment is removed. So get the role assignment if it exists, then add the role definition to the existing role assignment.

This would look like this:

public static void Bind(ISecurableObject iSecurableObject,
                        SPRoleDefinition roleDefinition,
                        SPPrincipal principal)
{
    if(!iSecurableObject.HasUniqueRoleAssignments)
    {
        BreakInheritance(iSecurableObject);
    }
    SPRoleAssignment assignee;
    try
    {
        assignee = iSecurableObject.RoleAssignments.
                   GetAssignmentByPrincipal(principal);
        if(!assignee.RoleDefinitionBindings.Contains(roleDefinition))
        {
            assignee.RoleDefinitionBindings.Add(roleDefinition)
        }
    }
    catch(Exception)
    {
        assignee = new SPRoleAssignment(principal);
        assignee.RoleDefinitionsBindings.Add(roleDefinition);
        iSecurableObject.RoleAssignments.Add(assignee);
    }
}

The try-catch-block is needed because the SPRoleAssignmentCollection throws an argument exception if there is no assignment of this principal in the collection.

Leave a Comment

Make use of “using” when dealing with the SPWeb object

Whenever you need to create an SPWeb object it is highly recommended that you dispose explicitly once you do not need it any longer. This can be done using the “using”-construct. Typically this works as follows:

using(SPWeb web = new SPSite("http://localhost").OpenWeb())
{
    // your code here
}

The reason for this is that the SPWeb object is especially large so that when a lot of users call your custom code in the context of SharePoint a lot of memory is allocated and never freed again (memory leak). The Internet Information Service (IIS) reacts by recycling the corresponding application pool. When this happens the next user coming across any of your application pages will wait quite some time, as the application needs to be re-initialised. If this happens a lot then your users will complain about performance issues. The problem of course is that you cannot reproduce this reliably so developers will have a hard time pin-pointing the problem.

This msdn entrye on this subject is worth reading.

Leave a Comment

The Trouble of using Constant Values

The trouble in SharePoint is that you need a lot of constant values for names of lists, fields, receivers, assemblies, groups, views and content types. Usually you define these in xml documents.

When specifying the components (lists, content types, fields, etc.) using xml you have no possibility to use variables. This is a problem as you have a lot of rework to do once you need to change something and you have a lot of references (references beeing mentions of other components at definition time. This is especially true for applications with high component coupling.

Another thing is that the possibilities for specification are limited. You cannot define lookup fields correctly as you do not know the GUID before the list and the field that are looked up exist (The GUIDs you can insert are not applicable as you would use the equivalent of a class GUID instead of the instance GUID and the instance is not yet created at definition time).

What you will do is either create a feature receiver to tidy up you definition (create remaining lookup fields programmatically using the SharePoint API) or doing the whole routine using the API inside the feature receiver. I favor this option as it reduces the redundancy, it is debuggable and easier to use (less error prone, as Visual Studio assists you). Drawback is of course that the list is not updateable using the intended Microsoft mechanism via stsadm -o upgradesolution.

As there are still some issues with this anyway (specification and deployment), SharePoint change management can be done only using the API from my point of view. So you would create a new one-shot solution containing a feature that on activation changes your application accordingly. There are certainly some issues to get into when doing this, but for SharePoint 2007 you should seriously consider this.

So at this point you are using feature receivers one way or the other for your lookup fields. So it makes sense to declare your constant values at one central point. For the start it does not matter how you do this using one giant class for each type (list, group, content type, view, etc.) or creating a class for each actual object of the sharepoint application but you should always remind yourself that it makes sense to declare variables as constants for performance issues. You should also think about how many objects you want to specify, as you will typically use these in a static context. So you use either lightweight objects, singletons, static class definitions but you definitely separate definition of these constants from your code logic.

For custom components using workflows, eventreceivers and definition of a lot of lists it especially makes sense to use this approach as you will reference your objects using the names as key-value when iterating over the collections or direct access.

The main objective is to be enable management of code that is subject to change a lot. Using redundant string values each and every time makes changing names strenuous and error-prone.

Leave a Comment

Web.config modification

In our project we needed to include Telerik into our SharePoint application. Telerik is used for creating high level web controls.

The vendor supplies a nice howto for this purpose.

The problem however is how to programmatically change the web.config for this.

The problem of changing the web.config can be solved by either

  • providing a new default web.config in the 12\CONFIG folder (is used when creating a new web application);
  • changing the web.config manually (not recommended for production environments!!);
  • using the API methods provided by SharePoint, as explained here

The big question now is how to implement this sequence correctly (click image to view original size):

webconfig1

When you just implement the usual way one after the other using the SPWebConfigModification object, you will see that the collection of web modifications (SPWebApplication.WebConfigModifications) is sorted primarily by the name of the modification, rather than the sequence number. Only if the name of the nodes is the same the sequence number is used. This is of course especially critical when adding nodes “add” and “remove” under a common root node (like configuration/system.web/httpHandlers) as “add” always comes before “remove”. The remove is appended at the end of the child list of the configuration/system.web/httpHandlers node.

This is not desirable as the “remove”-node removes all active server module mappings, so when a module is supposed to be executed the server does not know which handler to use. The effect can be seen for the “SharePoint Excel Export” for lists. It simply doesn’t work anymore (authorization request loop, or empty spread sheet eventhough the exported list is not empty) because the module reference fails.

It does not help to change the sequence number of the SPWebConfigModification objects and it does not help to change your code so that the insertion order of the changes is the way you would like the changes to appear in the web.config. The modifications are stored in the content database of SharePoint and when retrieved the sort order is determined neither by the sequence number (only as second parameter) nor the insertion ID. You would expect that this doesn’t matter as an xml document usually doesn’t concern itself with ordering. In this special case as the actions for HttpHandlers are executed in order this is the case though.

The solution consists of two steps (the solution for this problem is easy to remedy but it has a side effect you need to correct as well):

SPWebConfigModification ModScriptResource
= new SPWebConfigModification(name, xpath)
            {
                Owner = OwnerModif,
                Sequence = sequenceNo,
                Type = SPWebConfigModification.
                  SPWebConfigModificationType.EnsureChildNode,
                Value = scriptResource
            };

The important variables are: name, xpath and scriptResource. The name is important for sort order and represents the path to the node relative to the variable xpath. XPath represents the absolute path of the node. ScriptResource is what is inserted in the web.config at the spot that is defined by the variable xpath.

For this scenario the sequence number is irrelevant.

webconfigmods

For the first “add” modification check out that it contains the “remove” node as well. This way you can ensure that it is always inserted in this order. This has one drawback though. When the modification should ever be removed the “remove” node stays in the web.config as the name of the webmodification is responsible for what is removed from the web.config. So this is not a clean approach. For this you need the empty dummy-entry for the “remove” node abve the “add” modification. This way both you ensure the two nodes are inserted as well as removed at the same time if you iterate over the modifications and remove all the entries for your owner module.

Leave a Comment

Synchronous and Asynchronous Eventhandling

The idea of events and eventhandling is simple. When an event occurs (a typical example in SharePoint: an item is added to a list or library) the system looks for all registered listeners waiting for this event to happen. These listeners are implemented by pieces of code (methods) that confirm to the following standards:

  • The class the method is contained in is derived from SPItemEventReceiver
  • The method name is equal to one of the entries of the enumeration SPEventReceiverType
  • The return value of the method is void
  • The signature of the method contains one parameter only of type SPItemEventProperties
  • The method has public visibility and is non-static

In conclusion, the method you write overrides an existing method from the SPItemEventReceiver class. A sample would look like this:

namespace MyEventReceivers
{
  public class MyFirstEventReceiver : SPItemEventReceiver
  {
     public override void ItemAdded(SPItemEventProperties properties)
     {
       // your code that executes when event occurs here.
     }
  }
}

Now that an eventreceiver has been created this needs to be compiled in an assembly and transported to the GAC using either on a testmachine a tool like gacutil (search for gacutil.exe on your system, it should be provided with .NET SDK) or directly creating a solution with either wspbuilder, visual studio extensions for SharePoint 2007 or manually writing a manifest and using the makecab command.

To inform SharePoint that it should execute your code whenever a certain event (in our case the ItemAdded event, which is an asynchronous event) occurs you need to register the receiver on the object you want to use.
ItemAdded is typically a list event, so we will register the event receiver on a list with the name MyListWithEventReceiver. You can do this either using Microsofts xml notation and deploying the solution or you can use a feature or executable (only development system) to do this.

public static void Main(string[] args)
{
  const string listName = "MyListWithEventReceiver";

  const string assemblyName = "MyAssemblyFullName";
  const string eventReceiverName = "MyFirstEventReceiver";

  using(SPWeb web = new Site("http://myServer:myPort").OpenWeb())
  {
       SPList list = web.Lists[listName];
       list.EventReceivers.
             Add(SPEventReceiverType.ItemAdded,
                   assemblyName,
                   eventReceiverName);
       list.Update();
  }
}

Check out this link and Dave Hunter’s Blog as well.

Important to know now is that everytime you write code to insert an item and then use a SPList.Update() call from our generic list your code will be executed. If for some reason you don’t want this, you can turn it off by using the DisableEventFiring() method as I explained here.

Of course this will also occur whenever someone adds an item to your list using the web front-end of SharePoint.

Now that the basics of SharePoint Events and EventReceivers are laid out to get to the topic at hand:
The difference between synchronous and asynchronous eventhandling. Synchronous events such as “ItemAdding”, “ItemUpdating”, “ItemDeleting” are executed logically during the event itself, asynchronous events are handled after the event has taken place.

So the “sync events” can be typically used for validation testing, the “async events” for consecutive actions, very much like workflows. “Async events” can be seen as primitive one-step workflows. Of course workflows can do a lot more, including waiting on human interaction to determine the next execution step.

Programatically, how does this effect the objects at your disposal?
The properties object contains an SPWeb object, which you can use to get all your object or identify the working web and create a new one with elevated privileges. You also have the BeforeProperties, AfterProperties and ListItem members.

The “async events” have the ListItem member, because it has been created already, the “sync events” have the before and afterProperties, which contain the values from the form, that was used to change the listItem. So it is always error-prone to change existing eventreceivers from async to sync and vice-versa.

Happy SharePointing!

The SPEventReceiverType enumeration gives an idea of all the events you can create listeners for.

Leave a Comment

Layer Architecture and DisableEventFiring

Some time ago, I had the problem that I wanted to stop an event from triggering cascadingly. That is usually not the biggest problem. The SPItemEventReceiver class contains a protected method for static void DisableEventFiring(); and static void EnableEventFiring(); that it inherits from Microsoft.SharePoint.SPEventReceiverBase. The first method prevents code from triggering further events and the second reactivates the default functionality.

Default functionality: Every Update(), Update(bool) (SystemUpdate(), SystemUpdate(bool)) method on SPWeb, SPList or SPListItem triggers all events that are registered with the according object (for ListItems this is the list they belong to (SPListItem.ParentList)).

If you have a layer architecture and you do not want to put all your code into the feature receiver methods, then you have a little problem that can be solved by created the following class:

public class DisableEventFiring: SPEventReceiverBase, IDisposable
{
  public DisableEventFiring()
  {
     DisableEventFiring();
  }
  public void Dispose()
  {
    EnableEventFiring();
    GC.SuppressFinalize(this);
  }
}

Now you can call from anywhere in your code:

void MyMethod(SPListItem itemWithTriggerEvents)
{
  using(new DisableEventFiring())
  {
    itemWithTriggerEvents.Update();
    // or itemWithTriggerEvents.SystemUpdate();
  }
}

Important to understand is also the disposal of the object. Using the “using”-block you can dispose the object directly and also you don’t need to worry about reactivating the event firing.

Happy SharePointing!

Comments (1)

SPEventReceiverType.CheckingIn

I was just working with document libraries and the dreaded “CheckingIn”-Event (SPEventReceiverType.CheckingIn).

The problem you get, when you try to change the
properties.ListItem (SPItemEventProperties.SPListItem) is that when listItem.Update(); (listItem.Update(bool);) are executed an Exception “Save conflict” occurs and your listitem is not checked in at all.

There are two nice blogs with good hints to the problem (also read the comments):

For me, it is not acceptable to catch exceptions and try the same action again, so I tried the variant of

listItem.SystemUpdate(false);

This of course requires elevation of privileges, because system update is supposed to be done by the system user, so the complete code looks like this:

public override void ItemCheckingIn(SPItemEventProperties properties)
{
  SPSecurity.RunWithElevatedPrivileges (
    delegate
    {
      SPListItem listItem = properties.Listitem;
      // change your listItem here
      // listItem["MyTextFieldInternalName"] = "foo bar";
      listItem.SystemUpdate(false);
    });
}

This worked for me. I hope it does for you, too!

Leave a Comment