Создайте серверную часть веб-приложения .NET 6 с помощью веб-API, EF Core и SQL Server Express в кратчайшие сроки!

Введение

В настоящее время .NET становится все лучше и лучше и все более важным в мире веб-разработки.

Почти в каждом запросе на новые проекты веб-разработки, который я получаю, запрашиваются знания в области .NET, включая Web API и Entity Framework Core.

Таким образом, знание основ серверной веб-разработки с помощью .NET может быть очень полезным для вашей карьеры. И вот здесь на помощь приходит эта серия руководств.

За короткий промежуток времени вы научитесь настраивать веб-API, выполнять вызовы этого веб-API в режиме покоя, а также постоянно сохранять данные с помощью Entity Framework Core, Code-First Migration, базу данных SQL Server и SQLite и все три типа отношений в этой базе данных.

Мы перейдем сразу к делу, вы увидите каждый шаг написания необходимого кода, и к концу этого курса у вас будет все необходимое, чтобы сказать да на все запросы проекта .NET. от любого рекрутера.

Единственный инструмент, который вам понадобится в начале, — это Visual Studio Code, который доступен бесплатно.

Мы будем использовать код Visual Studio для наших реализаций и выполнять вызовы веб-API с помощью пользовательского интерфейса Swagger — интерфейса, который позволяет вам использовать API «из коробки» благодаря платформе .NET.

Visual Studio Code доступен для Windows, Mac OS и Linux. А поскольку платформа .NET является кроссплатформенной, вы можете проходить этот курс в любой из этих операционных систем.

Позже мы будем использовать бесплатную версию SQL Server Express с SQL Server Management Studio для управления нашей базой данных. Мы также кратко рассмотрим SQLite, чтобы вы знали, как использовать любую базу данных, которую вы хотите.

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

Итак, я надеюсь, вы готовы к новым навыкам и новым проектам. Давайте начнем!

Инструменты

Единственный инструмент, который нам нужен на данный момент, — это Visual Studio Code. Кроме того, вам необходимо загрузить и установить .NET 6 SDK.

VS Code можно найти на https://code.visualstudio.com/.

А SDK можно скачать на https://dotnet.microsoft.com/download. Обязательно загрузите .NET 6 для своей операционной системы.

Создайте новый веб-API

Как только .NET SDK и Visual Studio Code будут установлены, мы уже можем создать наше первое .NET-приложение, которое сразу же станет веб-API.

Для начала я создал новую папку под названием «dotnet-rpg» — для «ролевой игры dotnet». Откройте папку в VS Code.

Я предполагаю, что вы уже немного знакомы с Visual Studio Code, если нет, не стесняйтесь осмотреться.

Пока вы это делаете, было бы неплохо установить определенные расширения.

Первый C# для Visual Studio Code от самой Microsoft. Это расширение также будет предложено VS Code, как только вы создадите свое первое приложение C#. Он включает в себя поддержку редактирования, подсветку синтаксиса, IntelliSense, переход к определению, поиск всех ссылок, просто взгляните, довольно полезные вещи.

Далее идет Расширения C# от KreativJos. Как говорится в описании, это может ускорить рабочий процесс разработки, добавив некоторые записи в контекстное меню, например Добавление нового класса или интерфейса C#.

И последний уже является одним из моих любимых, Material Icon Theme. Этот просто предоставляет много-много симпатичных иконок.

Хорошо, а теперь давайте создадим наш веб-API! Мы открываем новое окно терминала, а затем давайте посмотрим, что предоставляет команда dotnet.

При добавлении -h вы видите все доступные команды. Сейчас нас интересует команда new, которая создает новый проект .NET.

Но у нас также есть команда run для запуска нашего приложения, а также команда watch, которую можно использовать вместе с run для перезапуска приложения, как только мы вносим изменения в любой файл с помощью Горячей перезагрузки, например. Довольно полезно, если вы не хотите останавливать и запускать проект самостоятельно каждый раз, когда вносите какие-либо изменения.

