Как я создаю с нуля полный API с помощью .Net 7, использую внешний интерфейс с помощью Blazor и публикую в Azure Cloud сильный>!
Идея здесь состоит в том, чтобы быть очень простым проектом списка дел, ориентированным на ежедневные рутинные исследования разработчиков, где также можно реагировать на эти задачи. Надеюсь, тебе понравится!
Создание API💻
Прежде всего, я начинаю с создания основы проекта, API, который будет содержать глаголы, которые я использую для манипулирования информацией. Я использую Visual Studio Code для его кодирования, и я буду считать, что у вас есть базовые знания в области программирования и есть все предварительные условия и библиотеки для кодирования на C # и ASP.Net.
Я создаю шаблон для проекта API, используя эту команду CLI:
dotnet new webapi -o DevToDoList.API
После этого я получаю доступ к созданному каталогу preject и в каталоге Controllers я создаю DevTodosController.cs.
Этот файл будет отвечать за выполнение запросов и имеет конфигурацию маршрутов в нашем API к базе данных. Обратите внимание, что я унаследовал класс ControllerBase, очень часто используемый для построения API в структуре MVC. Также аннотация ApiController в верхней части класса имеет некоторые соглашения и упрощает некоторые вещи, такие как определение параметров.
using DevToDoList.API.Entities; using DevToDoList.API.Models; using DevToDoList.API.Persistence; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Models; namespace DevToDoList.API.Controllers { [ApiController] [Route("api/dev-todo")] public class DevTodosController : ControllerBase { private readonly DevTodoDbContext _context; public DevTodosController(DevTodoDbContext context) { _context = context; } [HttpGet] public IActionResult GetAll() { var devTodos = _context.DevTodos.ToList(); return Ok(devTodos); } // api/dev-todo/1 HTTP GET [HttpGet("{id}")] public IActionResult GetById(int id) { var devTodo = _context.DevTodos .Include(s => s.Reactions) .SingleOrDefault(s => s.Id == id); if (devTodo == null) return NotFound(); return Ok(devTodo); } [HttpPost] public IActionResult Post(DevTodoInputModel model) { var devTodo = new DevTodo(model.Title, model.Description, model.Done); _context.DevTodos.Add(devTodo); _context.SaveChanges(); return CreatedAtAction("GetById", new { id = devTodo.Id }, model); } // api/dev-todo/1/reactions HTTP POST [HttpPost("{id}/reactions")] public IActionResult PostReaction(int id, ReactionDevTodoInputModel model) { var devTodo = _context.DevTodos.SingleOrDefault(s => s.Id == id); if (devTodo == null) return BadRequest(); devTodo.AddReaction(model.IsPositive); _context.SaveChanges(); return NoContent(); } } }
Здесь у нас есть метод HttpGet, который возвращает все задачи в базе данных, если они есть. HttpGet, который вернет только один регистр по идентификатору. HttpPost, который добавит задачу в базу данных, и другой HttpPost, который опубликует реакцию на любую из этих задач.7
Закрытая переменная _context только для чтения отвечает за обеспечение связи между методами API и базой данных. Мы поговорим об этом позже.
У нас есть эти модели в каталоге Models:
DevTodoInputModel.cs
namespace Models { public class DevTodoInputModel { public string Title { get; set; } public string Description { get; set; } public bool Done { get; set; } } }
ReactionDevTodoInputModel.cs
namespace DevToDoList.API.Models { public class ReactionDevTodoInputModel { public int DevTodoId { get; set; } public bool IsPositive { get; set; } } }
Теперь Entities только с данными, которые будут доступны снаружи. Это концепция безопасности, которая облегчает связь между системами. Это хорошая практика, потому что она не позволяет раскрывать конфиденциальную информацию.
DevTodo.cs
namespace DevToDoList.API.Entities { public class DevTodo { public DevTodo(string title, string description, bool isDone) { Title = title; Description = description; IsDone = isDone; Reactions = new List<DevTodoReaction>(); CreatedAt = DateTime.Now; } public int Id { get; private set; } public string Title { get; private set; } public string Description { get; private set; } public bool IsDone { get; private set; } public DateTime CreatedAt { get; private set; } public List<DevTodoReaction> Reactions { get; private set; } public void AddReaction(bool isPositive) { Reactions.Add(new DevTodoReaction(isPositive)); } } }
ReactionDevTodoInputModel.cs
namespace DevToDoList.API.Models { public class ReactionDevTodoInputModel { public int DevTodoId { get; set; } public bool IsPositive { get; set; } } }
Настройка базы данных 🏦
Я использовал Entity Framework Core, чтобы обеспечить постоянство базы данных данных приложения. Если вы новичок в Entity Framework, я рекомендую документацию Microsoft, чтобы помочь вам начать работу с ней.
Я использую интерфейс командной строки dotnet, поэтому для начала я запускаю эту команду, чтобы убедиться, что он распознает ее, когда я ее использую:
dotnet tool install --global dotnet-ef
Я также устанавливаю эти пакеты NuGet:
- Microsoft.EntityFrameworkCore.InMemory
- Microsoft.EntityFrameworkCore.SQLServer
- Microsoft.EntityFrameworkCore.Design
Если вы находитесь в VSCode, необходимо будет установить диспетчер пакетов NuGet для установки этих пакетов.
После этого я создал директорию Persistence и в ней файл DevTodoDbContext.cs.
Этот файл важен тем, что в нем будут установлены свойства DbSet, которые будут представлять наши таблицы в базе данных вверх.
using DevToDoList.API.Entities; using Microsoft.EntityFrameworkCore; namespace DevToDoList.API.Persistence { public class DevTodoDbContext : DbContext { public DevTodoDbContext(DbContextOptions<DevTodoDbContext> options) : base(options) {} public DbSet<DevTodo> DevTodos { get; set; } public DbSet<DevTodoReaction> DevTodoReactions { get; set; } protected override void OnModelCreating(ModelBuilder builder) { builder.Entity<DevTodo>(e => { e.HasKey(s => s.Id); e.HasMany(s => s.Reactions) .WithOne() .HasForeignKey(r => r.DevTodoId) .OnDelete(DeleteBehavior.Restrict); }); builder.Entity<DevTodoReaction>(sn => { sn.HasKey(s => s.Id); }); } } }
Обратите внимание на защищенный метод OnModelCreating, который в основном определяет первичный ключ и внешний ключ в наших таблицах.
Мы также должны добавить следующий код в файлы program.cs и appsettings.json:
appsettings.json
, "AllowedHosts": "*", "ConnectionStrings": { "DevTodoList": "server=yourservername; Database=DevTodoListDb; Integrated Security=True; trustServerCertificate=true" }
Здесь будет строка подключения к вашей базе данных.
program.cs
var connectionString = builder.Configuration.GetConnectionString("DevTodoList"); builder.Services.AddDbContext<DevTodoDbContext>( o => o.UseSqlServer(connectionString) );
Здесь соединение выполняется с использованием конфигурации SqlServer.
Вся настройка завершена, теперь мы можем запустить эти команды, чтобы легко создать нашу базу данных с помощью Entity Framework Core:
dotnet ef migration add FirstMigration -o Persistence/Migrations
Это создаст нашу папку миграции и первую миграцию с командами базы данных, которые будут выполняться для создания нашей базы данных и таблиц.
Теперь мы запускаем эту команду для запуска и обновления нашей базы данных.
dotnet ef database update
Теперь наша база данных с нашими таблицами и столбцами должна быть создана, и мы можем проверить ее с помощью Management Studios или любой другой SGDB.
Документация с Swagger 📗
До сих пор мы сохраняли простоту документирования API с помощью Swagger. Но можно детализировать различные данные, такие как описание, параметры и коды ответов. Это значительно упрощает интеграцию и общение между членами команды и другими командами.
Что добавить при документировании APIS?
- Описание;
- Примеры объектов для отправки (POST, PUT и другие)
- Возможные коды ответа на конечной точке
- Параметры и их описания.
Чтобы это стало возможным, мы должны добавить этот фрагмент кода в файл .csproj приложения API. Этот фрагмент будет отвечать за включение генерации файла документации с использованием Swagger и отключит некоторые ненужные предупреждения.
<PropertyGroup> <generateDocumentationFile>true</generateDocumentationFile> <NoWarn>$(NoWarn);1591</NoWarn> </PropertyGroup>
Теперь мы можем создать метод документации в контроллере:
— Убедитесь, что у вас установлено расширение VSCode: Комментарии к XML-документации C#
— Затем введите 3 косых черты («/») над выбранным методом документирования.
Теперь вы можете поместить некоторую информацию следующим образом:
// api/dev-todo HTTP POST /// <summary> /// Add a To Do task. /// </summary> /// <remarks> /// { "title": "Clean Architecture", "Description": "Definition and examples.", "IsDone": true } /// </remarks> /// <param name="model">Todo Task data</param> /// <returns>Object created</returns> /// <response code="201">Success</response>
Я помещаю json-пример объекта, который этот метод, в случае HttpPost, может обслуживать.
Наконец, в Program.cs мы устанавливаем следующий код:
builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "DevTodoList.API", Version = "v1", Contact = new OpenApiContact { Name = "Mario Alves", Email = "[email protected]", LinkedIn = new Uri("https://www.linkedin.com/in/marioalvesneto/") } }); var xmlFile = "DevTodoList.API.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); });
Это может помочь другим разработчикам ответить на вопросы, которые могут у них возникнуть при использовании нашего API.
В дополнение к вставке комментариев в метод с помощью данных, введенных в контроллере.
Чтобы выполнить API, не забудьте просто запустить следующую команду в каталоге проекта:
dotnet run
Логирование с помощью Serilog 🔍
Serilog — это инструмент ведения журналов, предназначенный для мониторинга и облегчения мониторинга и потока журналов из приложения .NET.
- Serilog — это библиотека, которая позволяет вести журнал для приложений .NET.
- Он поддерживает множество форматов, таких как SQL Server, SQLite, PostgreSQL и другие.
- Библиотека для ядра [ASP.NET](http://ASP.NET), которую мы будем использовать, называется Serilog.AspNetCore.
Мы устанавливаем две Пакеты Nuget:
— Serilog.Sinks.MSSqlServer
— Serilog.AspNetCore
Теперь снова заходим в Program.cs:
// Configuration to Serilog database registration. builder.Host.ConfigureAppConfiguration((hostingContext, config) => { Serilog.Log.Logger = new LoggerConfiguration() .Enrich.FromLogContext() .WriteTo.MSSqlServer(connectionString, sinkOptions: new MSSqlServerSinkOptions() { AutoCreateSqlTable = true, TableName = "Logs" }) .WriteTo.Console() .CreateLogger(); }).UseSerilog();
Здесь мы в основном определяем, что мы хотим автоматически создать таблицу Sql с именем Logs, которая будет содержать журналы ОС реестра, сгенерированные Serilog.
Теперь при тестировании базы данных возвращается ошибка с использованием Serilog на практике:
Теперь при вызове метода GetAll таблица и реестр логов будут сохраняться в SQL Server:
Это очень полезно, потому что показывает журналы, которые мы хотим показать, а также все другие журналы, такие как успехиисключение. Мы можем использовать его, чтобы показать эти журналы в более «красивом» и удобном интерфейсе, например, для пользователя или администратора приложения.
Публикация в облаке ☁️
Теперь мы публикуем приложение в облаке. Я буду использовать службу приложений Azure, где есть бесплатный уровень для тестирования в облаке Azure.
- Будьте внимательны при загрузке приложения: проверьте версию .NET приложения при загрузке в облако, она должна совпадать с созданной службой приложений Azure. Пример. Приложение находится в .NET 7, поэтому обязательно, чтобы Служба приложений работала с .NET в этой версии.
- Шаг за шагом для публикации ресурса в облаке:
- Как только это будет сделано и об этих важных деталях позаботятся, мы сможем загрузить приложение.
- Во-первых, отключите интеграцию базы данных, поскольку у нас не будет базы данных в облаке (в этом примере), и оставим только базу данных в памяти.
- Затем мы можем установить расширение VSCode Azure App Service, чтобы легко загрузить приложение в облако Azure.
Установив и войдя в свою учетную запись Azure из расширения VSCode, просто загрузите свое приложение в созданную службу приложений Azure:
Если вы сейчас запустите приложение из Azure и добавите /swagger к URL-адресу, вы обнаружите, что приложение работает нормально.
Бонус: использование API во внешнем интерфейсе📝
В качестве бонуса к этой истории здесь, на Medium, я подготовил свой собственный интерфейс для использования этого API здесь, который мы создали ⭐️ в центре внимания проекта был API, но я создаю этот интерфейс, чтобы показать структуру интерфейса .net Blazor, это потрясающе, и я очень рекомендую.
Важная деталь для использования нашего API во внешнем интерфейсе: знаменитая ошибка CORS. Чтобы этого избежать, нам нужно добавить следующий код в program.cs в проекте API:
builder.Services.AddCors( options => { options.AddDefaultPolicy( policy => { policy.WithOrigins("frontend_url"); }); }); app.UseCors();
Затем добавьте URL-адрес туда в frontend_url и настройте свой интерфейс для получения информации, поступающей от вашего API.
В итоге мой интерфейс выглядел так:
Очень просто, можно многое улучшить, хе-хе.
Ссылка на репозиторий: https://github.com/marioalvesx/DevToDoList
Спасибо, надеюсь, вам понравится!