5.05. Веб-разработка и интеграции
Веб-разработка и интеграции
ASP.NET Core
MVC, Razor Pages, Web API
Middleware, DI, конфигурация
ASP.NET – технология для создания веб-приложений, веб-API, сервисов, работающих под Windows, Linux, macOS. Поддерживает MVC, Razor Pages, Web API, SignalR и другие подходы.
Как работает ASP.NET Core?
ASP.NET построен на основе Kestrel – кросс-платформенного веб-сервера. Он может быть запущен как самостоятельный процесс или за обратным прокси-сервером (например, Nginx или IIS).
ASP.NET: Запрос – бизнес-логика – результат.
Pipeline (конвейер обработки запроса) работает в следующем порядке:
- запрос приходит к серверу (Kernel);
- проходит через цепочку middleware: логирование, статические файлы, маршрутизация, авторизация;
- выполняется контроллер/обработчик;
- ответ отправляется клиенту.
Структура проекта ASP.NET:
| Папка / Файл | Описание |
|---|---|
Program.cs | Точка входа в приложение. Начиная с .NET 6, содержит конфигурацию сервисов и middleware pipeline (вместо Startup.cs). |
Startup.cs (до .NET 6) | Класс для настройки зависимостей (ConfigureServices) и конвейера обработки запросов (Configure). Использовался до появления упрощённого хостинга в .NET 6. |
wwwroot/ | Папка для статических файлов: CSS, JavaScript, изображения и другие ресурсы, доступные напрямую через HTTP. |
Controllers/ | Содержит классы контроллеров, отвечающих за обработку HTTP-запросов в архитектуре MVC или Web API. |
Views/ | Хранит представления (view), используемые в MVC, написанные на языке Razor (.cshtml). |
Pages/ | Содержит страницы в модели Razor Pages, где каждая страница представляет собой отдельный маршрут с кодом и разметкой. |
Models/ | Папка для классов, представляющих данные приложения (модели предметной области, DTO, view models). |
appsettings.json | JSON-файл с конфигурацией приложения: строки подключения, параметры сервисов, пользовательские настройки. Поддерживает профили (например, appsettings.Development.json). |
Компоненты ASP.NET
Middleware – ПО промежуточного слоя (потому и middle), которое обрабатывает HTTP-запросы и ответы. К примеру, это аутентификация, логирование, обработка ошибок, статические файлы. Каждый компонент работает последовательно, словно конвейер, получая HttpContext, выполняя код, останавливая цепочку или отправляя ответ.
Все middleware подключаются в методе app.Use() или app.Run() внутри Program.cs.
Пример:
app.Use(async (context, next) =>
{
Console.WriteLine("Перед выполнением других middleware");
await next(); // Передаёт управление дальше
Console.WriteLine("После выполнения других middleware");
});
Middleware выполняются в том порядке, в котором они добавлены:
app.UseRouting(); // Сначала маршрутизация
app.UseAuthentication(); // Затем аутентификация
app.UseAuthorization(); // Потом авторизация
app.UseEndpoints(endpoints => { ... }); // И только потом — обработка
Dependency Injection (DI) – встроенный механизм внедрения зависимостей. Это способ передачи зависимостей в класс без жёсткой привязки к конкретной реализации. В ASP.NET есть встроенный контейнер DI, который управляет временем жизни объектов и их зависимостями. Регистрация происходит в Program.cs через builder.Services.
Services – регистрируются в DI-контейнере и доступны в контроллерах и middleware.
| Время жизни | Описание |
|---|---|
AddSingleton | Один и тот же экземпляр сервиса используется на протяжении всего жизненного цикла приложения. Создаётся при первом запросе и сохраняется до завершения работы приложения. Подходит для логгеров, кэширующих сервисов, глобальных конфигураций. |
AddScoped | Один экземпляр сервиса создаётся на один HTTP-запрос (или сеанс). Все компоненты, участвующие в обработке одного запроса, получают один и тот же экземпляр. Используется, например, для контекста базы данных (DbContext) и сервисов, зависящих от состояния запроса. |
AddTransient | Новый экземпляр сервиса создается при каждом обращении к нему. Подходит для простых, не содержащих состояния служб, таких как валидаторы, форматтеры, отправщики уведомлений. |
Пример регистрации:
builder.Services.AddSingleton<ILogService, FileLogService>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddTransient<IMessageSender, EmailSender>();
Routing – маршруты, которые можно определять через атрибуты или явно в pipeline.
[ApiController]
[Route("[controller]")]
public class HelloController : ControllerBase
{
[HttpGet]
public string Get() => "Hello from API!";
}
Маршрутизация – это процесс определения того, какой код должен обработать HTTP-запрос. ASP.NET использует endpoint routing, где маршруты регистрируются отдельно от обработчиков:
- URL анализируется (
/home/index); - по таблице маршрутов определяется, какой контроллер и метод вызвать;
- выполняется метод, возвращается результат.
MVC – Model (данные и логика), View (представление, обычно .cshtml), Controller (обработчик запросов).
Контроллеры – это классы, содержащие действия (actions). Выше был приведён пример ApiController.
Контроллеры тесно связаны с машрутизацией. Вот атрибуты маршрутизации:
| Атрибут | Описание |
|---|---|
[Route] | Задаёт пользовательский маршрут для контроллера или действия; поддерживает шаблоны и токены (например, [Route("api/[controller]/[action]")]) |
[HttpGet] [HttpPost] | Ограничивает действие определённым HTTP-методом (GET, POST и др.); часть набора атрибутов маршрутизации |
[ApiController] | Применяется к контроллеру API и включает поведение по умолчанию: автоматическая модельная привязка из тела, ответы 400 при ошибках валидации, обязательные атрибуты привязки |
[FromQuery]< [FromBody] | Указывает источник параметров: из строки запроса (query string) или из тела запроса (JSON, XML) |
Razor Pages – упрощённая модель, где каждая страница – отдельный класс + .cshtml-файл. Razor – это шаблонизатор, который позволяет встраивать C# в HTML.
Синтаксис Razor
| Синтаксис | Описание |
|---|---|
@model MyNamespace.MyModel | Объявляет тип модели, используемой в представлении (строго типизированное представление) |
@using MyNamespace | Подключает пространство имён в текущем представлении |
@{ ... } | Блок кода на C#, используется для объявления переменных, циклов, условий |
@if (...) { ... } | Условная логика в разметке |
@for (...) { ... } | Цикл в представлении |
@Html.Raw(...) | Выводит строку как неэкранированный HTML (внимание: потенциальный риск XSS) |
@Url.Action(...) | Генерирует URL к указанному действию контроллера |
@await Component.InvokeAsync(...) | Асинхронный вызов компонента представления (view component) |
@section Scripts { ... } | Определяет секцию скриптов, которая будет вставлена в соответствующее место в _Layout.cshtml |
@helper MyHelper(...) { ... } | Определение пользовательского вспомогательного метода (устарело, не поддерживается в Razor Pages) |
Элементы Razor
| Элемент | Описание |
|---|---|
@page | Директива, указывающая, что файл — это Razor Page, а не MVC-представление; активирует обработку как независимой конечной точки |
_Layout.cshtml | Основной шаблон страницы, обеспечивающий единое оформление (header, footer, меню); используется через @layout |
_ViewStart.cshtml | Файл, выполняемый перед каждым представлением; обычно задаёт общий Layout или общие переменные |
Partial Views | Частичные представления (.cshtml) для повторного использования UI-фрагментов (например, формы, карточки); включаются через @Html.Partial() или <partial> Tag Helper |
Tag Helpers | Компоненты, расширяющие стандартные HTML-теги серверной логикой (например, asp-controller, asp-action, asp-for); делают разметку чище и ближе к HTML |
Tag Helpers позволяют расширять HTML-элементы возможностями C#. Например:
<a asp-controller="Home" asp-action="Index">Главная</a>
<form asp-action="SubmitForm" method="post">
<input asp-for="Name" />
<span asp-validation-for="Name"></span>
</form>
Страница (Page) — это класс, производный от System.Web.UI.Page. Каждая .aspx-страница компилируется в объект этого класса при выполнении запроса. Она управляет жизненным циклом, обработкой данных, рендерингом HTML и взаимодействием с пользователем. Когда браузер запрашивает .aspx файл, IIS передаёт управление ASP.NET, который создаёт экземпляр класса Page, вызывает нужные события жизненного цикла и генерирует HTML, который отправляется обратно клиенту.
Типы страниц бывают разными:
- Обычная (
aspx) — это самостоятельная страница с полной разметкой. - Мастер-страница (
.master) - шаблон, задающий общий вид сайта (например, шапка, меню, футер). Позволяет создавать согласованный интерфейс. - Контентная страница использует мастер-страницу и заполняет её содержимым через
ContentPlaceHolder.
Пользовательский элемент управления (ascx) это повторно используемый UI-компонент (например, кастомный хэдер или карточка товара).
Элементы управления (Controls) — это серверные компоненты, которые можно использовать на странице и программировать на C#. Они работают на стороне сервера, имеютс свой собственный жизненный цикл и автоматически сохраняют своё состояние, могут быть статичными (Label) или динамическими (TextBox, GridView, Button):
- HTML-контролы (
<div>)работают как обычный HTML, но доступны на сервере. - Веб-контролы (
TextBox,Button) являются удобными, богатыми функциями, которые автоматически управляют состоянием. - Пользовательские контролы — это как раз пользовательские элементы управления.
- Серверные контролы (
Calendar,AdRotator) являются готовыми решениями от Microsoft.
Элементы управления выстраиваются в дерево элементов (Control Tree) при инициализации, словно DOM.
ViewState — это состояние страницы, механизм сохранения состояния элементов управления между PostBack'ами. Хранится в скрытом поле (__VIEWSTATE) на странице в виде закодированной строки. Это сохраняет значение текстовых полей, выбора в списке, и позволяет не перезагружать данные при каждом PostBack'е.
PostBack — это механизм, при котором браузер отправляет запрос на ту же самую страницу , с которой он был вызван (в отличие от GET-запроса или перехода на другую страницу). Пользователь взаимодействует с элементом управления (например, нажимает кнопку). JavaScript (__doPostBack) запускает форму с method="post" на эту же страницу. Сервер получает запрос, создаёт экземпляр страницы, восстанавливает её состояние (ViewState), обрабатывает событие. Страница снова рендерится и отправляется обратно браузеру.
Такое можно наблюдать для элементов Button, DropDownList, CheckBox, LinkButton, ImageButton. Используйте IsPostBack, чтобы не выполнять лишнюю инициализацию. Для динамических частей страницы применяйте UpdatePanel - механизм частичного PostBack (когда пользователь нажимает на кнопку, обновляется только содержимое панели без полной перезагрузки страницы).
Кроме PostBack, есть ещё Cross-Post, когда запрос отправляется на другую страницу, и Redirect - перенаправление, когда браузер загружает новую страницу.
Рендеринг — это финальный этап жизненного цикла, когда ASP.NET преобразует все элементы управления в HTML, который отправляется браузеру. Каждый контрол имеет метод Render(), который выводит свой HTML.
Инициализация происходит на этапе Init. На этом этапе создаются все элементы управления, присваиваются начальные свойства и происходит связь с родительской страницей. Если создавать элементы динамически (в коде), то лучше делать это именно на этапе Init, чтобы они участвовали во всех последующих этапах.
Страница в ASP.NET имеет свой жизненный цикл - последовательность этапов, через которые проходит веб-страница при обработке запроса от клиента (браузера). Каждый этап вызывает определённые события, на которые можно подписаться и выполнять пользовательский код.
| Событие страницы | Описание |
|---|---|
PreInit | Первое событие жизненного цикла. Можно задавать динамическую тему, мастер-страницу или создавать динамические контролы. |
Init | Инициализация элементов управления. Все контролы создаются и получают свои начальные свойства. |
InitComplete | Указывает на завершение этапа инициализации. Доступны все контролы, можно выполнять действия, требующие полной инициализации. |
LoadViewState | Восстановление состояния страницы из ViewState, если запрос является PostBack. |
LoadPostData | Обработка данных формы: контролы, реализующие IPostBackDataHandler, обновляют своё состояние (например, текст в TextBox). Выполняется для каждого контрола отдельно. |
PreLoad | Вызывается перед событием Load. Может использоваться для выполнения логики, которая должна быть до основной загрузки. |
Load | Основной этап загрузки страницы. Здесь обычно размещается бизнес-логика, привязка данных, взаимодействие с элементами управления. |
LoadComplete | Вызывается после завершения Load. Подходит для завершающих действий, например, запуск асинхронных операций. |
PreRender | Последняя возможность изменить содержимое страницы или контролов перед рендерингом. Все данные уже загружены. |
PreRenderComplete | Указывает, что этап PreRender завершён. Используется редко, часто внутренними механизмами платформы. |
SaveStateComplete | После сохранения ViewState и ControlState. Подходит для операций, которые не должны влиять на состояние страницы. |
Unload | Последнее событие жизненного цикла. Используется для освобождения внешних ресурсов (файлов, соединений). Не рекомендуется для работы с контролами или HTTP-контекстом. |
вход в ASP, авторизация и аутентификация, управление статусом входа в ASP и его элементы.
ASP.NET поддерживает надежные элементы управления входом для веб-приложений, не требующие никакого программного кодирования. Элемент управления LoginStatus — очень простой элемент управления, все, что он делает, — отображает ссылку, которая отличается в зависимости от того, вошел ли пользователь в систему или нет. Если пользователь вошел в систему, он отображает ссылку LogOut и наоборот.
Он поддерживает несколько свойств, LogOutAction можно использовать для указания того, что происходит, когда пользователь нажимает на LogOutLink, а параметры — Redirect, RedirectToLoginPage, Refresh. Если мы устанавливаем Redirect, то мы должны установить другое свойство LogOutPage Url, на которое перенаправляется пользователь после выхода из веб-сайта.
WCF
Веб-сервисы в C#
WCF (Windows Communication Foundation)
Кратко: что такое, когда использовать
Сервисы, контракты, привязки
WCF
System.ServiceModel, System.ServiceModel.Channels, Binding – основы Windows Communication Foundation.
автогенерируемый прокси-класс WCF.
Интеграции
REST, gRPC, SOAP в C#
Работа с внешними API в C#
Планирование задач (Quartz.NET)
Cron – формат расписания (0 0 1 */10 * * – каждые 10 дней в 1:00).
Quartz.NET – библиотека для планирования задач в .NET.
Job, Trigger, Scheduler – ключевые понятия Quartz.
Потоки данных
Подпоток (Substream) – часть основного потока интеграции (например, шаг ETL).
Интеграционный поток – процесс обмена данными между системами.
OutputIntegrationStream<TModel, TResponse> – пример абстракции для исходящих данных.
Работа с моделями
ExportRepository<TModel> – репозиторий для выборки данных перед отправкой.
ImportRepository<TModel> – для сохранения полученных данных.
Обработка моделей – маппинг, валидация, сериализация.
Сессии интеграции
Открытие/закрытие сессии – аутентификация, получение ID сессии.
Интеграционная авторизация – токены, Basic Auth, OAuth и т.д.
Endpoint – настройка адресов (appsettings.json, DI).
Обработка ответов
Switch/case – ветвление логики на основе кодов ответа.
Импорт данных – обработка входящих данных через подпотоки.
protected abstract void – шаблон "Template Method" для кастомизации.