Создание профессионального веб-приложения на ASP.NET Core MVC

freeCodeCamp.org 189 тыс. 2 ч 30 мин 17 мин 20.03.2024
Главное

«Безопасность — это не то, что можно добавить в конце, а фундамент, на котором строится архитектура», — убеждает инструктор, объясняя, почему цены товаров должны жить на серверах Stripe, а не в коде клиента. В этом руководстве мы разбираем создание современного приложения на ASP.NET Core MVC: от настройки связей «многие ко многим» в базе данных до интеграции многопользовательского редактора и защищенной системы платежей.

🍕 Архитектура MVC, настройка Entity Framework и проектирование моделей 0:00

Архитектура ASP.NET Core MVC 0:53

Курс от автора под псевдонимом Allan из проекта Koda future начинается с анонса трех разноплановых проектов: от простого веб-приложения для ресторанного меню до полноценного клона Google Docs и платформы с интеграцией платежной системы Stripe. Ранее в разговоре автор вскользь упоминает эти будущие сложные этапы разработки, однако отправной точкой для изучения веб-технологий становится детальный разбор классического паттерна MVC (Model-View-Controller).

Архитектура веб-приложения ASP.NET Core разделена на несколько изолированных слоев, каждый из которых выполняет свою строгую функцию. Модели представляют собой обычные C#-классы, свойства которых напрямую отображаются на столбцы таблиц в физической базе данных. Для связи программного кода с сервером баз данных используется строка подключения (connection string), хранящая адрес сервера и параметры авторизации; этот конфигурационный элемент традиционно выносится в отдельный файл appsettings.json.

Ключевым звеном в этой цепи выступает контекст данных (Context) — специальный класс-посредник, предоставляющий готовые C#-методы для манипуляции данными, такие как добавление записей или выборка строк. С контекстом напрямую взаимодействуют контроллеры, которые перехватывают и обрабатывают входящие запросы пользователей. Наконец, за визуальное отображение отвечает слой представлений (Views) — фронтенд-составляющая интерфейса, которая динамически наполняется данными из контекста и рендерится в браузере. Первым практическим полигоном для этой архитектуры становится приложение Food Menu.

Настройка Entity Framework Core и конфигурация базы данных 3:24

Создав новый проект по стандартному шаблону ASP.NET Core MVC под именем "Menu", разработчик переходит к подготовке инфраструктуры данных. Для этого через менеджер пакетов NuGet устанавливается базовый стек библиотек, необходимый для работы с ORM-системой.

В состав обязательного окружения входят три компонента:

После успешной установки пакетов Аллан запускает SQL Server Management Studio (SSMS) для получения точного имени локального сервера. Создав базу данных с именем "Menu database", он копирует сгенерированную строку подключения в файл appsettings.json, регистрируя её под ключом DefaultConnection. На этом этапе автор дает важную техническую ремарку: в строку необходимо добавить параметр Encrypt=False, так как подключение происходит локально без строгой аутентификации по паролю. Финальным штрихом конфигурации базы данных становится регистрация контекста в файле Program.cs, где строка инициализации связывает созданный класс контекста с импортированной из настроек строкой подключения.

Проектирование моделей данных для меню и связей «многие ко многим» 4:41

Разработка логики приложения начинается с создания структуры данных в папке Models. Аллан проектирует класс Dish (первоначально названный Menu), добавляя свойства целочисленного идентификатора Id, строки Name, ссылки на изображение ImageUrl и цены Price с типом данных double. Следом создается модель Ingredient, описывающая компоненты блюд и содержащая только идентификатор и наименование.

Поскольку одно блюдо может состоять из множества ингредиентов, а один и тот же ингредиент может входить в состав разных позиций меню, возникает классическая задача реализации связи «многие ко многим». Для этого Аллан создает промежуточную связующую модель DishIngredient. Она содержит внешние ключи DishId и IngredientId, а также навигационные свойства, ссылающиеся на родительские объекты. Взаимная связь замыкается добавлением списков List<DishIngredient> в оба исходных класса.

Для управления созданными сущностями в новой папке Data создается класс MenuContext, наследуемый от стандартного DbContext. В его конструктор передаются параметры конфигурации DbContextOptions. Отношения между таблицами детально настраиваются через Fluent API в переопределенном методе OnModelCreating. Здесь разработчик явно указывает составной первичный ключ для таблицы DishIngredient, состоящий из пары внешних идентификаторов, и прописывает каскадные связи для моделей Dish и Ingredient. В завершение структуры класса объявляются свойства DbSet для каждой из трех таблиц.

Чтобы приложение не запускалось с пустым экраном, Аллан организует первичную инициализацию данных (data seeding) прямо внутри конфигурации контекста. Он жестко прописывает в коде добавление пиццы «Маргарита» стоимостью 7.50 с URL-адресом картинки из Google. Затем генерирует два базовых ингредиента — томатный соус и моцареллу, после чего связывает их с пиццей через создание записей в DishIngredient с указанием соответствующих ID.

Реализация миграций базы данных и устранение ошибок 23:27

Когда программная модель полностью готова, наступает этап её переноса в физическую среду SQL Server. В консоли диспетчера пакетов Аллан вводит команду создания первой миграции: Add-Migration InitialMigration. Инструменты Entity Framework успешно генерируют файлы миграции, описывающие структуру будущих таблиц на основе C#-классов.

Однако первая попытка применить изменения к серверу с помощью команды Update-Database завершается ошибкой. Проблема оказывается в синтаксисе строки подключения внутри файла конфигурации. Вместо знака равенства Аллан случайно поставил двоеточие перед логическим значением флага шифрования: «Когда я вводил encrypt в строку подключения, там должно было быть не двоеточие, а знак равенства». После оперативного исправления конфигурации на Encrypt=False повторный запуск Update-Database завершается успешно, и таблицы создаются в СУБД. Полностью подготовив базу данных, разработчик переходит к созданию контроллера для управления меню.

🛠️ Разработка интерфейса: Контроллеры, Razor и динамический поиск 25:11

После того как архитектура данных и миграции базы данных были настроены (о чем шла речь в предыдущей части руководства), наступает этап визуализации. В ASP.NET Core MVC связующим звеном между данными и пользователем выступают контроллеры и представления (Views). Основная задача текущего этапа — превратить «сырые» таблицы SQL в интерактивное меню ресторана, где каждое блюдо имеет свое описание, цену и список ингредиентов.

Создание контроллера и логика отображения меню 25:27

Процесс начинается с создания MenuController, который будет обрабатывать входящие запросы. Ключевым моментом здесь является использование механизма внедрения зависимостей (Dependency Injection) для получения доступа к контексту базы данных MenuContext. Это позволяет контроллеру напрямую взаимодействовать с таблицами через Entity Framework.

Основной метод Index проектируется как асинхронный (async Task<IActionResult>). Это критически важно для производительности веб-приложения: пока база данных обрабатывает запрос, поток сервера не блокируется и может обслуживать других пользователей. Метод извлекает список всех блюд с помощью вызова _context.Dishes.ToListAsync() и передает его в представление.

В самом представлении Razor (Index.cshtml) используется строго типизированная модель — список объектов Dish. Для построения сетки интерфейса применяется фреймворк Bootstrap:

Особое внимание уделяется форматированию данных. Например, для корректного отображения цены используется метод .ToString("C2") (или аналогичное форматирование с точностью до двух знаков после запятой), что придает интерфейсу профессиональный вид.

Детализация блюд: работа со связями в Entity Framework 33:51

Одной из самых мощных функций ASP.NET Core является работа со связанными данными. Когда пользователь нажимает кнопку «Посмотреть детали» (View Dish), контроллер вызывает метод Details, принимающий уникальный ID блюда.

Однако простого поиска по ID недостаточно, так как информация об ингредиентах хранится в отдельных связанных таблицах. Чтобы выгрузить их одним запросом, применяется метод .Include(). В коде это выглядит как цепочка вызовов: сначала подключается промежуточная таблица DishIngredients, а затем — сама таблица Ingredients. Если блюдо с указанным ID не найдено, система возвращает стандартную страницу ошибки NotFound().

