asp.net-mvcsortingpaginationrepository-pattern

Sorting and Paging on repository


I have a simple ASP.NET MVC application which has possibility to search, filter and page a list of vehicle makes. I implemented sorting, filtering and paging on controller (on "Index" action) following the tutorials from kudvenkat on youtube https://www.youtube.com/watch?v=srN56uxw76s

So, this is my "VehicleMakeController" and "Index" action:

 public class VehicleMakeController : Controller
{
    private readonly IVehicleRepository _vehicleRepository;

    public VehicleMakeController()
    {
        _vehicleRepository = new VehicleRepository(new VehicleDbContext());
    }

    // GET: VehicleMake
    public ActionResult Index(string search, int? page, string sort)
    {
        ViewBag.SortNameParameter = string.IsNullOrEmpty(sort) ? "Name desc" : "";

        var makes = _vehicleRepository.AllMakes;

        switch (sort)
        {
            case "Name desc":
                makes = makes.OrderByDescending(x => x.Name);
                break;
            default:
                makes = makes.OrderBy(x => x.Name);
                break;
        }

        if (search == null)
        {
            return View(makes.ToList().ToPagedList(page ?? 1, 5));
        }

        return View(makes.Where(x => x.Name.ToLower().StartsWith(search)).ToList().ToPagedList(page ?? 1, 5));
}

and this is my "Index" view:

@using PagedList;
@using PagedList.Mvc;
@model IPagedList<Project.Service.Entities.VehicleMake>

@{
ViewBag.Title = "Vehicle Makes";
}

<h2>@ViewBag.Title</h2>

@Html.ActionLink("Create", "CreateVehicleMake")

<br/>
<br/>

@using (@Html.BeginForm("Index", "VehicleMake", FormMethod.Get))
{
<p>
    @Html.TextBox("search") <input type="submit" value="Search"/>
</p>
}

<table class="table">
<thead>
<tr>
    <th>@Html.ActionLink("Name", "Index", new { sort = ViewBag.SortNameParameter, search = Request.QueryString["search"] })</th>
    <th></th>
</tr>
</thead>
<tbody>

@foreach (var vehicleMake in Model)
{
    <tr>
        <td>@vehicleMake.Name</td>
        <td>@Html.ActionLink("Edit", "EditVehicleMake", new {id = vehicleMake.Id})</td>
        <td>@Html.ActionLink("Delete", "DeleteVehicleMake", new {id = vehicleMake.Id})</td>
    </tr>
}
</tbody>
</table>

 @Html.PagedListPager(Model, page => Url.Action("Index", new { page,  search   = Request.QueryString["search"], sort = Request["sort"]}),
 new PagedListRenderOptions() { Display = PagedListDisplayMode.IfNeeded,   DisplayPageCountAndCurrentLocation = true})

@if (!Model.Any())
{
 <b>No rows match search criteria!</b>
}

In application I'm using repository pattern and I have "AllMakes" method to retrieve all vehicle makes from database. So, this is my "VehicleRepository":

public class VehicleRepository : IVehicleRepository
{

private readonly VehicleDbContext _context;


public VehicleRepository(VehicleDbContext context)
{
    _context = context;
}

public IEnumerable<VehicleMake> AllMakes => _context.VehicleMakes;

}

and this is my "IVehicleRepository" interface:

public interface IVehicleRepository
{
IEnumerable<VehicleMake> AllMakes { get; }
}

My DbContext class is following:

public class VehicleDbContext : DbContext
{
public VehicleDbContext() : base("VehicleDbContext")
{

}

public DbSet<VehicleMake> VehicleMakes { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{

}
}

This everything works OK, but now I want to implement sorting and paging in repository and remove it from controller. The parameters should be passed trough get/query method. I'm not sure how to do this and I would appreciate any help.


Solution

  • You can declare a function in IVehicleRepository and implement it.

    public interface IVehicleRepository
    {
        IEnumerable<VehicleMake> AllMakes { get; }
    
        List<VehicleMake> GetVehicleWithPagination(string search, int? page, string sort);
    }
    
    public class VehicleRepository : IVehicleRepository
    {
    
        // your old code
    
        public List<VehicleMake> GetVehicleWithPagination(string search, int? page, string sort)
        {
            // this is your code from controller 
            switch (sort)
            {
                case "Name desc":
                    makes = AllMakes.OrderByDescending(x => x.Name);
                    break;
                default:
                    makes = AllMakes.OrderBy(x => x.Name);
                    break;
            }
    
            if (search == null)
            {
                return AllMakes.ToList().ToPagedList(page ?? 1, 5);
            }
        }
    }
    

    And your controller:

    public ActionResult Index(string search, int? page, string sort)
    {
        ViewBag.SortNameParameter = string.IsNullOrEmpty(sort) ? "Name desc" : "";
        return View(_vehicleRepository.GetVehicleWithPagination(search, page, sort));
    }