Andriy Shyrokoryadov

.Net developer, data scientist

№2 Класс Startup в приложении Asp.Net Core MVC / Web API.

Текст к видео "Класс Startup в приложении Asp.Net Core MVC / Web API" на канале YouTube

Приветствую Вас на моём канале. Как было обещано в предыдущем видео, каждый элемент приложения Asp.Net Core будет рассмотрен более детально. Сегодня мы начинаем разбор первого элемента из списка – то есть с класса Startup. Благодаря предыдущему видео мы знаем что класс Startup состоит из 2 методов: ConfigureServices и Configure:

  • метод ConfigureServices является не обязательным и служит для регистрации услуг (на английском языке services), то есть компонентов, которые имеют определенную функциональность и могут использоваться в различных приложениях многократно и повсеместно. Услуги, которые регистрируются в данном методе, могут быть далее получены через фреймворк внедрения зависимости или через свойство ApplicationServices объекта, который реализует интерфейс IApplicationBuilder.
  • метод Configure используется для создания последовательности операций для обработки HTTP запросов к нашему приложению. Последовательность операций – это последовательность связующих программных компонентов, которые также упоминались в предыдущем видео.

Оба метода вызываются при старте приложения Asp.Net Core. В этом месте стоит вспомнить, где конкретно указывается класс Startup в приложения Asp.Net Core. Данный класс указывает в коде, который отвечает за создание хоста. Как мы помним из предыдущего видео обычно это происходит классе Program и методе Main. Если быть более точным, то класс Startup указывается в методе UseStartUp объекта, который имплементирует интерфейс IWebHostBuilder. Объект webBuilder в строчках 21 и 23 именно таким объектом и является.

В общем примере из предыдущего видео класс Startup имел конструктор по умолчанию. Однако есть возможность использовать класс Startup, который принимает в конструкторе в качестве аргумента объект, который реализует интерфейс IConfiguration. Данный объект передается хостом в конструктор класса Startup. В этом объекте могут содержаться услуги хоста, а приложение Asp.Net Core добавляет свои собственные услуги при помощи метода ConfigureServices. Услуги хоста и приложения могут быть использованы далее
методом Configure и далее данные услуги будут доступны во всём приложении Asp.Net Core. Кроме объекта, который реализует интерфейс IConfiguration, в конструктор класса Startup можно добавить еще 2 объекта:

  • IWebHostEnvironment – объект, который содержит информацию о текущей среде в которой было запущено веб приложение
  • IHostEnvironment – объект, который содержит информацию о текущей среде в которой было запущено приложение

Важное замечание - большинство услуг не будет доступно в нашем приложении, пока не будет вызван метод Configure.

Приложение Asp.Net Core может использоваться с несколькими классами Startup. В приложении может быть определено несколько классов Startup для каждой из сред в которых запускается приложение, например Startup и StartupDevelopment. Если суффикс названия класса Startup соответствует названию среды в которой было запущено приложение, то данный класс Startup будет выбран. Например, если наша среда называется Development, то класс StartupDevelopment будет выбран. Естественно мы должны такой класс определить. Если класс StartupDevelopment не будет определен, то будет выбран стандартный класс Startup.

Вернемся к нашим 2 основным методам класса Startup и повторим их назначение:

Метод ConfigureServices:

  • Необязательный метод
  • Вызывается перед методом Configure
  • Используется для регистрации услуг приложения

Некоторый услуги, которые мы можем зарегистрировать в ConfigureServices, могут требовать предварительной конфигурации. В этом случае используются методы расширения доступные в объекте IServiceCollection, которые начинаются со слова Add и в параметрах данных методов передаются определенные настройки, например:

services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));

Метод Configure служит для того, чтобы определить как приложение будет отвечать на запросы HTTP. Хост создает объект IApplicationBuilder и передаёт его непосредственно в метод Configure в качестве аргумента. К данному объекту при помощи методов расширения добавляются различные связующие программные компоненты (middleware, middle – середина, ware – товар, изделие; по аналогии с software и hardware). Каждый метод, который начинается с глагола Use добавляет один или несколько связующих программных компонентов. Некоторые методы Use сразу же добавляются в код после создания шаблона приложения. Как уже упоминалось в предыдущем видео каждый связующий программный компонент отвечает за то чтобы после выполнения своего кода передать управление следующему связующему программному компоненту или отправить ответ отправителю запроса. Более подробно тему связующих программных компонентов мы рассмотрим в одном из следующих видео.

Дополнительно в сигнатуру метода Configure могут быть добавлены услуги IWebHostEnvironment и ILoggerFactory, а также любые услуги зарегистрированные в методе ConfigureServices.

