Development With A Dot

Blog on development in general, and specifically on .NET

Sponsors

News

My Friends

My Links

Permanent Posts

Portuguese Communities

More SharePoint 2010 Expression Builders

Introduction

Following my last post, I decided to publish the whole set of expression builders that I use with SharePoint. For all who don’t know about expression builders, they allow us to employ a declarative approach, so that we don’t have to write code for “gluing” things together, like getting a value from the query string, the page’s underlying SPListItem or the current SPContext and assigning it to a control’s property.

These expression builders are for some quite common scenarios, I use them quite often, and I hope you find them useful as well.

SPContextExpression

This expression builder allows us to specify an expression to be processed on the SPContext.Current property object. For example:

   1: <asp:Literal runat="server" Text=“<%$ SPContextExpression:Site.RootWeb.Lists[0].Author.LoginName %>”/>

It is identical to having the following code:

   1: String authorName = SPContext.Current.Site.RootWeb.Lists[0].Author.LoginName;

SPFarmProperty

Returns a property stored on the farm level:

   1: <asp:Literal runat="server" Text="<%$ SPFarmProperty:SomeProperty %>"/>

Identical to:

   1: Object someProperty = SPFarm.Local.Properties["SomeProperty"];

SPField

Returns the value of a selected page’s list item field:

   1: <asp:Literal runat="server" Text="<%$ SPField:Title %>"/>

Does the same as:

   1: String title = SPContext.Current.ListItem["Title"] as String;

SPIsInAudience

Checks if the current user belongs to an audience:

   1: <asp:CheckBox runat="server" Checked="<%$ SPIsInAudience:SomeAudience %>"/>

Equivalent to:

   1: AudienceManager audienceManager = new AudienceManager(SPServiceContext.Current);
   2: Audience audience = audienceManager.Audiences["SomeAudience"];
   3: Boolean isMember = audience.IsMember(SPContext.Current.Web.User.LoginName);

SPIsInGroup

Checks if the current user belongs to a group: 
   1: <asp:CheckBox runat="server" Checked="<%$ SPIsInGroup:SomeGroup %>"/>

The equivalent C# code is:

   1: SPContext.Current.Web.CurrentUser.Groups.OfType<SPGroup>().Any(x => String.Equals(x.Name, “SomeGroup”, StringComparison.OrdinalIgnoreCase));

SPProperty

Returns the value of a user profile property for the current user: 
   1: <asp:Literal runat="server" Text="<%$ SPProperty:LastName %>"/>

Where the same code in C# would be:

   1: UserProfileManager upm = new UserProfileManager(SPServiceContext.Current);
   2: UserProfile u = upm.GetUserProfile(false);
   3: Object property = u["LastName"].Value;

SPQueryString

Returns a value passed on the query string:
   1: <asp:GridView runat="server" PageIndex="<%$ SPQueryString:PageIndex %>" />

Is equivalent to (no SharePoint code this time):

   1: Int32 pageIndex = Convert.ChangeType(typeof(Int32), HttpContext.Current.Request.QueryString["PageIndex"]);

SPWebProperty

Returns the value of a property stored at the site level:
   1: <asp:Literal runat="server" Text="<%$ SPWebProperty:__ImagesListId %>"/>

You can get the same result as:

   1: String imagesListId = SPContext.Current.Web.AllProperties["__ImagesListId"] as String;

Code

OK, let’s move to the code. First, a common abstract base class, mainly for inheriting the conversion method:

   1: public abstract class SPBaseExpressionBuilder : ExpressionBuilder
   2: {
   3:     #region Protected static methods
   4:     protected static Object Convert(Object value, PropertyInfo propertyInfo)
   5:     {
   6:         if (value != null)
   7:         {
   8:             if (propertyInfo.PropertyType.IsAssignableFrom(value.GetType()) == false)
   9:             {
  10:                 if (propertyInfo.PropertyType.IsEnum == true)
  11:                 {
  12:                     value = Enum.Parse(propertyInfo.PropertyType, value.ToString(), true);
  13:                 }
  14:                 else if (propertyInfo.PropertyType == typeof(String))
  15:                 {
  16:                     value = value.ToString();
  17:                 }
  18:                 else if ((typeof(IConvertible).IsAssignableFrom(propertyInfo.PropertyType) == true) && (typeof(IConvertible).IsAssignableFrom(value.GetType()) == true))
  19:                 {
  20:                     value = System.Convert.ChangeType(value, propertyInfo.PropertyType);
  21:                 }
  22:             }
  23:         }
  24:  
  25:         return (value);
  26:     }
  27:     #endregion
  28:  
  29:     #region Public override methods
  30:     public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
  31:     {            
  32:         if (String.IsNullOrEmpty(entry.Expression) == true)
  33:         {
  34:             return (new CodePrimitiveExpression(String.Empty));
  35:         }
  36:         else
  37:         {
  38:             return (new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(this.GetType()), "GetValue"), new CodePrimitiveExpression(entry.Expression.Trim()), new CodePropertyReferenceExpression(new CodeArgumentReferenceExpression("entry"), "PropertyInfo")));
  39:         }
  40:     }
  41:     #endregion
  42:  
  43:     #region Public override properties
  44:     public override Boolean SupportsEvaluate
  45:     {
  46:         get
  47:         {
  48:             return (true);
  49:         }
  50:     }
  51:     #endregion
  52: }

