Problem
How to implement filtering in ASP.NET Core Web API.
Solution
To an empty project update Startup class to add services and middleware for MVC,
- public void ConfigureServices(
- IServiceCollection services)
- {
- services.AddSingleton<IMovieService, MovieService>();
-
- services.AddMvc();
- }
-
- public void Configure(
- IApplicationBuilder app,
- IHostingEnvironment env)
- {
- app.UseDeveloperExceptionPage();
- app.UseMvcWithDefaultRoute();
- }
Add model to hold filtering data
- public class FilteringParams
- {
- public string FilterBy { get; set; } = "";
- }
Add a service and domain model
- public interface IMovieService
- {
- List<Movie> GetMovies(FilteringParams filteringParams);
- }
- public class MovieService : IMovieService
- {
- public List<Movie> GetMovies(FilteringParams filteringParams)
- {
- var query = this.movies.AsQueryable();
-
- var filterBy = filteringParams.FilterBy.Trim().ToLowerInvariant();
- if (!string.IsNullOrEmpty(filterBy))
- {
- query = query
- .Where(m => m.LeadActor.ToLowerInvariant().Contains(filterBy)
- || m.Title.ToLowerInvariant().Contains(filterBy)
- || m.Summary.ToLowerInvariant().Contains(filterBy));
- }
-
- return query.ToList();
- }
- }
-
- public class Movie
- {
- public int Id { get; set; }
- public string Title { get; set; }
- public int ReleaseYear { get; set; }
- public string Summary { get; set; }
- public string LeadActor { get; set; }
- }
Add output models (to send data via API)
- public class MovieOutputModel
- {
- public int Count { get; set; }
- public List<MovieInfo> Items { get; set; }
- }
-
- public class MovieInfo
- {
- public int Id { get; set; }
- public string Title { get; set; }
- public int ReleaseYear { get; set; }
- public string Summary { get; set; }
- public string LeadActor { get; set; }
- public DateTime LastReadAt { get; set; }
- }
Add a controller for the API with service injected via constructor,
- [Route("movies")]
- public class MoviesController : Controller
- {
- private readonly IMovieService service;
-
- public MoviesController(IMovieService service)
- {
- this.service = service;
- }
-
- [HttpGet(Name = "GetMovies")]
- public IActionResult Get(FilteringParams filteringParams)
- {
- var model = service.GetMovies(filteringParams);
-
- var outputModel = new MovieOutputModel
- {
- Count = model.Count,
- Items = model.Select(m => ToMovieInfo(m)).ToList(),
- };
- return Ok(outputModel);
- }
- }
Output
Discussion
Let’s walk through the sample code step-by-step,
- Filtering information is usually received via query parameters. The POCO FilteringParamssimply hold this information and passes to service (or repository).
- Service will then filter the data and returns a list.
- We build our output model MovieOutputModel and return status code 200(OK). The output model contains,
- Total number of items returned by the server.
- List of movies. As discussed in previous post (CRUD) we map the domain model to an output model (MovieInfo in this case).
Source Code
GitHub