С помощью dotnet new мы видим некоторые из доступных шаблонов. Чтобы увидеть их все, мы можем ввести dotnet new --list. Их много, и наконец мы получили Web API. Так воспользуемся!

Мы набираем dotnet new webapi и нажимаем return.

Теперь мы видим некоторые файлы, которые были сгенерированы для нас в проводнике. Давайте пройдемся по ним очень быстро.

Внизу мы видим класс WeatherForecast. Это всего лишь часть проекта веб-API по умолчанию. Нам это на самом деле не нужно, но давайте воспользуемся этим примером через минуту.

Тем временем мы получаем небольшое всплывающее окно с сообщением о том, что мы должны добавить несколько файлов. Конечно, мы хотим их добавить.

Теперь вы должны видеть, что у нас есть папка .vscode с launch.json и tasks.json. Оба являются конфигурационными файлами, используемыми для отладки, форматирования исходного кода, упаковщиков и т. д., но в данный момент они не очень интересны для нас.

Итак, давайте посмотрим на класс Program.

Это новшество в .NET 6. Ранее мы дополнительно получили класс Startup для настройки. Теперь все обрабатывается в Program.cs.

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

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

Пожалуйста, не обращайте внимания на все эти модные словечки прямо сейчас…

Кроме того, этот класс создает конвейер обработки запросов приложения, то есть мы указываем, как приложение отвечает на HTTP-запросы.

Как видите, мы используем HttpsRedirection, Authorization и так далее. Со всеми этими Use... методами расширения мы добавляем компоненты промежуточного программного обеспечения в конвейер запросов.

Например, UsesHttpRedirection добавляет промежуточное ПО для перенаправления HTTP-запросов на HTTPS.

Я также хотел бы упомянуть, что, начиная с .NET 5, мы получаем готовую конфигурацию для SwaggerUI. При этом мы получаем удобное решение для тестирования нашего API. Мы уже собираемся использовать его в следующей главе.

В файле .csproj мы видим SDK, целевой фреймворк, в нашем случае .NET 6 и корневое пространство имен.

Мы также видим ссылку на пакет Swashbuckle.AspNetCore для SwaggerUI.

Позже в этом файле мы найдем дополнительные пакеты, такие как Entity Framework Core.

Что касается файлов appsettings.json, нам нужно только знать, что здесь мы можем добавлять и изменять некоторые конфигурации.

Сейчас более интересным является файл launchSettings.json, в котором настраивается текущая среда, а также URL-адрес приложения. С помощью этого URL-адреса мы найдем нашу работающую веб-службу.

Папки obj и bin пока можно игнорировать. Здесь мы находим временные объектные и окончательные бинарные файлы.

Очень интересной и часто используемой в этой серии руководств является папка Controllers.

Первый контроллер, который вы видите здесь, — это сгенерированный демонстрационный контроллер WeatherForecast. Подробнее о контроллерах мы поговорим позже. Пока важно только знать, что мы уже можем вызвать здесь метод Get()Get().

Первый вызов API

В терминале вводим dotnet watch run, чтобы запустить наше приложение и уже использовать вотчер и горячую перезагрузку. Ваш браузер по умолчанию должен открыться автоматически, и в терминале, который вы видите, уже есть URL-адрес, который мы видели в файле launchSettings.json.

То, что мы здесь уже видим, — это пользовательский интерфейс Swagger. Это поможет нам протестировать наш веб-API, но давайте на секунду забудем о Swagger. Здесь вы уже можете видеть контроллер WeatherForecast, но мы также можем получить доступ к контроллеру с помощью адресной строки Chrome.

