Краткая история веб-разработки
- PHP мертв, используй ColdFusion!
- PHP мертв, используй ASP.NET!
- ... Ruby on Rails!
- ... Django!
- PHP мертв, используй NextJS!
с 30-м днем рождения PHP!
- PHP мертв, используй ColdFusion!
- PHP мертв, используй ASP.NET!
- ... Ruby on Rails!
- ... Django!
- PHP мертв, используй NextJS!
с 30-м днем рождения PHP!
Термины в статье:
К стеку добавился:
Vue.js
Потратив 2 ночи (и немного терпения), я наконец завершил реализацию всех эндпоинтов! В какой-то момент это очень наскучило, но я все равно продолжал писать их.
Как выглядят эндпоинты в этой статье - Создаю онлайн-сервис для чтения книг. День 4. Обработка первого запроса.
Архитектура папок теперь выглядит вот так:
Всего реализовано 38 эндпоинтов , и это еще не конец — их количество будет расти! Последний из них ощущался как будто я пробежал марафон.
Но как делать веб без дизайна? Верно, никак! 🤔
Зайдя в Figma и подсмотрев интерфейс GitHub'а , я накидал ориентировочный дизайн страниц регистрации и входа.
Верстка — это немного рутинное занятие, но результат того стоит!
Могу сказать, что получилось почти идентично дизайну.
Почему Vue.js ? Просто такие условия 🙃. Если бы выбор был за мной, я бы взял React .
Добавлю в решение новый проект Веб-приложение ASP.NET Core (MVC) . Стандартный шаблон создаст такие папки:
wwwroot
Это корневая папка для статических файлов, которые будут доступны напрямую через браузер.
Controllers
Папка содержит классы контроллеров, которые управляют маршрутизацией.
Models
Папка содержит модели данных, которые представляют сущности приложения.
Views
Папка содержит представления — файлы, которые отвечают за отображение HTML-страниц пользователю.
В папку wwwroot/lib добавлю клиентскую библиотеку Vue.js .
Создам новый контроллер для страниц аутентификации.
В папке Views есть еще 2 папки:
Home
Shared
В папку Shared добавлю новый шаблон страницы Razor с названием _LoginLayout для страниц аутентификации.
Создам папку Auth, добавив туда пустую страницу Razor с названием _ViewStart. Этот файл указывает какой шаблон будут использовать страницы.
@{
Layout = "_LoginLayout";
}
Теперь закину в wwwroot/css свой файл со стилем, который наверстал.
Начну со страницы входа, добавив HTML-разметку, которую наверстал.
Снизу файла напишу блок скриптов:
@Section scripts {
<script src="~/lib/vue/vue.global.js"></script>
<script>
...тут будут все скрипты...
</script>
}
Пример запроса на бэкенд:
На скрине показан метод ассинхронный метод login(), в нем реализована отправка запроса на эндпоинт /auth/login, если запрос проходит успешно, я записываю Access-токен в локальное хранилище и перенаправляю пользователя на страницу по адресу /home. В противном случае я показываю ошибку пользователю.
В ответе сервера я получаю Access и Refresh токены.
Access-токен записываю в локальное хранилище.
Refresh-токен храню в Http-only куках для большей безопасности 🛡️.
Пример записи куки на сервере:
Здесь я записал новую куку с под названием refreshToken, и значением, равным Refresh-токену.
Вообще для чего мне Refresh-токен, если есть Access? Все очень просто, у Access-токена срок жизни 15 минут, поэтому через 15 минут его необходимо будет сгенерировать заново. Для этого как раз и понадобится Refresh-токен.
По истечению Access-токена я буду посылать на сервер запрос со своими куками. Сервер прочитает Refresh-токен из них и, если он валидный, вернет новый Access-токен.
Как это реализовано со стороны сервера:
Со стороны клиента:
При загрузке страницы сразу же срабатывает метод checkRefreshToken, далее отправляется запрос на /auth/refresh. Если сервер возвращает положительный ответ, записываю новый Access в локальное хранилище и продолжаю пользоваться сервисом.
Запущу бэкенд и фронтенд.
После запуска я сразу попадаю на страницу входа.
Войду в аккаунт, который я создвал еще на начальных этапах.
Если сейчас обратиться по адресу /home, меня перекинет назад на страницу авторизации.
Попробую сначала ввести неправильный пароль.
Теперь введу правильный пароль. Все сработало! Я попал на домашнюю страницу.
Зайдя в консоль разработчика, можно посмотреть локальное хранилище и найти там Access-токен.
Теперь я могу пользоваться сервисом, отправляя запросы на эндпоинты, передавая данный токен в заголовке.
🎁 Бонусная статья.
Создам таблицу, которая будет хранить коды подтверждения. В ней будут следующие столбцы:
id: уникальный идентификатор
code: сгенерированный код
email: почта, на которую пришел код
expires_in: дата и время истечения кода
Опишу методы работы с этой базой данных через интерфейс.
В интерфейс добавлю логику для отправки кода на почту.
Отправляться будет шестизначный код. Генерация кода выглядит так:
Теперь зайду в mail.ru и создам новую почту. Перейду в настройки безопасности и выберу пункт "Пароли для внешних приложений" . Создам новое внешнее приложение и получу для него пароль. Запишу его себе куда-нибудь.
Для отправки сообщений необходимо подключить библиотеку System.Net.Mail. Она поможет настроить SMTP-клиент и отправить письмо.
Эти переменные необходимы для настройки подключения к SMTP-серверу, который будет отправлять письмо.
Описание : Адрес SMTP-сервера, который используется для отправки писем.
Пример :
Для Gmail: smtp.gmail.com
Для Mail.ru: smtp.mail.ru
Для Yandex: smtp.yandex.ru
Описание : Порт, используемый для подключения к SMTP-серверу. Обычно это:
587 (для TLS/STARTTLS)
465 (для SSL)
Пример : 587 для Gmail или Mail.ru.
Описание : Логин (обычно email), который используется для аутентификации на SMTP-сервере.
Описание : Пароль для аутентификации на SMTP-сервере. В моем случае я вписал пароль, который недавно получил от mail.ru.
Класс MailMessage используется для создания самого письма. Вот его основные параметры:
Описание : Этот флаг указывает, что тело письма содержит HTML-разметку. Если установлено значение false, то тело письма будет обрабатываться как простой текст.
Описание : Указывает адрес отправителя. Это поле должно быть заполнено объектом типа MailAddress.
Описание : Указывает адрес получателя. Можно добавить несколько адресов с помощью метода message.To.Add().
Описание : Тема письма, которая отображается в заголовке сообщения.
Описание : Тело письма. Если IsBodyHtml = true, то здесь можно использовать HTML-разметку. В противном случае это будет простой текст. В моем случае я сверстал небольшую форму, записал её в отдельную переменную класса Constaints.
Создам эндпоинт, который будет отвечать за отправку сообщения. Например:
Запускаю сервер и тестирую функционал:
Ввожу адрес электронной почты, на который хочу отправить сообщение. 📝
Нажимаю "Выполнить". ✅
И... Письмо пришло! 🎉
Убеждаюсь, что запись добавлена в базу данных. Все отлично работает! ✅
Теперь пользователи могут подтвердить свою почту с помощью шестизначного кода.
Добрый день.
Вот видел здесь Питонистов... а нет ли C# учителей (менторов), кто поможет MVC и ASP .NET CORE осваивать?
Попробую первый пост по разработке. Специально для одного моего подписчика который пишет на Delphi)
И так, делал древовидное меню для интернет-магазина, с возможностью добавления категорий "на лету", но план изменился и, дабы труд не пропадал, предам его общественности, может даже кому пригодится.
Пример можно посмотреть тут
Проект на .net Core 3.1 в среде разработки Visual Studio 2019.
- Создаем проект на .net mvc (Core или .net Framework не имеет значения);
- Добавляем модель категории;
- Создаем папку для хранения класса Html-хелпера который будет формировать разметку для нашего меню (в моем случае это App_Code);
- Добавляем класс для хелпера (у меня это TreeViewMenuHelper.cs) и добавляем туда код:
- Теперь для вывода меню на странице нам достаточно указать строку: @Html.CreateBaseList(Model), а компилятор сделает все за нас и создаст html-разметку
- Мой проект имеет такую структуру:
- Затем создадим объекты Category, без них ну вообще ни как). Я добавил их просто в контроллере, при обращении к Index мы создаем объекты и передаем их в представление.
Отступление для тех кто первый раз или пишет на Delphi:
Теперь у нас готова реализация MVC:
model - мы описали объект Category.
view - представление, то что видит пользователь.
controller - контроллер, который работает связующим звеном и обрабатывает запросы, например передать в представление категорию с Id = 1 или Id = 2, или все вместе.
Почему в аббревиатуре MVC "С" - поставили последней не знаю, мне кажется это не справедливо по отношению к ней.
- Теперь нам следует добавить стили в файлы стилей (у меня site.css) и скрипты в файлы скриптов (у меня site.js), не перепутать.
- CSS и JavaScript (берем по ссылке в примере).
- И получаем такое меню.
Ссылка на депозитарий GiHub (Узнал, что депозитАрий пишется через "А", день не зря прожил)
Здравствуйте. Меня зовут Олег и я новичок в С#, можно сказать нуб.
Решил создать простой квест. Функция в if'е не отображается при выводе, без if'а все работает нормально. Пожалуйста подскажите откуда у меня руки растут и как поставить их на место, то есть пожалуйста объясните где моя ошибка и как ее исправить.