A service that returns paged Products with optional filtering In order to better understand what the code does, I've captured this screencast.

Basically, I have a products page and a user can filter products.

CODE

Here is the Page action method on my ProductController:

public ActionResult Page(SearchViewModel search, int page = 1)
{
  var viewModel = _productService.GetPagedProducts(search, page);
  PopulateDropDownSelectListsForSearchVm(viewModel.Search);
  return View(viewModel);
}


That PopulateDropDownSelectListsForSearchVm is a helper method that sits within the controller.

Here is the implementation of the GetPagedProducts method on the IProductService interface:

public ProductPageViewModel GetPagedProducts(SearchViewModel search, int page = 1)
{
  int totalNumberOfProducts;
  if (HaveSearchTermsChanged(search)) page = 1;
  var products = _context.Products.Where(p =&gt; p.IsDeleted == search.ShowDeleted).AsQueryable();
  if (search.CategoryId != 0) products = products.Where(p =&gt; p.CategoryId == search.CategoryId);
  if (search.BrandId != 0) products = products.Where(p =&gt; p.BrandId == search.BrandId);
  if (search.QualityId != 0) products = products.Where(p =&gt; p.QualityId == search.QualityId);

  if (!string.IsNullOrEmpty(search.SearchTerm))
  {
    products = products
                .Where(p =&gt; p.Name == search.SearchTerm.Trim())
                .OrderBy(p =&gt; p.Name);
    totalNumberOfProducts = products.Count();
    products = products.Skip(_recordsPerPage * (page - 1)).Take(_recordsPerPage);
  }
  else
  {
    products = products.OrderBy(p =&gt; p.Name);
    totalNumberOfProducts = products.Count();
    products = products.Skip(_recordsPerPage * (page - 1)).Take(_recordsPerPage);
  }

  var productPageVm = new ProductPageViewModel
  {
    Products = ProductViewModelFactory.BuildListOfProductViewModels(products.ToList()),
    Pagination = new PaginationViewModel
    {
      CurrentPage = page,
      RecordsPerPage = _recordsPerPage,
      TotalRecords = totalNumberOfProducts
    },
    Search = search
  };

  TrackCurrentSearchTerm(productPageVm);
  return productPageVm;
}


Readability is really important to me, and right now it just doesn't feel readable. What can I do to improve the overall code, and have it be very readable?
I would suggest you to move the pagination settings to your SearchModel

Then you can have an utility/extension method or whatever you whish with this signature

public IQueryable&lt;Product&gt; ApplyFilter(IQueryable&lt;Product&gt; productQuery, SearchModel model)


and you write there ll the filtering business, so you can re use it in more methods and simplify the readability of your main method.

Finally, I would not recommend to rewrite your if statements like this

if (search.CategoryId != 0)
{
    products = products.Where(p =&gt; p.CategoryId == search.CategoryId);
}