Разметка страницы деталей (Details.cshtml) отличается от главной страницы:

  1. Одиночная модель: В отличие от списка в Index, здесь на вход подается один объект Dish.
  2. Список ингредиентов: Для отображения состава блюда используется маркированный список, который заполняется через вложенный цикл foreach по коллекции model.DishIngredients.
  3. Навигация: Для удобства пользователя добавляется кнопка «Back to Menu», которая реализуется через вспомогательный тег (Tag Helper) asp-action="Index", автоматически генерирующий правильную ссылку.

Наполнение базы данных и ускоренная разработка 44:21

В процессе разработки часто возникает необходимость быстро добавить тестовые данные. Вместо того чтобы писать сложные скрипты инициализации (seeding) в коде C#, можно воспользоваться инструментами прямого управления БД. Использование SQL Server Management Studio (SSMS) позволяет вручную вводить названия блюд, цены и ссылки на изображения прямо в таблицы.

Например, в ходе демонстрации в меню добавляются пицца «Пепперони» и «Вегетарианская». Для изображений используются прямые URL-адреса из открытых источников. Важно помнить о связях: после добавления блюда необходимо вручную прописать его ID в таблице ингредиентов, чтобы связать, например, соус и моцареллу с конкретной новой пиццей. После сохранения изменений в SSMS данные мгновенно становятся доступны в веб-приложении благодаря динамическим запросам Entity Framework.

Интеграция функции поиска в навигационную панель 48:34

Завершающим этапом улучшения интерфейса в этой главе становится создание поисковой системы. Вместо стандартных ссылок «Home» и «Privacy», которые создаются шаблоном Visual Studio по умолчанию, в главный макет приложения (_Layout.cshtml) встраивается форма поиска.

Основные технические характеристики поисковой формы:

Логика фильтрации на стороне сервера строится на использовании LINQ. Когда контроллер получает строку поиска, он добавляет условие .Where(d => d.Name.Contains(searchString)) к базовому запросу к базе данных. Это позволяет пользователям мгновенно находить нужные позиции в меню по ключевым словам в названии.

💻 Создание клона Google Docs 57:36

Разработка собственного текстового редактора, вдохновленного функционалом Google Docs, — это амбициозный проект, требующий интеграции продвинутых инструментов форматирования. Основой системы становится ASP.NET Core MVC с настроенной аутентификацией Individual Accounts, что позволяет каждому пользователю создавать, хранить и редактировать персональные документы.

Для управления данными создается модель Document (или Doc), включающая следующие ключевые поля:

Важной деталью проектирования является требование обязательного наличия владельца у каждого документа, что реализуется через атрибут [Required] для поля UserID. Это обеспечивает целостность данных: при удалении аккаунта пользователя все связанные с ним документы также будут удалены из базы. Для визуального редактора используется библиотека TinyMCE. Её интеграция позволяет трансформировать стандартное поле textarea в полноценный интерфейс редактирования с панелью инструментов, похожей на MS Word или Google Docs, даже без использования платного API-ключа на этапе разработки.


🛡️ Аутентификация и права доступа 1:05:03

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

Реализация защиты строится на проверке UserID внутри методов Edit и Delete контроллера. С помощью конструкции, сопоставляющей идентификатор текущего авторизованного пользователя с владельцем документа, можно предотвратить несанкционированный доступ:

if (document.UserId != User.FindFirstValue(ClaimTypes.NameIdentifier))
{
    return NotFound();
}

Этот механизм гарантирует, что если пользователь попытается получить доступ к чужому документу через прямую ссылку, система вернет страницу Not Found, вместо того чтобы открыть чужие данные. Дополнительно весь контроллер защищается атрибутом [Authorize], который ограничивает доступ к функционалу исключительно для зарегистрированных пользователей. В процессе создания документа UserID автоматически подтягивается из системы Identity с помощью инъекции UserManager, при этом само поле скрывается от глаз пользователя в интерфейсе с помощью элемента input типа hidden.

-

💳 Интеграция Stripe: Настройка аккаунта и управление продуктами 1:35:22

После завершения работы над функционалом текстового редактора и настройки прав доступа для пользователей, о которых шла речь в предыдущих разделах, автор переходит к реализации третьего крупного проекта в рамках курса. Эта часть посвящена внедрению полноценной системы приема платежей в приложение на ASP.NET Core. Основным инструментом для решения этой задачи выбрана платформа Stripe — один из самых популярных и надежных сервисов для онлайн-эквайринга в мире.

Интеграция Stripe позволяет превратить обычное веб-приложение в коммерческую платформу, способную безопасно обрабатывать транзакции. Автор подчеркивает, что процесс интеграции, несмотря на кажущуюся сложность, достаточно прямолинеен и хорошо документирован, что делает его доступным даже для начинающих разработчиков.

Настройка аккаунта Stripe и работа с API-ключами 1:36:00

Первым шагом на пути к приему платежей является создание и настройка учетной записи на официальном сайте сервиса. Процесс регистрации на stripe.com стандартен и не занимает много времени. После подтверждения аккаунта разработчик получает доступ к личному кабинету (Dashboard), который служит центром управления всеми финансовыми операциями и техническими настройками.

Ключевым элементом взаимодействия между вашим ASP.NET Core приложением и серверами Stripe являются API-ключи. В разделе настроек разработчика представлены два типа ключей:

Секретный ключ необходим для аутентификации запросов при создании сессий оформления заказа (checkout sessions). Автор акцентирует внимание на том, что этот ключ должен храниться в строгом секрете и никогда не должен попадать в клиентский код, чтобы исключить возможность компрометации аккаунта.

Безопасность и формирование каталога продуктов 1:37:05

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

Такой подход считается наиболее безопасным по нескольким причинам:

  1. Защита от подмены цены: Если цена товара передается напрямую с фронтенда, злоумышленник может перехватить запрос и изменить стоимость.
  2. Валидация на стороне Stripe: При создании сессии оплаты сервер приложения передает только идентификатор цены (Price ID), а Stripe сам подтягивает актуальную стоимость из своей защищенной базы.

В качестве примера автор демонстрирует уже созданные товары, такие как футболка «Jordan» стоимостью 25 долларов. Для каждого такого продукта система генерирует уникальный API ID, который в дальнейшем используется в коде контроллеров ASP.NET Core для инициализации платежа.

Создание товаров: практический пример 1:38:13

Для наглядности процесса автор создает новый продукт — наручные часы «Money Watch». Процедура включает в себя несколько этапов, которые разработчик должен выполнить в интерфейсе Stripe:

После сохранения продукта он мгновенно становится доступным для интеграции. Разработчику остается только скопировать сгенерированный идентификатор цены, чтобы связать его с логикой своего интернет-магазина.

Использование документации Stripe для разработки 1:39:40

Сильной стороной Stripe является детальная документация, которая предлагает готовые шаблоны кода для различных языков программирования. Автор обращается к разделу Stripe Docs, чтобы продемонстрировать структуру будущего платежного модуля.

Документация предоставляет не только серверную логику (например, класс server.cs с методами создания платежных сессий), но и необходимые HTML-шаблоны. Типовая структура интеграции включает в себя:

Этот фундамент позволяет быстро развернуть систему приема платежей, минимизируя написание шаблонного кода и фокусируясь на бизнес-логике конкретного приложения.

💳 Создание сессий Stripe и проектирование базы данных продуктов 1:40:45

Создание checkout-сессий Stripe и проведение тестовых платежей 1:48:39

Для запуска полноценного платежного функционала в веб-приложении ASP.NET Core MVC первоначальная настройка начинается с конфигурации безопасности. Секретный ключ API Stripe переносится в файл appsettings.json <a class="ts" data-seconds="6072" href="#t=6072" title="Смотреть с 1:41:12" aria-label="Смотреть с 1:41:12"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>, что представляет собой наиболее защищенный и рекомендуемый метод управления конфиденциальными данными в коммерческой разработке. Затем внутри файла Program.cs этот ключ динамически извлекается и передается в глобальную конфигурацию биллинговой системы: StripeConfiguration.ApiKey = builder.Configuration.GetSection("Stripe")["SecretKey"] <a class="ts" data-seconds="6208" href="#t=6208" title="Смотреть с 1:43:28" aria-label="Смотреть с 1:43:28"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. Чтобы проект успешно компилировался и поддерживал экосистему Stripe, через менеджер пакетов NuGet в проект предварительно устанавливается официальная зависимость Stripe.net <a class="ts" data-seconds="6269" href="#t=6269" title="Смотреть с 1:44:29" aria-label="Смотреть с 1:44:29"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>.

