.Net developer, data scientist
Привет всем! Сегодня мы обсудим тему маршрутизации, или как некоторые могут сказать, тему роутинга в приложениях ASP.NET Core. Мне кажется, что это видео будет интересным, с большим числом примеров кода. Предыдущие темы на канале были немного абстрактные, так как программисты не задумываются о вопросах среды приложения или сервера приложения в повседневной работе. Конечно, знать эти темы нужно, особенно перед собеседованием, а на практике этим вопросам уделяется меньшее внимания. Тема маршрутизации с этой точки зрения является более интересной темой. Почему? Потому что в своей повседневной работе вы будете довольно часто добавлять контроллеры и действия в контроллерах попутно задумываясь над тем, как привязать конкретное действие к контролеру к определенному адресу. Но это не единственный вопрос, который у вас может возникнуть. Вы узнаете через несколько минут что добавить действие и привязать его к определенному адресу / пути в строке браузера это тривиальное задание. А как можно передать какие-то параметры вместе с запросом? На этот вопрос вы также получите ответ. Я понимаю, что меня могут смотреть также и опытные программисты, поэтому я сразу предупрежу, что сегодня мы будем рассматривать некоторые базовые понятия, например рассмотрим вкратце некоторые методы HTTP запросов, такие как GET, POST, PUT, DELETE. Сегодня в примерах будет много атрибутов, что также должно быть интересно моим зрителям.
Если речь идет о маршрутизации, то это определенная логика, которая определяет на основании адреса, под который был выслан запрос, а также на основании метода запроса (о них мы поговорим позже), каким контроллером и каким действием должен быть обслужен данный запрос. То есть перейти от адреса запроса к конкретному коду в нашем приложении. Логика работы маршрутизации в приложениях ASP.NET Core довольно сложная и вряд ли удастся объяснить все нюансы в течении 20 минутного видео. Сегодня мы познакомимся как пользоваться данной логикой и взаимодействовать с ней, в основном при помощи атрибутов.
Если вас спросят на собеседовании какие виды маршрутизации в приложении ASP.NET Core вы знаете, то можно смело ответить после просмотра данного видео, что вы знаете 2 метода маршрутизации: первый метод – это так называемый обычный метод, на основании маппинга маршрутов контроллеров, и второй метод на основании атрибутов. Сложно сказать, как из этих методов лучше или хуже. Результат работы этих методов одинаков, однако способ настройки маршрутизации отличается. Скорей всего это дело привычки. Я заметил, что если программист хочет сделать что-то быстро, то он использует маршрутизацию на основании атрибутов. Возможно, обычная маршрутизации требует больше времени для понимания как она работает, однако в ней также ничего сложно нет. В любом случае сегодня будут представлены оба метода маршрутизации.
Если речь идет о практическом примере, то я подготовил небольшое приложение с двумя контроллерами. Каждый из контроллеров имеет маршрутизацию настроенную либо на основании атрибутов, либо на основании декларирования маршрутов. К сожалению или, к счастью, нельзя использовать одновременно 2 вида маршрутизации, однако, с другой стороны, я могу представить себе ситуацию, когда контроллер настроен для использования обоих типов маршрутизации, а какой конкретно тип будет использоваться определяется при старте приложения.
Давайте посмотри на контроллер ValuesController. Сразу бросается в глаза что каждое действие контроллера имеет атрибут с названием метода запроса. Конкретно у нас есть 4 метода: GET, POST, PUT, DELETE. Каждый из методов имеет своё семантическое значение. Если мы вспомним шаблон проектирования «Репозиторий», то можно сказать, что каждый из этих методов, который передаётся вместе с запросом, соответствует операциям «Получить», «Добавить», «Обновить», «Удалить», то есть:
Каждый запрос с одним из этих методов в случае безошибочного выполнения может вернуть статус 200, то есть «ОК». Однако, более профессионально будет разделение успешных статусов на отдельные статусы в зависимости от метода запроса. Что имеется в виду:
Это не ошибка, если все операции будут возвращать код статуса 200. И это также не правило, что, например все запросы POST должны возвращать статус 201. Надо смотреть на каждую ситуации в отдельности и выбирать соответствующий код, который будет наиболее подходящим в данном контексте. Например, с кодами ошибок клиента ситуация другая – всегда возвращается код, который наиболее точно характеризует ошибку. Вот несколько примеров:
Возвращаясь к нашему коду, каждый из этих атрибутов определяет с каким методом может использоваться данное действие контроллера. По умолчанию название действия определяется по названию метода контроллера. Это не всегда удобно, так как названия методов могут быть длинными и будет неудобно их вписывать в адрес запроса. Используя атрибут ActionName с аргументом типа string, который определяет, как будет называться действие, связанное с данным методом.
Теперь вернемся к классу StartUp. В этом классе задекларирован метод ConfigureRoute. В этом методе определены все адреса, которые используются нашим приложением и как эти адреса связаны с контроллерами и действиями. Сразу стоит оговорится, что адреса могут декларироваться как константы. То есть адресу соответствует определенный контроллер и действие. Например, давайте посмотрим на декларацию маршрута, которая называется «UserExample1». Здесь контроллеру Values и действию «UserFromBody» будет соответствовать один единственный адрес: адрес сервера + строка «UserJson».
Также адрес может быть задекларирован так, что шаблон адреса будет подходить большому количеству адресов. Давайте посмотрим на первую декларацию: если мы укажем только адрес сервера без указания контроллера и действия, то получим контроллер и действие по умолчанию, то есть „Values” и „Index”. А если укажем только контроллер любой, то будет попытка вызова действия „Index” – если такое действие есть, будет выполнена его логика. Если такого действия нет, то будет возвращена ошибка «404 - Страница не найдена». Если же кроме адреса сервера мы укажем и название контроллера, и название действия, то будет попытка вызова этого контроллера с указанным действием. Результатом этой операции будет либо выполнение логики, либо ошибка 404.
Все декларации в методе ConfigureRoute, кроме первой, относятся к конкретным адресам для конкретных методов и действий. Так иногда бывает, что в строке запрос, в адресе, мы хотели бы передать определенный параметр. Это возможно. Более того мы можем указать параметр какого типа мы ожидаем. Обратите внимание в некоторых паттернах деклараций после двоеточия указан конкретный тип – это и есть ограничение на тип передаваемого параметра. Также возле некоторых параметров можно увидеть знак вопроса. Он означает, что данный параметр необязательный.
Вернемся в контроллер ValuesController. Обратите внимание, что некоторые действия принимают аргумент сложного типа User и возле каждого аргумента есть атрибут. Таких атрибутов 3: FromBody, FromQuery, FromForm. Они определяют как этот сложный тип будет передан в запросе в наш контроллер. Более подробно мы рассмотрим это на конкретном примере.
Также часто бывают ситуации, когда в контроллер необходимо передать файл вместе с запросом. Чтобы это сделать необходимо задекларировать действие, которое принимает аргумент типа IFormFile. Как это работает мы узнаем после запуска приложения.
Если речь идёт о маршрутизации на основании атрибутов, то давайте посмотрим на контроллер ValuesTwoController, который полностью повторяет функциональность контроллера ValuesController. Однако, маршруты, которые определены в данном контроллере немного отличаются, чтобы было понятно, что мы работает с другим контроллером, который не связан с первым. В этом контроллере также, как и в предыдущем, задекларированы атрибуты методов запросов. Наблюдательные зрители заметят, что некоторые из атрибутов принимают аргумент типа string, например действие Index. Это первый способ декларации маршрута при помощи атрибутов. Действие Index будет доступно по адресу ValuesTwo/Primary. Способ декларирования маршрутов при помощи атрибутов несколько. Рассмотрим их на примерах:
Мне кажется, сегодня мне удалось показать большее количество примером как можно реализовать маршрутизацию в приложении ASP.NET Core, а кроме того, показать реальный практический пример использования атрибутов. Пора заканчивать видео. Напоминаю, что в описании к данному видео вы найдете ссылку на репозиторий с кодом, который был использован в примере, ссылку на текст к данному видео и ссылку на коллекции запросов Postman для обычного роутинга и роутинга по атрибутам. Спасибо за внимание. Если видео было вам хоть чуточку полезным, буду благодарен за лайк, комментарий и подписку, если вы не подписаны. До новых встреч.
Пример кода из видео на GitHub
Для открытия файла проекта необходимо Visual Studio 2019.