diff --git a/Rock/Web/UI/Controls/Grid/Grid.cs b/Rock/Web/UI/Controls/Grid/Grid.cs index f09691a97cc..9586e245b35 100644 --- a/Rock/Web/UI/Controls/Grid/Grid.cs +++ b/Rock/Web/UI/Controls/Grid/Grid.cs @@ -2444,6 +2444,15 @@ protected void Actions_ExcelExportClick( object sender, EventArgs e ) continue; } + // Skip indexer properties. They cannot be read without an index argument, so the + // prop.GetValue( item, null ) call below would throw a TargetParameterCountException. + // LavaDataObject exposes a public "this[string key]" indexer, so any grid whose data + // source type inherits from it lands here. + if ( prop.GetIndexParameters().Length > 0 ) + { + continue; + } + props.Add( prop ); } @@ -2748,6 +2757,14 @@ private List FilterDynamicObjectPropertiesCollection( Type dataSou var dropProperties = typeof( RockDynamic ).GetProperties().Select( a => a.Name ); additionalMergeProperties = additionalMergeProperties.Where( a => !dropProperties.Contains( a.Name ) ).ToList(); } + // If this is a LavaDataObject class, don't include any of the properties that are inherited from + // LavaDataObject. This mirrors the non-RockLiquid branch below. Without it, LavaDataObject's + // "this[string key]" indexer is treated as an exportable "Item" column. + else if ( typeof( LavaDataObject ).IsAssignableFrom( dataSourceObjectType ) ) + { + var dropProperties = typeof( LavaDataObject ).GetProperties().Select( a => a.Name ); + additionalMergeProperties = additionalMergeProperties.Where( a => !dropProperties.Contains( a.Name ) ).ToList(); + } } else { diff --git a/Rock/Web/UI/Controls/Grid/LavaField.cs b/Rock/Web/UI/Controls/Grid/LavaField.cs index 791ee334ddb..756552743ae 100644 --- a/Rock/Web/UI/Controls/Grid/LavaField.cs +++ b/Rock/Web/UI/Controls/Grid/LavaField.cs @@ -243,7 +243,9 @@ private Dictionary ToGridItemsDictionary( GridViewRow gridViewRo /// The data item. private void PopulateDataItemPropertiesDictionary( object dataItem ) { - var dataItemProperties = dataItem.GetType().GetProperties().Where( a => a.GetGetMethod() != null && !a.GetGetMethod().IsVirtual ).ToArray(); + // Exclude indexer properties (e.g. LavaDataObject's "this[string key]"): they cannot be read + // without an index argument, so GetValue( dataItem, null ) on them throws a TargetParameterCountException. + var dataItemProperties = dataItem.GetType().GetProperties().Where( a => a.GetGetMethod() != null && !a.GetGetMethod().IsVirtual && a.GetIndexParameters().Length == 0 ).ToArray(); this.DataItemPropertiesDictionary = new Dictionary(); // add MergeFields based on the associated ColumnHeaderText of each property of the dataitem (without spaces or special chars)