How to retrieve the current context from a posting object

I received the question if it is possible to get the current active context inside a custom placeholder definition. This is not the same as within a placeholder control as a placeholder control always uses the CmsHttpContext.

A placeholder can live without the CmsHttpContext (e.g. in a CmsApplicationContext). To check which mode the context is in it is necessary to access the context object of the current posting.

It actually took me 2 hours to find a solution. For the question above the first thing to get is the posting object – which is simple as the posting is a property of the placeholder object.
After this the current CmsContext of this Posting needs to be identified. This is where things become complicated as this information is stored in a private member property of a sealed class which prevents direct access to it from outside.
So I used reflection to access the protected fields. (Don’t forget to add using System.Reflection to your code).
Actually the class hierarchy looks as follows:
– Posting
–   ChannelItem
–      HierarchyItem
–         CmsObject
The CmsObject has a private member named “m_objectmap” of class “CmsObjectMap” (you can see this information in VS.NET when debugging your code and adding a posting to the watch list).
The current context is a member of the CmsObjectMap class.
To access this context we first need to get access to the m_objectmap field and then access the property holding the current context.
Due to the fact that we cannot cast to CmsObjectMap due to the protection level (really ugly) we need to do a two level reflection to get to the context. And thanks god: we can cast to CmsContext.
Here is how to resolve this. po is the posting object:
// get the type of CmsObject
System.Type CmsObjectOwnerType = po.GetType().BaseType.BaseType.BaseType;
// get the field Info for the m_objectMap property.
System.Reflection.FieldInfo CmsObjectFieldInfo = CmsObjectOwnerType.GetField(“m_objectMap”, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

// get the object
// this does not work: CmsObjectMap objectMapObject = CmsObjectFieldInfo.GetValue(po) as CmsObjectMap
// so we need to do it this way:
object objectMapObject = CmsObjectFieldInfo.GetValue(po);
System.Type objectMapType = CmsObjectFieldInfo.GetValue(po).GetType();
// get the field Info for the m_context property
System.Reflection.FieldInfo CmsContextFieldInfo = objectMapType.GetField(“m_context”, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
// voila: here is our context.
CmsContext currentContext = CmsContextFieldInfo.GetValue(objectMapObject) as CmsContext;

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.