После подготовки базовой инфраструктуры разработчик создает специализированный контроллер PaymentController <a class="ts" data-seconds="6309" href="#t=6309" title="Смотреть с 1:45:09" aria-label="Смотреть с 1:45:09"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a> и сопутствующие ему представления (Views). Структура включает в себя три ключевые страницы: стандартную страницу корзины с кнопкой оформления заказа, страницу успешного завершения транзакции (Success) и страницу отмены или сбоя операции (Cancel) <a class="ts" data-seconds="6405" href="#t=6405" title="Смотреть с 1:46:45" aria-label="Смотреть с 1:46:45"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. Центральной логической частью всего платежного конвейера становится метод CreateCheckoutSession <a class="ts" data-seconds="6531" href="#t=6531" title="Смотреть с 1:48:51" aria-label="Смотреть с 1:48:51"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. Внутри этого POST-метода инициализируется объект SessionCreateOptions, где детально определяются параметры будущей транзакции:

Непосредственное создание сессии берет на себя встроенный сервис SessionService, транслирующий структурированный запрос на серверы Stripe <a class="ts" data-seconds="6756" href="#t=6756" title="Смотреть с 1:52:36" aria-label="Смотреть с 1:52:36"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. После успешной генерации сессии на стороне шлюза контроллер перенаправляет пользователя на внешнюю платежную страницу Stripe, возвращая стандартный HTTP-статус 303 See Other <a class="ts" data-seconds="6756" href="#t=6756" title="Смотреть с 1:52:36" aria-label="Смотреть с 1:52:36"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. В режиме тестирования для симуляции реального покупателя применяется универсальный номер карты 4242 4242 4242 4242 <a class="ts" data-seconds="6852" href="#t=6852" title="Смотреть с 1:54:12" aria-label="Смотреть с 1:54:12"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. Итогом успешного прохождения сценария становится проверка транзакции: в панели управления Stripe в реальном времени отображается платеж от тестового пользователя James, подтверждающий корректность интеграции <a class="ts" data-seconds="6941" href="#t=6941" title="Смотреть с 1:55:41" aria-label="Смотреть с 1:55:41"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>.

Перенос каталога в базу данных и динамическая работа с Price ID 1:56:08

Постоянное использование жестко закодированных идентификаторов цен (Price ID) внутри контроллеров не подходит для масштабируемых систем. Чтобы сделать проект гибким, автор переходит к проектированию полноценного локального каталога продуктов, данные из которого будут извлекаться на лету для последующей передачи в Stripe <a class="ts" data-seconds="6993" href="#t=6993" title="Смотреть с 1:56:33" aria-label="Смотреть с 1:56:33"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. Стоит отметить, что ранее в разговоре они уже касались общих принципов построения моделей данных, поэтому интеграция новой сущности происходит по стандартному паттерну MVC.

Для реализации этого подхода в проекте создается папка Models и объявляется класс Item <a class="ts" data-seconds="7060" href="#t=7060" title="Смотреть с 1:57:40" aria-label="Смотреть с 1:57:40"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. Данная модель описывает структуру товара в репозитории и содержит следующий набор свойств:

Для организации взаимодействия объектного кода с реляционной базой данных разворачивается контекст данных MVCContext, наследующий базовые возможности DbContext <a class="ts" data-seconds="7106" href="#t=7106" title="Смотреть с 1:58:26" aria-label="Смотреть с 1:58:26"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. Чтобы предоставить приложению инструменты для работы с данными, разработчик подключает три критически важных пакета через менеджер NuGet: Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Tools (необходимый для генерации миграций) и Microsoft.EntityFrameworkCore.SqlServer <a class="ts" data-seconds="7175" href="#t=7175" title="Смотреть с 1:59:35" aria-label="Смотреть с 1:59:35"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. Внутри контекста регистрируется соответствующая таблица через свойство DbSet<Item> Items <a class="ts" data-seconds="7262" href="#t=7262" title="Смотреть с 2:01:02" aria-label="Смотреть с 2:01:02"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>.

