Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
Рассмотрим, как добавить в приложение сортировку данных. Для начала собственно создадим новый проект ASP.NET Core по типу ASP.NET Core Web App (Model-View-Controller). Назовем его, к примеру, SortApp.
Далее добавим в проект в папку 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
В итоге весь проект будет выглядеть так:
После запуска проекта с помощью нажатия на заголовки столбцов в таблице мы сможем отсортировать объекты по нужному столбцу: