In this article, we’re going to tackle the topic of searching in ASP.NET Core Web API. Searching is one of those functionalities that can make or break your API, and the level of difficulty when implementing it can vary greatly depending on your specifications.

If you need to implement a basic searching feature where you are just trying to search one field in the database, you can easily implement it. On the other hand, if it’s a multi-column multi-term search you would probably be best of with some of the great search libraries out there like Lucene.NET which are already optimized and proven.

You can find the source code on the GitHub repo. If you want to follow along with the article, you can use the start branch and if you want to get the final solution or if you get stuck, switch to the final branch.

NOTE: Some degree of previous knowledge is needed to follow this article. It relies heavily on the ASP.NET Core Web API series on Code Maze, so if you are not sure how to set up the database or how the underlying architecture works, we strongly suggest you go through the series.

In this article we are going to learn:

Let’s dive right into it.

What is Searching?

There is no doubt in our minds that you’ve seen a search field on almost every website on the internet.

It’s easy to find something when we are familiar with the website structure or when a website is not that large. But, if we want to find the most relevant topic for us, or if we don’t know what we’re going to find, or maybe we’re first-time visitors of a large website, we’re probably going to use a search field.

Basic search is not that hard to implement, but if taken lightly, the search function can be useless. Sometimes it’s better to just revert back to Google, or use a google dork to search the website. If you are not familiar with Google dorks, we highly recommend you try them out.

In our simple project, one use case of a search would be to find an owner by his/her name.

Let’s see how we can achieve that.

How to Implement Searching in ASP.NET Core Web API

Since we’re going to implement the most basic search in our project, the implementation won’t be complex at all. We have all we need infrastructure-wise since we already covered paging and filtering. We’ll just extend our implementation a bit.

What we want to achieve is something like this:
https://localhost:5001/api/owners?name=Anna Bosh

This should return just one result: Anna Bosh. Of course, the search needs to work together with filtering and paging, so that’s one of the things that we need to keep in mind too.

Like we did with filtering, we’re going to extend our OwnerParameters class first since we’re going to send our search query as a query parameter:

public class OwnerParameters : QueryStringParameters
{
	public uint MinYearOfBirth { get; set; }
	public uint MaxYearOfBirth { get; set; } = (uint)DateTime.Now.Year;

	public bool ValidYearRange => MaxYearOfBirth > MinYearOfBirth;

	public string Name { get; set; }
}

We’ve added just one new property – Name.

Simple as that.

Now we can write queries with name="term" in them.

The next thing we need to do is to actually implement the search functionality in our OwnerRepository class:

public PagedList<Owner> GetOwners(OwnerParameters ownerParameters)
{
	var owners = FindByCondition(o => o.DateOfBirth.Year >= ownerParameters.MinYearOfBirth &&
								o.DateOfBirth.Year <= ownerParameters.MaxYearOfBirth);

	SearchByName(ref owners, ownerParameters.Name);

	return PagedList<Owner>.ToPagedList(owners.OrderBy(on => on.Name),
		ownerParameters.PageNumber,
		ownerParameters.PageSize);
}

private void SearchByName(ref IQueryable<Owner> owners, string ownerName)
{
	if (!owners.Any() || string.IsNullOrWhiteSpace(ownerName))
		return;

	owners = owners.Where(o => o.Name.ToLower().Contains(ownerName.Trim().ToLower()));
}

First, we need to check if the name parameter is actually sent, by doing a simple IsNullOrWhiteSpace check on the Name property. If it’s not, there’s no point in searching for anything really.

After that, we are using the Where clause with trimmed Name string (just in case). We are doing this after the filtering is done to search through fewer results.

Everything else stays the same.

That’s it for our implementation. As you can see it really isn’t that hard since it is the most basic search, and we already had an infrastructure set.

Testing Our Implementation

The only thing that remains is to test our solution.

First, let’s recall how our database table looks.

database owners

Now, let’s try to find Anna:
https://localhost:5001/api/owners?name=Anna Bosh

Sure enough, we get our result.

search result

If we entered her full name, Anna Bosh, the result would be the same. That’s because we are looking for the entire term by default with .Contains().

For an additional example, let’s try to find all the owners that contain the letter “o”:

https://localhost:5001/api/owner?name=o

Now, we should get three results instead of one:

[
  {
    "id": "261e1685-cf26-494c-b17c-3546e65f5620",
    "name": "Anna Bosh",
    "dateOfBirth": "1974-11-14T00:00:00",
    "address": "27 Colored Row"
  },
  {
    "id": "24fd81f8-d58a-4bcc-9f35-dc6cd5641906",
    "name": "John Keen",
    "dateOfBirth": "1980-12-05T00:00:00",
    "address": "61 Wellfield Road"
  },
  {
    "id": "66774006-2371-4d5b-8518-2177bcf3f73e",
    "name": "Nick Somion",
    "dateOfBirth": "1998-12-15T00:00:00",
    "address": "North sunny address 102"
  }
]

Now let’s combine that with filtering and paging:

https://localhost:5001/api/owner?name=o&minYearOfBirth=1974&maxYearOfBith=1985&pageSize=1&pageNumber=2

Can you guess which result we should get (hint, it’s a single result)? If you’ve guessed, leave us a comment in the comments section.

That’s it, we’ve successfully implemented and tested our search functionality.

Let’s sum that up.

Conclusion

In this article we’ve covered:

  • What searching is and how it’s different from filtering
  • The way to implement searching in ASP.NET Core Web API
  • How to test searching in our API
  • Combining search with our existing solutions for paging and filtering

Hope this short article was useful to you. If you have any questions or suggestions, please leave us a comment and we’ll get to you as quickly as possible.

Next up, we’ll cover sorting.