Физическая база данных под названием StripeWebData создается на локальном сервере через среду SQL Server Management Studio (SSMS) <a class="ts" data-seconds="7316" href="#t=7316" title="Смотреть с 2:01:56" aria-label="Смотреть с 2:01:56"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. Настроенная строка подключения копируется из свойств среды и прописывается в конфигурационный файл appsettings.json в секцию ConnectionStrings:DefaultConnection, где параметру шифрования Encrypt принудительно присваивается значение false для обхода локальных ограничений безопасности <a class="ts" data-seconds="7360" href="#t=7360" title="Смотреть с 2:02:40" aria-label="Смотреть с 2:02:40"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. Финальным шагом инфраструктурного этапа становится регистрация контекста как службы в файле Program.cs с помощью метода builder.Services.AddDbContext<MVCContext> с вызовом провайдера options.UseSqlServer и динамическим считыванием строки подключения <a class="ts" data-seconds="7426" href="#t=7426" title="Смотреть с 2:03:46" aria-label="Смотреть с 2:03:46"><svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg></a>. Данный фундамент подготавливает приложение к динамическому формированию корзины на основе записей из реальной базы данных.

🖥️ Финализация отображения товаров и интеграция оплаты 2:05:52

На финальном этапе разработки основной задачи проекта внимание переключается на техническую реализацию вывода данных из базы и создание интерактивного интерфейса для покупателей. Ранее в разговоре они касались настройки БД и Entity Framework, а также интеграции Stripe для платежей.

Работа с данными и контроллером 2:10:33

После того как база данных заполнена информацией о продуктах (включая названия, URL изображений и идентификаторы цен из Stripe), необходимо передать эти данные на страницу. Процесс начинается с обновления базы через миграцию, после чего данные извлекаются через контекст контроллера.

Для корректной работы приложения в контроллере объявляется private read-only переменная для MVC context, которая инициализируется через конструктор. Метод Index переписывается как асинхронный (async Task), чтобы эффективно ожидать получение списка элементов из базы данных с помощью команды await context.Items.ToListAsync(). Важно не забыть импортировать соответствующее пространство имен Microsoft.EntityFrameworkCore в верхней части файла для устранения ошибок компиляции.

Верстка представления и стилизация 2:13:06

Отображение товаров на странице Index.cshtml строится с использованием сеточной системы Bootstrap. В модель представления передается коллекция элементов, по которой выполняется цикл foreach для рендеринга каждого товара.

Каждый блок товара включает:

Для улучшения визуального восприятия используется CSS-анимация при наведении курсора. Изначально заголовок и кнопка скрыты (свойство opacity равно 0), но при наведении на блок товара (:hover) они становятся видимыми (устанавливается opacity 0.4), а основное изображение слегка затемняется.

Финальная интеграция Stripe 2:27:03

Заключительный шаг — связывание данных формы с методом обработки платежа. С помощью атрибута [Bind] данные элемента (ID, название, URL изображения и идентификатор цены) передаются в метод контроллера.

Ключевым моментом является использование интерполяции строк для динамического формирования запроса к Stripe: метод получает item.priceID, что позволяет создавать уникальные checkout-сессии для каждого конкретного товара. При тестировании функционала (включая ввод тестовых данных карты) система корректно перенаправляет пользователя на платежную страницу Stripe, подтверждая успешную интеграцию всех компонентов приложения.

💬 Цитаты

«This is actually the most secure way to do it, so that the price is not written in the client side.»

«Использование async/await в контроллере позволяет серверу не блокироваться во время тяжелых запросов к базе данных.»

Инструктор 30:45

«that's actually the recommended way stripe payments are done»

«If the document.user ID is not equal to the to the user that is currently logged in the application then we're we're going to return a not found page»

«As soon as we hover over the item so the whole div we want to access this item title and the same thing is for the item button»

👥 Спикеры
📖 Термины
Stripe Checkout
Готовое платежное решение от Stripe для приема онлайн-платежей с высокой степенью безопасности.
ASP.NET Core MVC
Фреймворк для создания веб-приложений на платформе .NET, разделяющий логику на модели, представления и контроллеры.
TinyMCE
Популярный WYSIWYG-редактор, позволяющий пользователям редактировать контент с использованием визуальных инструментов.
Технологии и IT ASP.NET Core MVC Stripe Entity Framework Core Веб-разработка