2

I'm currently working with ASP Dynamic Data for the first time and I'm trying to build a filter. Our users have a need to locate items in a list based upon whether or not the item is a child of a selected parent (our items can have more than one parent).

The items in question are Segments and each Segment has a property called RouteIds, of type IEnumerable, which is a collection of all of the Segment's parent Ids.

I've gotten to this point in overriding the GetQueryable method in my filter, but I keep getting exceptions thrown on the last line shown:

ConstantExpression ce = Expression.Constant(int.Parse(this.ddlRouteNames.SelectedValue));
ParameterExpression pe = Expression.Parameter(source.ElementType);
MemberExpression me = Expression.Property(pe, this.Column.Name);
var callExpression = Expression.Call(typeof(Enumerable), "Contains", new Type[] { me.Type }, ce, me);

The thought is that a user would select the appropriate Route from a DropDownList and then I'd check to see if the Segment's RouteIds property contains that Route's Id.

Any pointers on how to get this working?

Edit - Here is the exception:

No generic method 'Contains' on type 'System.Linq.Enumerable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.

svick
  • 236,525
  • 50
  • 385
  • 514
Sonny Boy
  • 7,848
  • 18
  • 76
  • 104
  • I've probably read this question completely wrong but could you not achieve the same more simply with a LINQ query? http://www.rapidprogramming.com/tutorial/C-Sharp-LINQ-Query-Expressions-375 – Luke Baughan May 02 '13 at 21:32
  • @bUKaneer, SQL-translatable LINQ queries have to use expression trees. Sometimes you can have the compiler do that legwork for you. Other times (when you only know the symbols at runtime as in the OP's example: `this.Column.Name`) you must build the expression trees the hard way (as above). – Kirk Woll May 02 '13 at 21:35
  • 1
    @SonnyBoy, you say "keep getting exceptions thrown" but you don't tell us what exceptions were thrown. – Kirk Woll May 02 '13 at 21:36
  • My apologies! Here's the exception: "No generic method 'Contains' on type 'System.Linq.Enumerable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic." – Sonny Boy May 02 '13 at 21:38
  • @Sonny, I think you might have forgotten to pass the enumerable itself as the first argument to `.Contains`. – Kirk Woll May 02 '13 at 21:40
  • @Kirk - How do I go about doing that? This is the first time I've really gotten under the hood of Linq. – Sonny Boy May 02 '13 at 21:42
  • Ive never used Dynamic Data before - fascinating, could this post be adapted? http://stackoverflow.com/questions/3612777/asp-net-dynamic-data-textsearch-custom-filter-template – Luke Baughan May 02 '13 at 21:43

1 Answers1

2

There are two problems in your code:

  1. Your parameters are backwards. The first parameter has to be the collection, the second the item you're searching for.
  2. Your type argument is IEnumerable<int>, when it should be just int.

So, the fixed code is:

var callExpression = Expression.Call(
    typeof(Enumerable), "Contains", new[] { typeof(int) }, me, ce);

But it seems all the parts of your expression are not actually dynamic, so maybe something like that following would work too:

Expression<Func<Segment, bool>> expression =
    s => s.RouteIds.Contains(int.Parse(this.ddlRouteNames.SelectedValue));
svick
  • 236,525
  • 50
  • 385
  • 514
  • Thank you. No more exceptions, though I've yet to verify that my approach is working. The expression will be dynamic in the future, however, as we will be adapting this approach to several of parent/child relationships. – Sonny Boy May 03 '13 at 13:45