Сортировка

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 09.12.2019

Рассмотрим, как добавить в приложение сортировку данных. Для начала собственно создадим новый проект ASP.NET Core по типу ASP.NET Core Web App (Model-View-Controller). Назовем его, к примеру, SortApp.

Сортировка в ASP.NET Core

Далее добавим в проект в папку Models следующие классы User и Company:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
	public int CompanyId { get; set; }
    public Company Company { get; set; }
}
public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }

    public List<User> Users { get; set; }
    public Company()
    {
        Users = new List<User>();
    }
}

Для взаимодействия с MS SQL Server через Entity Framework добавим в проект через Nuget пакет Microsoft.EntityFrameworkCore.SqlServer. Далее добавим в папку Models новый класс UsersContext, через который будем взаимодействовать с бд:

using Microsoft.EntityFrameworkCore;

namespace SortApp.Models
{
    public class UsersContext : DbContext
    {
        public DbSet<User> Users { get; set; }
        public DbSet<Company> Companies { get; set; }
        public UsersContext(DbContextOptions<UsersContext> options)
            : base(options)
        { 
			Database.EnsureCreated();
		}
    }
}

В файле Startup.cs установим контекст данных и подключение к базе данных:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using SortApp.Models;
using Microsoft.EntityFrameworkCore;

namespace SortApp
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            string connection = "Server = (localdb)\\mssqllocaldb; Database = userstoredb; Trusted_Connection=true";
            services.AddDbContext<UsersContext>(options =>
                options.UseSqlServer(connection));
            services.AddControllersWithViews();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseDeveloperExceptionPage();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

Итак, в классе User есть три свойства (не считая Id), по которым можно вести сортировку: Name, Age, Company. Сортировка может быть по возрастанию и по убыванию. Таким образом, мы получаем шесть критериев сортировки: сортировка по свойству Name по возрастанию, сортировка по свойству Name по убыванию и так далее. Для описания всех этих критериев добавим в папку Models перечисление SortState:

public enum SortState
{
    NameAsc,	// по имени по возрастанию
    NameDesc,	// по имени по убыванию
    AgeAsc,	// по возрасту по возрастанию
    AgeDesc,	// по возрасту по убыванию
    CompanyAsc,	// по компании по возрастанию
    CompanyDesc	// по компании по убыванию
}

Это перечисление хранит критерии сортировки в виде числовых констант.

Теперь изменим код контроллера HomeController:

using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using SortApp.Models;

namespace SortApp.Controllers
{
    public class HomeController : Controller
    {
        UsersContext db;
        public HomeController(UsersContext context)
        {
            this.db = context;
			// добавим начальные данные для тестирования
			if(db.Companies.Count() == 0)
            {
                Company oracle = new Company { Name = "Oracle" };
                Company google = new Company { Name = "Google" };
                Company microsoft = new Company { Name = "Microsoft" };
                Company apple = new Company { Name = "Apple" };

                User user1 = new User { Name = "Олег Васильев", Company = oracle, Age = 26 };
                User user2 = new User { Name = "Александр Овсов", Company = oracle, Age = 24 };
                User user3 = new User { Name = "Алексей Петров", Company = microsoft, Age = 25 };
                User user4 = new User { Name = "Иван Иванов", Company = microsoft, Age = 26 };
                User user5 = new User { Name = "Петр Андреев", Company = microsoft, Age = 23 };
                User user6 = new User { Name = "Василий Иванов", Company = google, Age = 23 };
                User user7 = new User { Name = "Олег Кузнецов", Company = google, Age = 25 };
                User user8 = new User { Name = "Андрей Петров", Company = apple, Age = 24 };

                db.Companies.AddRange(oracle, microsoft, google, apple);
                db.Users.AddRange(user1, user2, user3, user4, user5, user6, user7, user8);
                db.SaveChanges();
            }
        }
        public async Task<IActionResult> Index(SortState sortOrder = SortState.NameAsc)
        {
            IQueryable<User> users = db.Users.Include(x=>x.Company);

            ViewData["NameSort"] = sortOrder==SortState.NameAsc ? SortState.NameDesc : SortState.NameAsc;
            ViewData["AgeSort"] = sortOrder == SortState.AgeAsc ? SortState.AgeDesc : SortState.AgeAsc;
            ViewData["CompSort"] = sortOrder == SortState.CompanyAsc ? SortState.CompanyDesc : SortState.CompanyAsc;

            users = sortOrder switch
            {
                SortState.NameDesc => users.OrderByDescending(s => s.Name),
                SortState.AgeAsc => users.OrderBy(s => s.Age),
                SortState.AgeDesc => users.OrderByDescending(s => s.Age),
                SortState.CompanyAsc => users.OrderBy(s => s.Company.Name),
                SortState.CompanyDesc => users.OrderByDescending(s => s.Company.Name),
                _ => users.OrderBy(s => s.Name),
            };
            return View(await users.AsNoTracking().ToListAsync());
        }
    }
}

Критерий сортировки передается в метод Index в виде параметра sortOrder. Мы ожидаем, что он будет равен одной из констант перечисления SortState. Если никакое значение не передается, по по умолчанию считаем, что используется сортировка по имени по возрастанию: SortState sortOrder = SortState.NameAsc

Далее устанавливаем ряд переменных во ViewData, которые будут хранить значения для трех столбцов. Например, для свойства Name определено значение ViewData["NameSort"]. Если параметр sortOrder равен константе SortState.NameAsc, то ViewData["NameSort"] присваивается значение SortState.NameDesc. То есть если ранее значение ViewData["NameSort"] указывало на сортировку по имени по возрастанию, то теперь после сортировки оно будет указывать на сортировку по имени по убыванию. И наоборот.

Далее в методе в конструкции switch..case смотрит на значение sortOrder и производим сортировку с помощью метода OrderBy/OrderByDescending.

В конце передаем полученные данные в представление.

И определим код в представлении Index.cshtml:

@using SortApp.Models
@{
    ViewData["Title"] = "Home Page";
}
@model IEnumerable<User>
<h1>Список пользователей</h1>
<table class="table">
    <tr>
        <th>
            <a asp-action="Index" asp-route-sortOrder="@ViewBag.NameSort">
                Имя
            </a>
        </th>
        <th>
            <a asp-action="Index" asp-route-sortOrder="@ViewBag.AgeSort">
                Возраст
            </a>
        </th>
        <th>
            <a asp-action="Index" asp-route-sortOrder="@ViewBag.CompSort">
                Компания
            </a>
        </th>
    </tr>
    @foreach (User u in Model)
    {
        <tr><td>@u.Name</td><td>@u.Age</td><td>@u.Company.Name</td></tr>
    }
</table>

В представлении каждый заголовок столбца будет представлять ссылку. То есть мы нажимаем на столбец, и отправляется запрос на сервер, который выполняет фильтрацию.

Каждая ссылка определена с помощью tag-хелпера:

<a asp-action="Index" asp-route-sortOrder="@ViewBag.NameSort">Имя</a>

Атрибут asp-route-sortOrder позволяет задать параметр sortOrder, который будет передавать на сервер выбранный критерий сортировки. И в результате будет создавать ссылка типа следующей:

http://localhost:xxxxx/?sortOrder=NameAsc

В итоге весь проект будет выглядеть так:

Проект ASP.NET Core для сортировки объектов

После запуска проекта с помощью нажатия на заголовки столбцов в таблице мы сможем отсортировать объекты по нужному столбцу:

Сортировка в ASP.NET Core MVC
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850