Problem
How to implement sorting in ASP.NET Core Web API.
Solution
Create an empty project, add NuGet package:
Update the 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 the sorting data.
- public class SortingParams
- {
- public string SortBy { get; set; } = "";
- }
Add an extension method to IQueryable.
- public static IQueryable<T> Sort<T>(this IQueryable<T> source, string sortBy)
- {
- if (source == null)
- throw new ArgumentNullException("source");
-
- if (string.IsNullOrEmpty(sortBy))
- throw new ArgumentNullException("sortBy");
-
- source = source.OrderBy(sortBy);
-
- return source;
- }
Add output models to send the data via API.
- public class MovieOutputModel
- {
- 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 service and domain model.
- public interface IMovieService
- {
- List<Movie> GetMovies(FilteringParams filteringParams);
- }
- public class MovieService : IMovieService
- {
- public List<Movie> GetMovies(SortingParams sortingParams)
- {
- var query = this.movies.AsQueryable();
-
- if (!string.IsNullOrEmpty(sortingParams.SortBy))
- query = query.Sort(sortingParams.SortBy);
-
- 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 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(SortingParams sortingParams)
- {
- var model = service.GetMovies(sortingParams);
-
- var outputModel = new MovieOutputModel
- {
- Items = model.Select(m => ToMovieInfo(m)).ToList(),
- };
- return Ok(outputModel);
- }
- }
Output
Discussion
Let’s walk through the sample code step-by-step.
- Sorting information is usually received via query parameters. The POCO SortingParams simply hold this information and pass it to the service (or repository).
- Service will, then, sort the data and return a list.
- Linq.Dynamic.Core provides an extension method on IQueryable that accepts the sorting expression as a string.
- We build our output model MovieOutputModel and return the status code 200 (OK). The output model contains a list of movies. As discussed in the previous post (CRUD), we map the domain model to an output model (MovieInfo in this case).
Note
The sample is a very basic implementation of sorting. You will get a ParseException if the field specified for sorting doesn’t exist on the model. Typically, you would either verify field’s existence or catch the exception.
Source Code
GitHub