1

I need help on how to show up my 2nd extension method "OrderBy" (shown below) in my ASP.Net MVC Controller.

The 1st extension method "Where" is showing up but not "OrderBy". What do i need to do to make it show up? Or maybe my code is wrong in the 2nd extension method?

NOTE: I have already imported the namespace in my controller by adding:

using MyApplication.Models;

Here's my code for the extension methods:

namespace MyApplication.Models
{
    public static class ExtensionMethods
    {
        public static IQueryable<T> Where<T>(this IQueryable<T> source, string     columnName, string value, string filterType)
        {

        ParameterExpression table = Expression.Parameter(typeof(T), "x");
        MemberExpression column = Expression.PropertyOrField(table, columnName);
        Expression valueExpression = null;
        Expression where = null;

        if (column.Type.FullName.Contains("String")) {...}
        if (column.Type.FullName.Contains("Int32")) {...}
        if (column.Type.FullName.Contains("DateTime")){...}

        var predicate = Expression.Lambda<Func<T, bool>>(where, table);

        return source.Where(predicate);
        }

        public static IOrderedQueryable<T> OrderBy<T,TKey>(this IQueryable<T> source,   string columnName)
        {
            ParameterExpression table = Expression.Parameter(typeof(T), "x");
            Expression column = Expression.PropertyOrField(table, columnName);
            var keySelector = Expression.Lambda<Func<T, TKey>>(column,table);
            return source.OrderBy(keySelector);
        }
    }
}

Here's the code in the Controller:

using MyApplication.Models;

...

using (MyContext context = new MyContext())
{

    IQueryable<Shipper> query = context.Shippers;
    query = query.Where(property,value,filterType);
    query = query.OrderBy(property);
}

Any help is greatly appreciated.

-Mark


EDIT:

Here's my new OrderBy extension method:

public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string columnName, bool asc)
    {
        var entityType = typeof(T);
        var property = entityType.GetProperty(columnName);
        ParameterExpression table = Expression.Parameter(entityType, "x");
        Expression column = Expression.PropertyOrField(table, columnName);

        string sortMethod="";

        if (asc) { sortMethod = "OrderBy"; }
        else { sortMethod = "OrderByDescending"; }

        var keySelector = Expression.Lambda(column,table);

        MethodCallExpression resultExp = Expression.Call(
            typeof(Queryable),
            sortMethod,
            new Type[] { entityType, property.PropertyType },
            source.Expression,
            Expression.Quote(keySelector));

        return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(resultExp);
    }

1 Answers1

3

The problem is that your extension method has two type parameters, but only one of them can be used in type inference by the compiler - TKey isn't mentioned at all in the normal parameter list, which is what's used in type inference.

I suspect this would find your extension method:

// Of course I don't know that it's meant to be string. You should use whatever
// type is appropriate.
query = query.OrderBy<Shipper, string>(property);

That may not be ideal in terms of usage, but at least it steers you in the right direction in terms of why it wasn't working. If you want to rely on type inference, you'll need to get rid of TKey as a type parameter, instead figuring that out - and then performing the rest of your logic - with reflection.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • can you please rewrite Op orderby function?? i did'nt understood your point unfortunately – Ehsan Sajjad May 07 '14 at 04:04
  • @EhsanSajjad: I don't see what you mean - I've changed the *calling* code for it to pick up on the extension method; the extension method doesn't need to be changed at all. – Jon Skeet May 07 '14 at 04:05
  • in calling where you put property what will be passed exactly? – Ehsan Sajjad May 07 '14 at 04:06
  • @EhsanSajjad: Sorry, I didn't understand that comment at all. All I've done is copy the code where the OP was *trying* to call the extension method before, and add type arguments. (I've guessed at the `string` part. I'll clarify that in my answer.) – Jon Skeet May 07 '14 at 04:06
  • what you have wrote for calling what is meant by sting in angle brackets and the sceond one in propert in parenthesis as in extension method OP has two parameters source and column on which orderby will be applied – Ehsan Sajjad May 07 '14 at 04:08
  • 1
    @EhsanSajjad: Those are generic type arguments. It's like when you specify a type argument to construct a list of strings: `var x = new List()`. The two types in angle brackets are type arguments; `property` is a regular argument. – Jon Skeet May 07 '14 at 04:08
  • +1 for the explanation now got a bit understanding of it – Ehsan Sajjad May 07 '14 at 04:13
  • @Jon: You're right. Thanks for pointing out my mistake. Meanwhile, I found an old post [here](http://stackoverflow.com/questions/1469531/linq-to-sql-repository-pattern-dynamic-orderby/1489207#1489207) where I based my updated code. Not sure if this is using reflection though. I still need to learn about that reflection. I will update my question with the new code for the extension method. Thanks Again! – MArk ABram CUenco DAvid May 07 '14 at 06:43