Класс Startup служит некоторым упрощением или выделением определенной функциональности в отдельный класс. По большому счет для запуска приложения Asp.Net Core нам не будет нужен класс Startup если предварительная настройка приложения будет осуществлена при помощи объекта HostBuilder в методе Main. При вызове метода **ConfigureWebHostDefaults ** мы можем передать делегат внутри которого будут вызваны методы ConfigureServices и Configure. Данные методы вызываются по цепочке. Если метод Configure был вызван несколько раз, то будет использована конфигурация из последнего вызванного метода Configure. По моему личному мнению все таки лучше использовать класс Startup и иметь несколько небольших классов, чем один большой. Однако ничего плохого в неиспользовании класса Startup нет и скорей всего в своей профессиональной деятельности вы встретитесь с таким техническим решением. Именно поэтому я решил о нём сейчас рассказать, чтобы вы знали что есть 2 метода конфигурации приложения – через класс Startup и без него. Оба метода хороши и выбор одного из методов зависит от предпочтений в конкретной компании.

Функционирование класса Startup можно улучшить путём использования объекта реализующего интерфейс IStartupFilter. Используя данный интерфейс мы можем настроить связующие программные компоненты без явного вызова методов, которые начинаются со слова Use.

Интерфейс IStartupFilter состоит из одного метода Configure, который в качестве аргумента принимает объект IApplicationBuilder. Каждая реализация интерфейса IStartupFilter может добавить один или несколько связующих программных компонентов. Приложение может использовать несколько реализаций IStartupFilter. Данные реализации будут использоваться в том порядке, в каком они были добавлены в методе ConfigureServices.

Для демонстрации этой функциональности я подготовил в качестве примера несколько классов:

  • класс TestMiddleware – это связующий программный компонент, который будет добавлен в наше приложение при помощи объекта IStartupFilter
  • класс TestMiddlewareStartupFilter, который добавит связующий программный компонент TestMiddleware

А теперь немного поподробней о каждом из классов.

В классе TestMiddleware есть метод Invoke, который получает в качестве аргумента объект типа HttpContext и мы работаем с этим объектом. Наша работа заключается в получении из данного объекта параметра строки запроса, который называется parameter. Далее управление передается в следующий программный компонент. Данный код будет вызваться для каждого запроса к нашему приложению.

Класс TestMiddlewareStartupFilter является реализацией интерфейса IStartupFilter. В методе Configure данного классы мы добавляем связующий программный компонент TestMiddleware используя метод UseMiddleware.

Чтобы данный связующий программный компонент был использован нашим приложением, мы должны его зарегистрировать при помощи фреймворка внедрения зависимости. Это можно сделать в методе ConfigureServices в классе Startup или при создании и настройке хоста – в данный момент данный код закомментирован. Способ регистрации реализаций IStartupFilter не влияет на его работу. Оба способа одинаковы и хороши в равной степени.

После запуска приложения с зарегистрированными реализациями интерфейса IStartupFilter каждый наш запрос будет проходит через данный связующий программный компонент, независимо от того будет ли в строке запрос переменная с названием parameter или нет.

Всю ту работу которую мы в данный момент выполнили мы могли бы сделать и в методе Configure класса Startup просто вызвав в определенном месте метода UseMiddleware с соответствующим типом связующего программного компонента. Возникает обоснованный вопрос – с какой целью мы должны использовать реализации интерфейса IStartupFilter. Сценарий использования данной функциональности следующий – ваше приложение может быть использовано с различным набором связующих программных компонентов в зависимости от клиента, бизнес-требований, среды выполнения. Каждый из этих наборов легче хранить в отдельно классе, который является реализацией IStartupFilter, чем в зависимости от каких то условий постоянно вносить изменения в метода Configure класса Startup. Выбор конкретной реализации интерфейса IStartupFilter можно параметризировать и в зависимости от параметра регистрировать соответствующий тип для внедрения зависимости.

Таким образом от класса Startup мы подошли к тематике связующих программных компонентов и внедрению зависимости. Данные темы будут раскрыты в следующих видео. А если конкретно, то я думаю следующее видео будет посвящено внедрению зависимости в более широком контексте, то есть не только в приложения Asp.Net Core, а также и в других типах приложений. Возможно даже будут 2 видео на эту тему, чтобы не паковать всё в одно очень длинное видео.

А пока на данный момент у меня уже всё на тему класса Startup. Возможно эти первые видео о приложениях Asp.Net Core получились слишком насыщены технической терминологией и сведения представленные в них не позволяют сразу сеть и написать приложение Asp.Net Core. Однако, чтобы писать качественные приложения Asp.Net Core, по моему скромную мнению, эти знания просто необходимы. Необходимо знать как всё это работает, настраивается и как между собой взаимосвязано. Здесь можно привести следующую аналогию - если у вас есть водительские права, то кроме навыков вождения, было бы неплохо еще и знать как устроены системы автомобиля или мотоцикла и как это совместно работает. В связи с этим последующие видео на тематику Asp.Net Core будут в том же ключе – иного технических деталей. Возможно, на собеседовании вы услышите вопрос как работает класс Startup и благодаря этому видео у вас будет готовый ответ. Мы проработаем все основы приложения данного типа и только лишь потом напишем некоторое приложения в качестве обучающего примера. И мы напишем это приложение с пониманием как всё совместно работает и какие существуют связи между отдельными компонентами приложения. А пока что я благодарю Вас за внимание, за то что меня смотрите. До новых встреч на моём канале.

Пример кода из видео на GitHub

Для открытия файла проекта необходимо Visual Studio 2019.