Sunday, January 17, 2010

Tapping into the hidden SharePoint API using Reflection

Summary

The SharePoint API provides a very rich experience for software developers as almost everything that can be done with the SharePoint user interfaces can be done through the API.  One could argue that the SharePoint API has contributed to SharePoint’s overall success.

Anyone that has used Reflector to view the internal works of the SharePoint API knows that there is a lot of really interesting functionality that is marked away as private and not to be used by Joe Developer when customizing SharePoint.  Typically this is done by using the C# Internal keyword.  Even though I’m sure Microsoft had our best interest at heart when they locked away some of SharePoint API, sometimes you find something inside of it that you really want/need to use.

Well when you are in that situation (which should be very rarely) .Net Reflection becomes your friend and allows you to send messages to these classes even though they are supposed to be protected from your fingers.

Example: Field.SetFieldBoolValue

Okay, so a few months back I was trying to do some cleanup on some SharePoint Publishing sites.  One of the things I was cleaning was duplicate fields on the Pages list (how we got in this situation is subject for a different blog post).  Well the field I needed to delete was marked as Hidden so it could not be deleted.  Also since the Field definition marked the field as hidden I could NOT set the Hidden value to false. 

So I was looking at the SPField.Hidden property inside of Reflector and discovered that it uses something called SetFieldBoolValue to actually set the Hidden property.

image

A quick scan of that method reveled that it is an Internal method of the SPField class so I could not access it directly (again this is a good thing since Microsoft wants to protect me from myself).

image

Even though I respect that someone at Microsoft does not want me to use this field I really needed to toggle the Hidden property so I could delete that field.

So I used a little Reflection kung-fu to give me access to SetFieldBoolValue.

Type type = field.GetType();


MethodInfo mi = type.GetMethod("SetFieldBoolValue", BindingFlags.NonPublic | BindingFlags.Instance);


mi.Invoke(field, new object[] { "Hidden", false });


mi.Invoke(field, new object[] { "CanToggleHidden", true });


field.Update();




So if you are new to .Net Reflection take a look at this introduction.  What makes this work is the BindingFlags on the GetMethod routine.  So now I can use the MethodInfo to send a message that tells the field object to call the SetFieldBoolValue method.  Great Success!



Conclusion



By using .Net Reflection you can gain access to places in the SharePoint API that are marked as Internal and not to be accessed.  Typically you do NOT want to do this, but sometimes you may need to crack open the engine.  One of the best examples I have seen of this was done recently by a developer on our team.  He used reflection to gain access to the underlying SharePoint list collection to see if a list item had a field value.  This allowed us to really cut down on the number of exceptions thrown by our application.



1 comments:

Ben Leach said...

Hi Jeff,

I was interested in this post as I have found myself in a similar situation. In my case it is related to the SocialTagManager class in the new SharePoint 2010 API which has a GetTags method. Unfortunately the GetTags method is pretty limited and won't allow you to return any items that have been classified as being private (even if you are trying to return your own items and not someone else's).

I suppose the only concern I have with this is the 'supportability' of the solution, meaning that MS could potentially at any time change their API resulting in your solution breaking.

I would be interested in your opinions on this.

Nice post!