Next, the code for each expression builder:

   1: [ExpressionPrefix("SPContext")]
   2: public class SPContextExpressionBuilder : SPBaseExpressionBuilder
   3: {
   4:     #region Public static methods
   5:     public static Object GetValue(String expression, PropertyInfo propertyInfo)
   6:     {
   7:         SPContext context = SPContext.Current;
   8:         Object expressionValue = DataBinder.Eval(context, expression.Trim().Replace('\'', '"'));
   9:  
  10:         expressionValue = Convert(expressionValue, propertyInfo);
  11:  
  12:         return (expressionValue);
  13:     }
  14:  
  15:     #endregion
  16:  
  17:     #region Public override methods
  18:     public override Object EvaluateExpression(Object target, BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
  19:     {
  20:         return (GetValue(entry.Expression, entry.PropertyInfo));
  21:     }
  22:     #endregion
  23: }

 

   1: [ExpressionPrefix("SPFarmProperty")]
   2: public class SPFarmPropertyExpressionBuilder : SPBaseExpressionBuilder
   3: {
   4:     #region Public static methods
   5:     public static Object GetValue(String propertyName, PropertyInfo propertyInfo)
   6:     {
   7:         Object propertyValue = SPFarm.Local.Properties[propertyName];
   8:  
   9:         propertyValue = Convert(propertyValue, propertyInfo);
  10:  
  11:         return (propertyValue);
  12:     }
  13:  
  14:     #endregion
  15:  
  16:     #region Public override methods
  17:     public override Object EvaluateExpression(Object target, BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
  18:     {
  19:         return (GetValue(entry.Expression, entry.PropertyInfo));
  20:     }
  21:     #endregion
  22: }

 

   1: [ExpressionPrefix("SPField")]
   2: public class SPFieldExpressionBuilder : SPBaseExpressionBuilder
   3: {
   4:     #region Public static methods
   5:     public static Object GetValue(String fieldName, PropertyInfo propertyInfo)
   6:     {
   7:         Object fieldValue = SPContext.Current.ListItem[fieldName];
   8:  
   9:         fieldValue = Convert(fieldValue, propertyInfo);
  10:  
  11:         return (fieldValue);
  12:     }
  13:  
  14:     #endregion
  15:  
  16:     #region Public override methods
  17:     public override Object EvaluateExpression(Object target, BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
  18:     {
  19:         return (GetValue(entry.Expression, entry.PropertyInfo));
  20:     }
  21:     #endregion
  22: }

 

   1: [ExpressionPrefix("SPIsInAudience")]
   2: public class SPIsInAudienceExpressionBuilder : SPBaseExpressionBuilder
   3: {
   4:     #region Public static methods
   5:     public static Object GetValue(String audienceName, PropertyInfo info)
   6:     {
   7:         Debugger.Break();
   8:         audienceName = audienceName.Trim();
   9:  
  10:         if ((audienceName.StartsWith("'") == true) && (audienceName.EndsWith("'") == true))
  11:         {
  12:             audienceName = audienceName.Substring(1, audienceName.Length - 2);
  13:         }
  14:  
  15:         AudienceManager manager = new AudienceManager();
  16:         Object value = manager.IsMemberOfAudience(SPControl.GetContextWeb(HttpContext.Current).CurrentUser.LoginName, audienceName);
  17:  
  18:         if (info.PropertyType == typeof(String))
  19:         {
  20:             value = value.ToString();
  21:         }
  22:  
  23:         return(value);
  24:     }
  25:  
  26:     #endregion
  27:  
  28:     #region Public override methods
  29:     public override Object EvaluateExpression(Object target, BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
  30:     {
  31:         return (GetValue(entry.Expression, entry.PropertyInfo));
  32:     }
  33:     #endregion
  34: }

 

   1: [ExpressionPrefix("SPIsInGroup")]
   2: public class SPIsInGroupExpressionBuilder : SPBaseExpressionBuilder
   3: {
   4:     #region Public static methods
   5:     public static Object GetValue(String groupName, PropertyInfo info)
   6:     {
   7:         groupName = groupName.Trim();
   8:  
   9:         if ((groupName.StartsWith("'") == true) && (groupName.EndsWith("'") == true))
  10:         {
  11:             groupName = groupName.Substring(1, groupName.Length - 2);
  12:         }
  13:  
  14:         Object value = SPControl.GetContextWeb(HttpContext.Current).CurrentUser.Groups.OfType<SPGroup>().Any(x => String.Equals(x.Name, groupName, StringComparison.OrdinalIgnoreCase));
  15:  
  16:         if (info.PropertyType == typeof(String))
  17:         {
  18:             value = value.ToString();
  19:         }
  20:  
  21:         return(value);
  22:     }
  23:  
  24:     #endregion
  25:  
  26:     #region Public override methods
  27:     public override Object EvaluateExpression(Object target, BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
  28:     {
  29:         return (GetValue(entry.Expression, entry.PropertyInfo));
  30:     }
  31:     #endregion
  32: }

 

   1: [ExpressionPrefix("SPProperty")]
   2: public class SPPropertyExpressionBuilder : SPBaseExpressionBuilder
   3: {
   4:     #region Public static methods
   5:     public static Object GetValue(String propertyName, System.Reflection.PropertyInfo propertyInfo)
   6:     {
   7:         SPServiceContext serviceContext = SPServiceContext.GetContext(HttpContext.Current);
   8:         UserProfileManager upm = new UserProfileManager(serviceContext);
   9:         UserProfile up = upm.GetUserProfile(false);
  10:         Object propertyValue = (up[propertyName] != null) ? up[propertyName].Value : null;
  11:  
  12:         propertyValue = Convert(propertyValue, propertyInfo);
  13:  
  14:         return (propertyValue);
  15:     }
  16:  
  17:     #endregion
  18:  
  19:     #region Public override methods
  20:     public override Object EvaluateExpression(Object target, BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
  21:     {
  22:         return (GetValue(entry.Expression, entry.PropertyInfo));
  23:     }
  24:     #endregion
  25: }

 

   1: [ExpressionPrefix("SPQueryString")]
   2: public class SPQueryStringExpressionBuilder : SPBaseExpressionBuilder
   3: {
   4:     #region Public static methods
   5:     public static Object GetValue(String parameterName, PropertyInfo propertyInfo)
   6:     {
   7:         Object parameterValue = HttpContext.Current.Request.QueryString[parameterName];
   8:  
   9:         parameterValue = Convert(parameterValue, propertyInfo);
  10:  
  11:         return (parameterValue);
  12:     }
  13:  
  14:     #endregion
  15:  
  16:     #region Public override methods
  17:     public override Object EvaluateExpression(Object target, BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
  18:     {
  19:         return (GetValue(entry.Expression, entry.PropertyInfo));
  20:     }
  21:     #endregion
  22: }

 

   1: [ExpressionPrefix("SPWebProperty")]
   2: public class SPWebPropertyExpressionBuilder : SPBaseExpressionBuilder
   3: {
   4:     #region Public static methods
   5:     public static Object GetValue(String propertyName, PropertyInfo propertyInfo)
   6:     {
   7:         Object propertyValue = SPContext.Current.Web.AllProperties[propertyName];
   8:  
   9:         propertyValue = Convert(propertyValue, propertyInfo);
  10:  
  11:         return (propertyValue);
  12:     }
  13:  
  14:     #endregion
  15:  
  16:     #region Public override methods
  17:     public override Object EvaluateExpression(Object target, BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
  18:     {
  19:         return (GetValue(entry.Expression, entry.PropertyInfo));
  20:     }
  21:     #endregion
  22: }

Registration

You probably know how to register them, but here it goes again: add this following snippet to your Web.config file, inside the configuration/system.web/compilation/expressionBuilders section:

   1: <add expressionPrefix="SPContext" type="MyNamespace.SPContextExpressionBuilder, MyAssembly, Culture=neutral, Version=1.0.0.0, PublicKeyToken=xxx" />
   2: <add expressionPrefix="SPFarmProperty" type="MyNamespace.SPFarmPropertyExpressionBuilder, MyAssembly, Culture=neutral, Version=1.0.0.0, PublicKeyToken=xxx" />
   3: <add expressionPrefix="SPField" type="MyNamespace.SPFieldExpressionBuilder, MyAssembly, Culture=neutral, Version=1.0.0.0, PublicKeyToken=xxx" />
   4: <add expressionPrefix="SPIsInAudience" type="MyNamespace.SPIsInAudienceExpressionBuilder, MyAssembly, Culture=neutral, Version=1.0.0.0, PublicKeyToken=xxx" />
   5: <add expressionPrefix="SPIsInGroup" type="MyNamespace.SPIsInGroupExpressionBuilder, MyAssembly, Culture=neutral, Version=1.0.0.0, PublicKeyToken=xxx" />
   6: <add expressionPrefix="SPProperty" type="MyNamespace.SPPropertyExpressionBuilder, MyAssembly, Culture=neutral, Version=1.0.0.0, PublicKeyToken=xxx" />
   7: <add expressionPrefix="SPQueryString" type="MyNamespace.SPQueryStringExpressionBuilder, MyAssembly, Culture=neutral, Version=1.0.0.0, PublicKeyToken=xxx" />
   8: <add expressionPrefix="SPWebProperty" type="MyNamespace.SPWebPropertyExpressionBuilder, MyAssembly, Culture=neutral, Version=1.0.0.0, PublicKeyToken=xxx" />

I’ll leave it up to you to figure out the best way to deploy this to your server! Winking smile

Comments

Anna said:

This works well for properties that are ints, dates, etc.  But what about for a sintrg property where the value could contain special characters?  In particular, I'm pretty sure values like  coop  and  co-op  would be sorted together by the default CompareTo for sintrgs in this code.  Short of doing some kind of ugly if-then-else in the delegate, how can this be made to use the ordinal type of sintrg compare?

# February 2, 2013 6:13 AM