Monthly Archive for August, 2009

SharePoint Enhanced List View Web Part

I just published an enhanced List View Web Part in the Trentacular SharePoint 2007 Features CodePlex project. The Web Part is a substitute for the out of the box List View Web Part with two additional capabilities:

  • Toggling of views in place (without leaving the web part page)
  • Ability to display lists located in different sites of the same SharePoint Farm

Development of this Web Part has proved to be a very difficult undertaking, and I would love for any assistance or ideas with how to go about accomplishing this differently.

Here is where I’ve currently landed in the Web Part’s development:

  • I am accessing the SPLimitedWebPartManager at the selected view’s url to load the SharePoint List View Web Part that was provisioned for the view when created
  • I then use reflection to invoke the private RenderView method of the Web Part

Yes, this sounds extremely hacky, and it is. Using the avaliable SharePoint ListView control didn’t play nice with many custom views (especially when the list used managed content types). I’ve also tried the SPView.RenderAsHtml method, but this also presented problems.

Another possible option would be to use the ListViewByQuery WebControl, but this would require an intense amount of code to duplicate the sorting and filtering that is available through the ListView control. So if you think this Web Part would be useful and would like to contribute to furthering it along, please get in touch.

Here are some screenshots:

Trentacular List View Web Part

Trentacular List View Web Part Editor

How to use NHibernate Lazy Initializing Proxies with Web Services or WCF

Working with object trees is risky business when combined with remoting. Object trees often have very deep branches and circular references that will clog your pipes and overflow your stack when not handled properly.

NHibernate has addressed this same problem in the object-relational space with a very cool feature called lazy initialization, implemented using the Castle DynamicProxy library. By default, when an entity is loaded, its related entities are populated with proxies. The use of a proxy allows the entity to remain uninitialized until the moment one of its non-identifying properties is accessed, which in many cases is never - thus minimizing database queries. This strategy also eradicates the problem with loading an entire object tree from the database when only a single entity is needed.

Proxies become a problem when combined with Web services or WCF. Serialization of objects to XML requires knowledge of the data type to be serialized (accomplished with the KnownType attribute in WCF). The dynamically generated nHibernate proxies are not known to the serializer and thus a request to the service results in an exception such as System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly.

In order to make these entities safe for sending through the pipes, we must “unproxy” them and impose a limit to the object tree depth. The following utility class can be used for doing both by simply calling possiblyProxiedEntity.UnproxyObjectTree(mySessionFactory, maxDepth):

using System;
using NHibernate;
using NHibernate.Metadata;
using NHibernate.Proxy;
 
namespace Trentacular.Data.NHibernate.Util
{
    public static class NHibernateProxyUtils
    {
        /// <summary>
        /// Force initialization of a proxy or persistent collection.
        /// </summary>
        /// <param name="persistentObject">a persistable object, proxy, persistent collection or null</param>
        /// <exception cref="HibernateException">if we can't initialize the proxy at this time, eg. the Session was closed</exception>
        public static T Unproxy<T>(this T persistentObject)
        {
            var proxy = persistentObject as INHibernateProxy;
 
            if (proxy != null)
                return (T)proxy.HibernateLazyInitializer.GetImplementation();
 
            return persistentObject;
        }
 
        /// <summary>
        /// Gets the underlying class type of a persistent object that may be proxied
        /// </summary>
        public static Type GetUnproxiedType<T>(this T persistentObject)
        {
            var proxy = persistentObject as INHibernateProxy;
            if (proxy != null)
                return proxy.HibernateLazyInitializer.PersistentClass;
 
            return persistentObject.GetType();
        }
 
        /// <summary>
        /// Force initialzation of a possibly proxied object tree up to the maxDepth.
        /// Once the maxDepth is reached, entity properties will be replaced with
        /// placeholder objects having only the identifier property populated.
        /// </summary>
        public static T UnproxyObjectTree<T>(this T persistentObject, ISessionFactory sessionFactory, int maxDepth)
        {
            // Determine persistent type of the object
            var persistentType = persistentObject.GetUnproxiedType();
 
            var classMetadata = sessionFactory.GetClassMetadata(persistentType);
 
            // If we've already reached the max depth, we will return a placeholder object
            if (maxDepth < 0)
                return CreatePlaceholder(persistentObject, persistentType, classMetadata);
 
            // Now lets go ahead and make sure everything is unproxied
            var unproxiedObject = persistentObject.Unproxy();
 
            // Iterate through each property and unproxy entity types
            for (int i = 0; i < classMetadata.PropertyTypes.Length; i++)
            {
                var nhType = classMetadata.PropertyTypes[i];
                var propertyName = classMetadata.PropertyNames[i];
                var propertyInfo = persistentType.GetProperty(propertyName);
 
                // Unproxy of collections is not currently supported.  We set the collection property to null.
                if (nhType.IsCollectionType)
                {
                    propertyInfo.SetValue(unproxiedObject, null, null);
                    continue;
                }
 
                if (nhType.IsEntityType)
                {
                    var propertyValue = propertyInfo.GetValue(unproxiedObject, null);
 
                    if (propertyValue == null)
                        continue;
 
                    propertyInfo.SetValue(
                        unproxiedObject,
                        propertyValue.UnproxyObjectTree(sessionFactory, maxDepth - 1),
                        null
                        );
                }
            }
 
            return unproxiedObject;
        }
 
        /// <summary>
        /// Return an empty placeholder object with the Identifier set.  We can safely access the identifier
        /// property without the object being initialized.
        /// </summary>
        private static T CreatePlaceholder<T>(T persistentObject, Type persistentType, IClassMetadata classMetadata)
        {
            var placeholderObject = (T)Activator.CreateInstance(persistentType);
 
            if (classMetadata.HasIdentifierProperty)
            {
                var identifier = classMetadata.GetIdentifier(persistentObject, EntityMode.Poco);
                classMetadata.SetIdentifier(placeholderObject, identifier, EntityMode.Poco);
            }
 
            return placeholderObject;
        }
    }
}

There are several approaches on where and when this should take place depending on if you are using ASP.Net 2.0 Web services or WCF which I am not going to go into in this post. If you are working with WCF, Tim Scott has written about a good approach here.