Когда мы возвращаемся в VS Code, мы видим имя контроллера ( WeatherForecast — без «Контроллер»). Мы также видим атрибут маршрутизации ([Route("[controller]”)), чтобы определить, как получить доступ к этому контроллеру — мы обсудим, как работают маршруты в следующей главе.

Итак, мы просто копируем название — WeatherForecast — возвращаемся в Chrome, вводим правильный маршрут и, наконец, получаем результаты.

Теперь вернемся к Сваггеру. Здесь вы видите контроллер, а также схему.

Схема на самом деле является классом WeatherForecast, который сообщает нам, как будет выглядеть результат вызова веб-API.

Теперь выше это не только контроллер, это фактически вызов GET веб-API. Мы видим доступные параметры — в данном конкретном случае параметров нет — и видим ожидаемый результат.

И лучше всего то, что мы можем попробовать это прямо здесь. Давайте сделаем это!

Когда мы нажимаем «Выполнить», мы видим URL-адрес запроса (это то же самое, что мы ввели в адресную строку минуту назад) и видим результат.

Мы также можем увидеть результат на вкладке «Сеть» в Инструментах разработчика Chrome. Просто нажмите F12 на клавиатуре, чтобы открыть инструменты, перейдите на вкладку Сеть, отфильтруйте по XHR — что означает запросы XML Http — и снова выполните вызов.

Видите ли, результат по сути тот же, только случайные значения другие.

Большой! Так что это работает. Теперь давайте перейдем к созданию нашего собственного веб-сервиса.

Веб-API

Введение

Итак, вы узнали, как создать проект веб-API в .NET с нуля и как сделать свой первый вызов API.

В следующих разделах мы создадим новый контроллер и модели для наших персонажей RPG (ролевых игр).

Кроме того, мы превратим наши синхронные вызовы в асинхронные вызовы, будем использовать объекты передачи данных (DTO) и изменим структуру нашего веб-API, чтобы он соответствовал передовым практикам.

Но сначала давайте взглянем на шаблон Model-View-Controller (MVC), который является основой всего этого.

Шаблон модель-представление-контроллер (MVC)

Модель-представление-контроллер или сокращенно MVC — это шаблон проектирования программного обеспечения, который делит связанную логику программы на три взаимосвязанных элемента. Позвольте мне объяснить, что означает каждый из этих трех элементов и как они взаимодействуют.

Начнем с модели. Можно также сказать, данные. Например, персонаж нашей ролевой игры — это модель. У него может быть идентификатор, имя, очки жизни, атрибуты, навыки и так далее.

Вы как разработчик знаете код своей модели. Но пользователь не увидит ваш код. Вот тут-то и появляется представление. Пользователь, вероятно, хочет увидеть представление персонажа в HTML, простом тексте или потрясающей 3D-графике — в зависимости от вашей игры. Другими словами, представление — это (графический) пользовательский интерфейс или (G)UI.

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

А что сейчас с контроллером? Контроллер делает фактическую работу. Там вы найдете большую часть своего кода, потому что он манипулирует вашими данными или моделью. В нашем случае это веб-API, который будет создавать, обновлять и удалять ваши данные.

Поскольку у нас не будет представления, кроме результатов наших вызовов в Postman, мы собираемся собрать наше приложение в следующем порядке: сначала модель, а затем контроллер. И мы всегда будем прыгать туда-сюда между этими двумя.

Однако с помощью представления пользователь может манипулировать данными, следовательно, свойствами персонажа RPG с кнопками, текстовыми полями и так далее. В браузерной игре это может быть по сути код JavaScript — возможно, с помощью фреймворков вроде Angular, React или VueJS — или Blazor WebAssembly.

Этот код JavaScript, в свою очередь, использует контроллер для выполнения манипуляций и постоянного сохранения этих изменений в базе данных. Управляемая модель обновит представление, которое затем снова увидит пользователь, и круг начнется снова.

Что ж, это подводит итог шаблону MVC. Теперь мы собираемся построить нашу первую модель.

Новые модели

В первую очередь нам нужны новые модели. Нам нужна модель для самого персонажа RPG, а также модель для типа персонажа RPG, т. е. класс персонажа, такой как варвар, монах, некромант и так далее.

Сначала мы создаем папку Models.

Для модели персонажа мы создадим новый класс в этой папке Models. Если у вас установлены «Расширения C#», вы можете добавить новый класс C#, щелкнув правой кнопкой мыши, в противном случае вы просто создадите новый файл.

Поэтому щелкните правой кнопкой мыши папку «Модели», затем выберите «Новый класс C#» и назовите этот класс Character.

Теперь давайте добавим некоторые свойства.

Мы также добавим свойство RpgClass, то есть тип персонажа. Но сначала мы должны создать для этого новый enum.

Итак, в папку Models добавим новый C# enum с именем RpgClass.

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

Теперь, когда у нас есть готовый RpgClass enum, мы наконец можем добавить его к модели Character.

Я установил по умолчанию Рыцаря, но опять же, это полностью зависит от вас.

Итак, первые модели готовы. Давайте теперь добавим новый контроллер и сделаем вызов GET, чтобы получить нашего первого персонажа ролевой игры.

Новый контроллер и ПОЛУЧИТЕ нового персонажа

Чтобы добавить новый контроллер, мы создаем новый класс C# в папке Controllers. С расширением C# мы также могли бы уже создать подготовленный класс «Контроллер API», но давайте сначала выполним необходимые шаги вручную.

Назовем этот класс CharacterController.

Прежде чем мы сможем начать реализацию какой-либо логики, мы должны сделать эту штуку правильным контроллером. Для этого мы сначала получаем из ControllerBase. Для этого мы также должны добавить соответствующую ссылку, Microsoft.AspNetCore.Mvc.

Это базовый класс для контроллера MVC безподдержки представлений.

Поскольку здесь мы создаем API, нам не нужнаподдержка представлений. Однако, если мы хотим добавить поддержку представлений, мы могли бы получить от Controller. Но в нашем случае просто добавьте ControllerBase.

public class CharacterController : ControllerBase

После этого мы должны добавить некоторые атрибуты. Первый — это атрибут [ApiController]. Этот атрибут указывает, что тип (а также все производные типы) используется для обслуживания ответов HTTP API.

Кроме того, когда мы добавляем этот атрибут в контроллер, он активирует несколько специфичных для API функций, таких как маршрутизация атрибутов и автоматические ответы HTTP 400, если с моделью что-то не так. Мы узнаем подробности, когда воспользуемся этими функциями.

[ApiController]
public class CharacterController : ControllerBase

Что касается маршрутизации атрибутов, это уже следующая вещь, которую мы должны добавить.

Под атрибутом [ApiController] мы добавляем атрибут [Route]. Вот как мы можем найти этот конкретный контроллер, когда хотим сделать вызов веб-службы.

Строка, которую мы добавляем к атрибуту [Route], равна ("api/[controller]”) (в скобках). Это означает, что к этому контроллеру можно получить доступ по строке «api», а затем по его имени, в нашем случае «Character» — то есть по той части имени класса C#, которая стоит перед «Controller».

[ApiController]
[Route("api/[controller]")]
public class CharacterController : ControllerBase

Обратите внимание, что WeatherForecastController не имеет строки «api». Опять же, это полностью зависит от вас.

Хорошо, давайте перейдем к телу нашего класса C#. Первое, что я хотел бы добавить, это статический фиктивный персонаж, который мы можем вернуть клиенту. Для этого вам нужно добавить ссылку dotnet_rpg.Models.

Поскольку здесь мы используем C# 10, мы могли бы также добавить ключевое слово «global» в директиву using и, возможно, переместить эту строку в Program.cs. Теперь все приложение знает эту ссылку, и нам больше никогда не придется добавлять директиву using.

Затем мы, наконец, реализуем метод Get() для получения нашего игрового персонажа.

Мы возвращаем IActionResult, потому что это позволяет нам отправлять определенные коды состояния HTTP обратно клиенту вместе с фактическими данными, которые были запрошены. В этом методе с помощью Ok(knight) мы отправляем код состояния 200 OK и наш фиктивный персонаж обратно.

Другими вариантами могут быть код состояния BadRequest 400 или 404 NotFound, если запрошенный символ не найден.

Хорошо, код реализован. Давайте проверим это сейчас, снова запустив приложение с dotnet watch run.

Открывая SwaggerUI, мы сначала видим Error!

Тем не менее, давайте попробуем вызвать метод нашего веб-сервиса через браузер. Как и в случае с WeatherForecastController, мы должны ввести маршрут CharacterController в адресную строку браузера. Обратите внимание на порт вашего URL, он может отличаться. В моем случае полный URL — https://localhost:7298/api/character. Этот URL должен привести нас к желаемому результату.

Вернемся к Swagger, давайте откроем инструменты разработчика и посмотрим на вкладку «Сеть». Здесь мы видим настоящую проблему: Действиям требуется явная привязка HttpMethod для Swagger.

Возвращаясь к VS Code, обратите внимание на атрибут, который был добавлен в наш метод Get(). Точно, нет.

Когда мы сравниваем это с WeatherForecastController, мы могли бы добавить атрибут [HttpGet].

Но это не обязательно для CharacterController, поскольку веб-API поддерживает соглашения об именах, и если имя метода начинается с Get...(), API предполагает, что используемый HTTP-метод также GET.

Кроме того, пока у нас в контроллере только один метод Get(), поэтому веб-служба точно знает, какой метод запрашивается.

Тем не менее, как мы теперь знаем, чтобы помочь Swagger, мы должны добавить атрибут [HttpGet] . Давайте сделаем это, а затем вернемся в Chrome.

[HttpGet]
public IActionResult Get()

Сейчас мы видим метод, но не видим никаких схем или ожидаемых типов возвращаемого значения.

Вернемся к VS Code еще раз и изменим тип возвращаемого значения на ActionResult типа CharacterCharacter.

[HttpGet]
public ActionResult<Character> Get()

После сохранения этого изменения нам, вероятно, придется перезапустить наше приложение из-за грубого редактирования.

Итак, давайте сделаем это, и, наконец, мы видим всю нужную информацию. Swagger показывает нам наш класс Character и перечисление RpgClass.

Есть еще одна маленькая вещь, которую мы можем добавить.

Глядя на перечисление, мы видим только номера вместо имени RpgClass.

Мы можем изменить это, настроив JsonConverter в файле enum.

Мы добавляем атрибут над определением перечисления с классом JsonStringEnumConverter, который преобразует значения перечисления в строки и обратно. Мы также должны добавить соответствующую ссылку для этого, а именно System.Text.Json.Serialization.

Если вы по-прежнему не видите названия классов RPG, возможно, вам придется перезапустить приложение вручную.

Но после этого мы видим имена RpgClass и можем без проблем протестировать метод Get().

Это первая часть этой серии руководств. Надеюсь, он уже был вам полезен. Большое вам спасибо за ваше время! Чтобы получать уведомления о следующей части, просто подпишитесь на мою рассылку или подпишитесь на меня здесь, на Medium. Вы узнаете об этом первыми.

Увидимся в следующий раз!

Заботиться,

Патрик

Далее: маршрутизация атрибутов, методы HTTP, добавление нового символа с помощью POST, асинхронные вызовы и многое другое!

Но подождите, есть еще!

  • ▶️ ️Наслаждайтесь множеством руководств по .NET и Blazor на YouTube.

Повышение уровня кодирования

Спасибо, что являетесь частью нашего сообщества! Больше контента в публикации Level Up Coding.
Подписывайтесь: Twitter, LinkedIn, Информационный бюллетень
Level Up меняет рекрутинг в сфере технологий ➡️ Присоединяйтесь к нашему коллективу талантов