3

I want to use the filterType parameter to define what property on the Stock object to Filter by.

[HttpGet("{searchText}/{filterType}")] 
public async Task<ActionResult<List<Stock>>> Get(string searchText, string filterType)
 {
    List<Stock> v = await this._context.StockView.Where(w => w.[filterType] == searchText).ToListAsync();

    return this.Ok(v);
 }

Is there a way of doing this whereby i can use a string parameter to define a property on the Object to restrict by?

1
  • 1
    Have you tried reflection? Commented Aug 22, 2019 at 10:58

2 Answers 2

5

You could use an Expression Tree to dynamically build a Linq where clause to filter on dynamic property.

I know this is probably a lot to digest but, here goes. Replace StockItem with the type of the StockView DbSet

[HttpGet("{searchText}/{filterType}")] 
public async Task<ActionResult<List<Stock>>> Get(string searchText, string filterType)
{
    var queryableStockView = this._context.StockView;

    // w =>
    var param = Expression.Parameter(typeof(StockItem), "w");

    var propertyInfo = typeof(StockItem).GetProperty(filterType);
    if (propertyInfo == null)
        throw new Exception($@"Property ""{property}"" was not found");

    // w.[filterType]
    var left = Expression.Property(param, propertyInfo);

    // searchText
    var right = Expression.Constant(searchText, typeof(string));

    // w.[filterType] == searchText
    var expression = Expression.Equal(left, right);
    
    // Bring it all together
    // Where(w => (w.[filterType] == searchText))
    var whereExpression = Expression.Call(
        typeof(Queryable),
        nameof(System.Linq.Enumerable.Where),
        new Type[] { queryableStockView.ElementType },
        queryableStockView.Expression,
        Expression.Lambda<Func<StockItem, bool>>(expression, new ParameterExpression[] { param })
    );

    // Run query against the database                                     
    var filteredItems = queryableStockView.Provider.CreateQuery<StockItem>(whereExpression);

    var v = await filteredItems.ToListAsync();

    return this.Ok(v);
 }

The dynamically generated Linq Expression should get translated to SQL without any issues.

Sign up to request clarification or add additional context in comments.

Comments

1

to do what you are wanting you would need to write a bunch of mapping code.(out of scope you would need to show what you have tried)

it would be easier to execute raw sql that way you can set the field dynamically.

alternatively you can setup your data to support your searching... see below.

[HttpGet("{searchText}/{filterType}")] 
public async Task<ActionResult<List<Stock>>> Get(string searchText, string filterType)
 {
    var v = await this._context.StockView
              .Where(x => x.Type == filterType 
                       && x.SearchField == searchText).TolistAsync();

    return this.Ok(v);
 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.