4

I am trying to pass a Lambda Expression to a Web API 2 call and not sure how to make this work.

Let me give you some background

Setup a Web API 2 that utilizes Entity Framework to communicate to the Database.

My applications ultimately call up to the Web API 2 to be able to communicate with the Database. My company ultimately requires this to allow added security to the Data Access Layer.

We have built a repository on the App Side that communicates with the Web API just fine. However one of the functions we want to add is a FIND function that incorporates a Lambda Expression.

public IEnumerable<T> FindAll(Func<T, bool> exp)
{
    HttpClientHandler hndlr = new HttpClientHandler();
    hndlr.UseDefaultCredentials = true;
    HttpClient httpClient = new HttpClient(hndlr);

    httpClient.BaseAddress = new Uri(ADMS.Utilities.Settings.DALService);
    HttpResponseMessage response = httpClient.GetAsync(string.Format("api/{0}/{1}", typeof(T).Name, exp)).Result;

    if (response.IsSuccessStatusCode)
    {
       return response.Content.ReadAsAsync<IEnumerable<T>>().Result.ToList();
    }
    return null;
}

Question I have is now on the Web API 2 side in the controller how do I get this to accept the Lambda Expression? What do I need to put in the controller to see this? Do I need to convert the Lambda Expression?

kevin c
  • 795
  • 1
  • 14
  • 29
  • related: http://stackoverflow.com/questions/6443433/how-can-i-pass-a-lambda-expression-to-a-wcf-service . basically, not 'out of the box' can you serialize a expression tree. BUT *do you really WANT to allow that*? – hometoast Jan 20 '15 at 17:36
  • EXACTLY - not sure I WANT that maybe the better question is how should I do a Find option in the Controller so I am not querying the entire DB – kevin c Jan 20 '15 at 17:41
  • You're really doing this on the wrong side of the airtight hatchway, so to speak. Define an interface that's good enough for your cases, and handle constructing the actual LINQ query on the other side. You want to limit the input as much as possible. And instead of passing `Func`, you really need some expression tree. Ideally *not* `Expression>` (way too many options), but... – Luaan Jan 21 '15 at 08:56

1 Answers1

5

You cannot directly pass a Lamda Expression to Web Api 2. You are right when you say you have to convert it somehow. Here are a few options.

Use odata

This works with Entity Framework, and comes with templates in Visual Studio (2012 / 2013). odata sits on top of Web Api 2. Basically, there are a bunch of operators already defined for you (equals, contains, greater than, etc.). With odata and entity framework everything is pretty much done for you. This should already be part of Visual Studio by default, it's a Microsoft pushed thing.http://www.odata.org/

Convert Manually

Each of your methods in your controllers can take in your required parameters (int skip, int take, string where, string order by) and then it is up to you to apply that. This means you'll have to try and come up with your own rules and syntax to make this work.

Use dynamic linq

As mentioned in the related answers. This is a way to use linq build dynamically at runtime. You can essentially pass that in the query string and pass it forward. You will have to figure out what your Repository accepts vs what your Api accepts and how to convert or pass that through. You will also have to be careful that you not allow more than what you really want. http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library

hatcyl
  • 2,190
  • 2
  • 21
  • 24