[ Полезный рекламный блок ]
Попробуйте свои силы в игре, где ваши навыки программирования на C# станут решающим фактором. Переходите по ссылке 🔰.
В этой статье, рассмотрим процесс построения пагинации в стиле «Показать еще» в проекте, который продемонстрирует совместное использование ASP.NET Core MVC и Entity Framework Core. Проект будет простым, но близким к реальности, приступим.
Создание и настройка проекта
Чтобы создать проект ShowMore, запустите Visual Studio и выберите в меню File (Файл) — New Project (Создать Проект). Укажите шаблон проекта ASP.NET Core Web Application (Веб-приложение ASP.NET Core). Введите ShowMore, в поле Name, на следующей странице укажите Framework .Net 7.0 и нажмите кнопку Create:
Конфигурация подключения
Для начала загрузим библиотеку Entity Framework Core Sql Server:
Или через Package Manager Console:
1 |
Install-Package Microsoft.EntityFrameworkCore.SqlServer |
Перейдем в файл appsettings.json и пропишем конфигурацию подключения и логирования:
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=productsStoreDb;Trusted_Connection=True;" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Information" } }, "AllowedHosts": "*" } |
Строки подключения определяются в файле appsettings.json, в коде выше, представлено определение строки подключения для БД приложения GameStore. В проекте применяется версия LocalDB продукта SQL Server, которая спроектирована специально для разработчиков и не требует конфигурирования или учетных данных.
Создание класса контекста данных
В обеспечении доступа к данным в БД инфраструктура Entity Framework Core полагается на класс контекста БД. Чтобы снабдить пример приложения контекстом, добавьте папку Data, а в нее файл класса по имени ApplicationContext.cs со следующим кодом:
1 2 3 4 5 6 7 8 |
public class ApplicationContext : DbContext { public ApplicationContext(DbContextOptions<ApplicationContext> context) : base(context) { Database.EnsureCreated(); } public DbSet<Product> Products { get; set; } } |
Класс контекста БД соответственно прост — хотя ситуация изменится с ростом сложности модели данных в ваших проектах.
Модель и Репозиторий
Модель для приложения Show будет основана на списке товаров. Создайте папку Models и добавьте в нее файл класса по имени Product.cs со следующим содержимым:
1 2 3 4 5 6 7 |
public class Product { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public decimal Price { get; set; } } |
использованием паттерна «Хранилище» (Repository), в котором интерфейс определяет свойства и методы, предназначенные для доступа к данным, а для работы с механизмом хранения данных применяется класс реализации. Преимущество использования паттерна «Хранилище» связано с облегчением модульного тестирования части MVC приложения, а также с тем, что детали, касающиеся хранения данных, скрыты от остальных частей приложения.
Чтобы создать интерфейс хранилища, создайте папку Interfaces и добавьте в нее файл интерфейса по имени IProduct.cs со следующим содержимым:
1 2 3 4 |
public interface IProduct { Task<IEnumerable<Product>> GetProductsAsync(int page, int pageSize); } |
Создайте папку Repository и добавьте в нее файл класса по имени ProductRepository.cs со следующим содержимым:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class ProductRepository : IProduct { private readonly ApplicationContext _context; public ProductRepository(ApplicationContext context) { _context = context; } public async Task<IEnumerable<Product>> GetProductsAsync(int page, int pageSize) { return await _context.Products.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync(); } } |
В приложении ASP.NET Core MVC, доступ к объектам контекста данных управляется с использованием внедрения зависимостей и потому в класс ProductRepository был добавлен конструктор, принимающий объект ApplicationContext, который будет предоставлен средством внедрения зависимостей во время выполнения.
Конфигурирование поставщика базы данных и класса контекста
Добавьте в класс Program.cs операторы конфигурации, чтобы сообщить инфраструктуре Entity Framework Core о том, каким образом использовать строку подключения, которую должен применять поставщик БД, и как управлять классом контекста:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// Add services to the container. builder.Services.AddControllersWithViews(); //Новый код builder.Services.AddTransient<IProduct, ProductRepository>(); IConfigurationRoot _confString = new ConfigurationBuilder(). SetBasePath(AppDomain.CurrentDomain.BaseDirectory).AddJsonFile("appsettings.json").Build(); builder.Services.AddDbContext<ApplicationContext>(options => options.UseSqlServer(_confString.GetConnectionString("DefaultConnection"))); //Новый код конец var app = builder.Build(); |
Расширяющий метод AddDbContext<T>() применяется для настройки класса контекста, указывает инфраструктуре Entity Framework Core, какой поставщик БД использовать (в этом случае посредством метода UseSqlServer(), но для каждого поставщика БД предусмотрен свой метод), и предоставляет строку подключения.
Начальные данные
Нередко возникает необходимость, чтобы база данных к моменту первого обращения приложения уже содержала начальные данные, например, базовые роли и учетную запись администратора.
Для инициализации базы данных начальными ролями и пользователями, в папке Data, определим класс DbInit, со следующим содержимым:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public class DbInit { private readonly ApplicationContext _context; public DbInit(ApplicationContext context) { _context = context; } public async Task InitializeAsync() { if (!await _context.Products.AnyAsync()) { List<Product> products = new List<Product>(); for (int i = 1; i <= 30; i++) { Product product = new Product { Name = "Product " + i, Description = "This is the description for Product " + i, Price = (decimal)(i * 10.99) // Example price calculation }; products.Add(product); } _context.Products.AddRange(products); await _context.SaveChangesAsync(); } } } |
Используем данный класс, в классе Program после var app = builder.Build();:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; try { await new DbInit(services.GetRequiredService<ApplicationContext>()).InitializeAsync(); } catch (Exception ex) { var logger = services.GetRequiredService<ILogger<Program>>(); logger.LogError(ex, "An error occurred while seeding the database."); } } |
Здесь с помощью метода services.GetRequiredService() получаем сервис ApplicationContext и передаем их его метод InitializeAsync. В итоге при первом запуске в базу данных будут добавлены все необходимые данные.
Запустим приложение и проверим, чтобы база данных успешно создалась, а таблицы с ролями и пользователями были заполнены:
Уважаемые энтузиасты программирования на C#!
С наилучшими пожеланиями,
[Леонид / Dijix Company]
Контроллер и представления
Перейдем в контроллер Home и определим в нем следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class HomeController : Controller { private readonly IProduct _products; public HomeController(IProduct products) { _products = products; } [Route("/")] [HttpGet] public async Task<IActionResult> Index(int page = 1, int pageSize = 10) { return View(await _products.GetProductsAsync(page, pageSize)); } [Route("get-more-products")] [HttpGet] public async Task<IActionResult> GetMoreProducts(int page = 1, int pageSize = 10) { return PartialView("_ProductsPartial",await _products.GetProductsAsync(page, pageSize)); } } |
Поскольку информации о продукте не мало, вынесем его в отдельное представление. Перейдем в папку Views / Shared и добавим частичное представление _ProductPartial.cshtml, со следующим содержимым:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
@model Product <div class="row justify-content-center mb-3"> <div class="col-md-12 col-xl-10"> <div class="card shadow-0 border rounded-3"> <div class="card-body"> <div class="row"> <div class="col-md-12 col-lg-3 col-xl-3 mb-4 mb-lg-0"> <div class="bg-image hover-zoom ripple rounded ripple-surface"> <img src="https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Products/img%20(4).webp" class="w-100" /> <a href="#!"> <div class="hover-overlay"> <div class="mask" style="background-color: rgba(253, 253, 253, 0.15);"></div> </div> </a> </div> </div> <div class="col-md-6 col-lg-6 col-xl-6"> <h5>@Model.Name</h5> <p class="mb-4 mb-md-0">@Model.Description</p> </div> <div class="col-md-6 col-lg-3 col-xl-3 border-sm-start-none border-start"> <div class="d-flex flex-row align-items-center mb-1"> <h4 class="mb-1 me-1">$@Model.Price</h4> </div> <h6 class="text-success">Free shipping</h6> <div class="d-flex flex-column mt-4"> <button class="btn btn-primary btn-sm" type="button">Details</button> <button class="btn btn-outline-primary btn-sm mt-2" type="button">Add to cart</button> </div> </div> </div> </div> </div> </div> </div> |
Перейдем в представление Views / Home / Index.cshtml и определим в нем следующее содержимое:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
@{ ViewData["Title"] = "All Products"; } @model IEnumerable<Product> <div class="container py-5" id="products"> @foreach (Product product in Model) { @await Html.PartialAsync("_ProductPartial", product) } </div> <div class="text-center"> <button id="showMore" class="btn btn-primary">Show more</button> </div> @section Scripts{ <script> var page = 2; //Начинаем со второй страницы, так как первая уже показана var pageSize = 10; $("#showMore").click(function () { $.ajax({ url: "/get-more-products?page=" + page + "&pageSize" + pageSize, success: function (data) { $("#products").append(data); page++; } }); }); </script> } |
Страница отображает начальный список продуктов. При нажатии на кнопку «Show more», срабатывает JavaScript код, с помощью которого отправляется запрос по адресу «/get-more-products?page=» + page + «&pageSize», в ответ на данный запрос мы получаем частичное представление с данными о товарах, которое успешно добавляем в основной блок на страницу.
Перейдем в папку Views / Shared и добавим частичное представление _ProductsPartial.cshtml, со следующим содержимым:
1 2 3 4 5 6 |
@model IEnumerable<Product> @foreach (Product product in Model) { @await Html.PartialAsync("_ProductPartial", product) } |
С помощью данного представления мы сможем поставлять определенное количество продуктов в основную страницу. Запустим проект и проверим его работу.
Я надеюсь, что вам понравилось читать эту статью, и она оказалась легкой для понимания. Пожалуйста, дайте мне знать, если у вас есть какие-либо комментарии или исправления.
Так же вам может быть интересна предыдущая статья — Создание приложения с использованием ASP.NET Core MVC и EF Core.
Вы хотите научится писать код на языке программирования C#?
Создавать различные информационные системы, состоящие из сайтов, мобильных клиентов, десктопных приложений, телеграмм-ботов и т.д.
Переходите к нам на страницу Dijix и ознакомьтесь с условиями обучения, мы специализируемся только на индивидуальных занятиях, как для начинающих, так и для более продвинутых программистов. Вы можете взять как одно занятие для проработки интересующего Вас вопроса, так и несколько, для более плотной работы. Благодаря личному кабинету, каждый студент повысит качество своего обучения, в вашем распоряжении:
- Доступ к пройденному материалу
- Тематические статьи
- Библиотека книг
- Онлайн тестирование
- Общение в закрытых группах
Живи в своем мире, программируй в нашем.