C
C#2y ago
Anton

❔ ASP.NET Core search

Can someone give me a few pointers at how to implement a generic search system? My initial thought was like here https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/search?view=aspnetcore-7.0 checking every possible filter and then applying them, but a generic system would be better if there are many filters. So like a ISearchFilter that would update the built database query, a request model with ISearchFilter[] which I'd loop through to apply the filters. The thing is that the ASP.NET Core binding system will have to instantiate the right implementations of ISearchFilter by the name given in the request body, and then there's the question of how bad would be dynamic queries like this in EF Core?
// an interface kinda like this
public interface ISearchFilter<T>
{
IQueryable<T> Apply(IQueryable<T> e);
}
// an interface kinda like this
public interface ISearchFilter<T>
{
IQueryable<T> Apply(IQueryable<T> e);
}
// a request body kinda like this
{
"Filters": [
{
"Type": "FilterType",
"SomeProperty": 5
},
{
// blah
}
]
}
// a request body kinda like this
{
"Filters": [
{
"Type": "FilterType",
"SomeProperty": 5
},
{
// blah
}
]
}
Is there some sort of built-in support for things like this, or do I have to roll out my own system?
12 Replies
Angius
Angius2y ago
You could use https://github.com/Biarity/Sieve for example
GitHub
GitHub - Biarity/Sieve: ⚗️ Clean & extensible Sorting, Filtering, a...
⚗️ Clean & extensible Sorting, Filtering, and Pagination for ASP.NET Core - GitHub - Biarity/Sieve: ⚗️ Clean & extensible Sorting, Filtering, and Pagination for ASP.NET Core
Anton
Anton2y ago
[HttpGet]
public Task<List<WhateverDto>> Search([FromBody] ISearchFilter<Whatever> filters)
{
var q = _dbContext.Whatevers.AsQueryable();
foreach (var filter in filters)
q = filter(q);
return await q.MapToGetDto().ToListAsync();
}
[HttpGet]
public Task<List<WhateverDto>> Search([FromBody] ISearchFilter<Whatever> filters)
{
var q = _dbContext.Whatevers.AsQueryable();
foreach (var filter in filters)
q = filter(q);
return await q.MapToGetDto().ToListAsync();
}
thanks I'll take a look
Callum
Callum2y ago
Maybe I'm biased but the OData project may also allow this
Callum
Callum2y ago
OData
Tutorial: Creating a Service with ASP.NET Core OData 8.0 for .NET 5
In this document, we will walk through the process of creating a local service using OData 8.0, which is optimized to support ASP.NET Core 5.
Callum
Callum2y ago
It doesn't do just filtering, it does paging, let's you expand into sub entities and a bunch of other nifty things, and you can specify which pieces to enable
Anton
Anton2y ago
alright
Callum
Callum2y ago
It might be a bit of overkill, but I've used it in like 6 projects now and when I first used it, it made a lot of my gripes about using APIs go away As the OData specification is also a standard that's used by various SAPs which now means you at least have a standard for how to say filter this collection to an API
Anton
Anton2y ago
sounds good is it just me, or does the api of the sieve library linked before look kinda fishy
Callum
Callum2y ago
I had a quick look, looks good to me.. I've seen far worse GraphQL was an adventure in .NET I didn't enjoy exploring too much, but can also solve this problem
Anton
Anton2y ago
It might be that I often expect too much from libraries
Callum
Callum2y ago
Yeah, the OData library has been pretty good to me and they've used the OASIS committee to help standardise API interactions so I've found it very cool, but it was also the first one I was introduced to for this problem so kinda bias haha
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.