Reputation: 57
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?
Upvotes: 3
Views: 483
Reputation: 13060
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.
Upvotes: 5
Reputation: 2415
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);
}
Upvotes: 1