Conditionally Getting Audience Information

Okay, so, like, what happens if you’re writing a web part that you want to work on both Windows SharePoint Services and SharePoint Portal Server? First, you have to determine the web part’s context - are you running in WSS or SPS? Doing that, you can conditionally display things like input fields for audience information, etc. (I dwell on audience stuff because that seems to be the biggest thing that I’d like to use in my web parts yet still want to use the parts on WSS, which doesn’t support audiences.)

The problem is, if you determine that you are running in SharePoint Portal Server and then start calling objects in the Microsoft.SharePoint.Portal namespace, that works great on the SPS box, but gives you compile-time binding errors on WSS. What to do? System.Reflection to the rescue. Late bind to the assemblies and use the System.Reflection namespace to call methods and properties on your late-bound objects.

That sounds like a big pain, and it is. That’s why I’m helping you out by putting up some code here: using System.Reflection; using System.Collections; /// <summary> /// Gets the list of audience names and GUIDs for the current site /// </summary> /// <returns>A SortedList object where the keys are the audience names (string) and the values are the audience GUIDs (System.Guid)</returns> public SortedList GetAudienceAndGuidList(){    SortedList audList = new SortedList();    Assembly assemblyInstance = Assembly.LoadWithPartialName("Microsoft.SharePoint.Portal");    if(assemblyInstance != null){       // We're working on a SharePoint Portal Server, or a WSS site on a server with SPS       // Get the current portal context       System.Type portalContext = assemblyInstance.GetType("Microsoft.SharePoint.Portal.PortalContext");       PropertyInfo currentContextProperty = portalContext.GetProperty("Current");       object currentContext = currentContextProperty.GetValue(null, null);       if(currentContext != null){          // We have a portal context, so we're on SPS          // Get the types we'll be working with          System.Type audMgrType = assemblyInstance.GetType("Microsoft.SharePoint.Portal.Audience.AudienceManager");          System.Type audCollType = assemblyInstance.GetType("Microsoft.SharePoint.Portal.Audience.AudienceCollection");          System.Type audType = assemblyInstance.GetType("Microsoft.SharePoint.Portal.Audience.Audience");          // Create the AudienceManager object          object audMgr = audMgrType.InvokeMember(null,             BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance,             null,             null,             new object[]{currentContext});          // Call the Audiences property to get the collection of audiences from the AudienceManager          IEnumerable audColl = (IEnumerable)audMgrType.InvokeMember("Audiences",             BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty,             null,             audMgr,             null);          // Get the name and GUID for each audience and put them in the collection          foreach(object aud in audColl){             try{                string audName = (string)audType.InvokeMember("AudienceName",                   BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty,                   null,                   aud,                   null);                Guid audGuid = (Guid)audType.InvokeMember("AudienceID",                   BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty,                   null,                   aud,                   null);                audList.Add(audName, audGuid);             }             catch(Exception exc){                // If there are any problems, don't add the audience to the list                System.Diagnostics.Debug.WriteLine("EXCEPTION getting audience and guid list: " + exc.Message);             }          }       }    }    return audList; } /// <summary> /// Uses System.Reflection to late-bind to the Microsoft.SharePoint.Portal assembly and determine if /// a user is a member of an audience. /// </summary> /// <param name="username">The username of the person to look up</param> /// <param name="audienceID">The audience ID to check membership for</param> /// <returns>True if the user is a member of the specified audience; false otherwise</returns> public bool UserIsMemberOfAudience(string username, Guid audienceID){    Assembly assemblyInstance = Assembly.LoadWithPartialName("Microsoft.SharePoint.Portal");    if(assemblyInstance != null){       // We're working on a SharePoint Portal Server, or a WSS site on a server with SPS       // Get the current portal context       System.Type portalContext = assemblyInstance.GetType("Microsoft.SharePoint.Portal.PortalContext");       PropertyInfo currentContextProperty = portalContext.GetProperty("Current");       object currentContext = currentContextProperty.GetValue(null, null);       if(currentContext != null){          // We have a portal context, so we're on SPS          // Get the types we'll be working with          System.Type audMgrType = assemblyInstance.GetType("Microsoft.SharePoint.Portal.Audience.AudienceManager");          // Create the AudienceManager object          object audMgr = audMgrType.InvokeMember(null,             BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance,             null,             null,             new object[]{currentContext});          // Call the IsMemberOfAudience method to determine audience membership          bool userIsMember = false;          object[] isMemberOfAudienceArgs = new object[] {username, audienceID};          try{             userIsMember = (bool)audMgrType.InvokeMember("IsMemberOfAudience",                BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,                null,                audMgr,                isMemberOfAudienceArgs);          }          catch(Exception err){             // Do nothing             System.Diagnostics.Debug.WriteLine("EXCEPTION determining audience membership:\n" + err.Message);          }          return userIsMember;       }       else{          // We're working in WSS, which doesn't have audiences, so we'll assume that everyone          // is a member of every audience.          return true;       }    }    else{       // We're working in WSS, which doesn't have audiences, so we'll assume that everyone       // is a member of every audience.       return true;    } }

Comments