[.NET, ASP, C] Как создать простое Rest API на .NET Core
Автор
Сообщение
news_bot ®
Стаж: 6 лет 4 месяца
Сообщений: 27286
ВведениеВсем привет, в данной статье будет рассказано, как с использованием технологии C# ASP.NET Core написать простое Rest Api. Сделать Unit-тесты на слои приложений. Отправлять Json ответы. Также покажу, как выложить данное приложение в Docker. В данной статье не будет описано, как делать клиентскую (далее Front) часть приложения. Здесь я покажу только серверную (далее Back).Что используем?Писать код я буду в Visual Studio 2019. Для реализации приложения, я буду использовать такие библиотеки NuGet:
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Tools
Для тестов вот эти библиотеки:
- Microsoft.NET.Test.Sdk
- Microsoft.NETCore.App
- Moq
- xunit
- xunit.runner.visualstudio
Для установки пакетов нужно зайти в обозреватель пакетов NuGet, сделать это можно, нажав ПКМ по проекту, и выбрав там пункт «управление пакетам NuGet»Что программировать?Для примера я возьму сильно упрощенную модель сервиса по ремонту автомобилей. В моей модели будут работники, которые будут заниматься ремонтом, автомобили, поступающие на ремонт, и документация по ремонту, которая будет отсылаться в ответе.Настройка Базы ДанныхДля настройки базы данных нужен класс ApplicationContext (реализация будет далее) и строка подключения, которая храниться в файле «appsettings.json». В этом классе будут прописаны все зависимости для генерации миграций. Строка подключения нужна для того, чтобы приложение знало в какую БД ей обращаться и с какими параметрами.Чтобы добавить строку подключения, достаточно зайти в файл «appsettings.json» и прописать следующие строки:
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=testdb;Trusted_Connection=True;"
},
Описание слоев приложенияМоделиВ слое моделей будут находиться сущности, которые с помощью Entity Framework будут преобразованы в таблицы в базе данных. Для описания модели в приложении достаточно просто описать класс, с нужными вам полями. Эти поля автоматически будут преобразованы в столбцы таблицы, а название таблицы будет соответствовать названию класса. Так задано по умолчанию, но есть специальные атрибуты, которые позволяют более гибко настраивать хранение данных в БД (но о них не в этой статье).Первая модель, которая понадобиться для описания сервиса по ремонту - модель сотрудника. Что она будет из себя представлять?
- Уникальный идентификатор сотрудника
- Имя сотрудника
- Должность сотрудника
- Номер телефона для связи с сотрудником
Следующая модель для описания сервиса - автомобили, которые будут поступать на ремонт.
- Уникальный идентификатор автомобиля
- Название автомобиля
- Номер автомобиля
И последняя модель, которую мы уже будем отсылать - документ (выписка) по ремонту.
- Уникальный идентификатор документа
- Сотрудник, который обслуживал автомобиль
- Автомобиль, который был на ремонте
Чтобы модели попали в базу данных, необходимо создать миграцию. Миграция - описание того, как и что будет записано в базу данных. С помощью Entity Framework миграции можно генерировать автоматически. Для этого в пакетном менеджере надо прописать команду "Add-Migration". После этого Entity Framework сгенерирует миграцию по вашим моделям, которые указаны в классе DbContext. Чтобы применить миграцию, используем команду "Update-Database", после этого ваши данные попадут в базу данных (как это применять будет описано далее).КонтроллерыКонтроллер - посредник между бизнес-логикой, либо базой данных и Front частью приложения. Получая запрос с Front, контроллер обрабатывает запрос, вызывает необходимые сервисы для реализации некой бизнес-логики и отправляет полученные данные обратно на Front.Для возвращаемого значения в контроллерах будут использоваться тип Json. Для этого достаточно в return прописать
new JsonResult(Ваш объект)
В данном примере, я покажу как сделать методы для GET, POST, PUT и DELETE запросов. В GET-запросе я буду выбирать все существующие документы и передавать их на Front, а в POST-запросе я буду вызывать сервис по ремонту автомобиля и возвращать выписку по ремонту, PUT будет отвечать за обновление существующего документа и DELETE за удаление документа.DAO (Репозитории)Репозитории нужны как посредники для обеспечения работы с БД, чтобы исключить прямое взаимодействие человека с данными. Это нужно для того, чтобы сокрыть логику работы автоматизировать многие моменты работы с БД, а также для безопасной работы с данными.В своем приложении я сделал репозиторий, который может принимать любую модель, и выполнять такие действия как get, get all, update, create, delete.СервисыСервисы - такие классы, которые содержат в себе бизнес-логику приложения. Представляют из себя класс с методами для решения той или иной задачи.В качестве примера сервиса, я сделал класс, всего с одним методом Work. Этот метод имитирует работу моего сервиса по починке машин. В этом методе «нанимается» рабочий, заводится автомобиль и заполняется документ о его починке.РеализацияТеперь, когда описано что и как будет устроено в приложении можно приступить и к реализации.Создание проектаПри создании нового проекта, я выбрал веб-приложение ASP.NET Core, далее прописал его название (RestApi) и выбрал папку, где оно будет храниться. На экране выбора шаблона выбрал API.![Клик для увеличения](https://linkme.ufanet.ru/box/200x100/f13b42dd0ab4b41d0bc333bb47bcab69.jpg)
Выбор шаблона приложенияДалее приступим к самому приложению.СтруктураЯ разделил все приложение по папкам (также Unit-тесты в отдельном проекте) и получил вот такую структуру мое приложения:![Клик для увеличения](https://linkme.ufanet.ru/box/200x100/d41356034d6f5b1f36556246f8296e4a.jpg)
Структура приложенияМоделиДля реализации моделей я сделал абстрактный класс BaseModel. Он понадобиться в будущем для корректного наследования, а также в нем прописан Id каждой, модели (это помогает не дублировать код):
public abstract class BaseModel
{
public Guid Id { get; set; }
}
Далее вышеописанные модели:
public class Car : BaseModel
{
public string Name { get; set; }
public string Number { get; set; }
}
public class Document : BaseModel
{
public Guid CarId { get; set; }
public Guid WorkerId { get; set; }
public virtual Car Car { get; set; }
public virtual Worker Worker { get; set; }
}
public class Worker : BaseModel
{
public string Name { get; set; }
public string Position { get; set; }
public string Telephone { get; set; }
}
РепозиторийКак уже было сказано репозиторий будет один, но сможет работать с абсолютно любой моделью. Также я сделал интерфейс для репозитория, чтобы инкапсулировать его работу.Интерфейс:
public interface IBaseRepository<TDbModel> where TDbModel : BaseModel
{
public List<TDbModel> GetAll();
public TDbModel Get(Guid id);
public TDbModel Create(TDbModel model);
public TDbModel Update(TDbModel model);
public void Delete(Guid id);
}
Реализация:
public class BaseRepository<TDbModel> : IBaseRepository<TDbModel> where TDbModel : BaseModel
{
private ApplicationContext Context { get; set; }
public BaseRepository(ApplicationContext context)
{
Context = context;
}
public TDbModel Create(TDbModel model)
{
Context.Set<TDbModel>().Add(model);
Context.SaveChanges();
return model;
}
public void Delete(Guid id)
{
var toDelete = Context.Set<TDbModel>().FirstOrDefault(m => m.Id == id);
Context.Set<TDbModel>().Remove(toDelete);
Context.SaveChanges();
}
public List<TDbModel> GetAll()
{
return Context.Set<TDbModel>().ToList();
}
public TDbModel Update(TDbModel model)
{
var toUpdate = Context.Set<TDbModel>().FirstOrDefault(m => m.Id == model.Id);
if (toUpdate != null)
{
toUpdate = model;
}
Context.Update(toUpdate);
Context.SaveChanges();
return toUpdate;
}
public TDbModel Get(Guid id)
{
return Context.Set<TDbModel>().FirstOrDefault(m => m.Id == id);
}
}
СервисСервис также как и репозиторий имеет интерфейс и его реализацию.Интерфейс:
public interface IRepairService
{
public void Work();
}
Реализация:
public class RepairService : IRepairService
{
private IBaseRepository<Document> Documents { get; set; }
private IBaseRepository<Car> Cars { get; set; }
private IBaseRepository<Worker> Workers { get; set; }
public void Work()
{
var rand = new Random();
var carId = Guid.NewGuid();
var workerId = Guid.NewGuid();
Cars.Create(new Car
{
Id = carId,
Name = String.Format($"Car{rand.Next()}"),
Number = String.Format($"{rand.Next()}")
});
Workers.Create(new Worker
{
Id = workerId,
Name = String.Format($"Worker{rand.Next()}"),
Position = String.Format($"Position{rand.Next()}"),
Telephone = String.Format($"8916{rand.Next()}{rand.Next()}{rand.Next()}{rand.Next()}{rand.Next()}{rand.Next()}{rand.Next()}")
});
var car = Cars.Get(carId);
var worker = Workers.Get(workerId);
Documents.Create(new Document {
CarId = car.Id,
WorkerId = worker.Id,
Car = car,
Worker = worker
});
}
}
КонтроллерУ меня в приложении всего один контроллер, но по его шаблону можно сделать сколько угодно контроллеров. Когда приложение запущено, для того чтобы обратиться к методу контроллера с Front части приложения, достаточно передать запрос, который выглядит примерно вот так:ДоменноеИмя/НазваниеКонтроллера/НазваниеМетода?Параметры(если есть)Пути гибко настраиваются с помощью специальных атрибутов (о них не в этой статье).Мой MainController:
[ApiController]
[Route("[controller]")]
public class MainController : ControllerBase
{
private IRepairService RepairService { get; set; }
private IBaseRepository<Document> Documents { get; set; }
public MainController(IRepairService repairService, IBaseRepository<Document> document )
{
RepairService = repairService;
Documents = document;
}
[HttpGet]
public JsonResult Get()
{
return new JsonResult(Documents.GetAll());
}
[HttpPost]
public JsonResult Post()
{
RepairService.Work();
return new JsonResult("Work was successfully done");
}
[HttpPut]
public JsonResult Put(Document doc)
{
bool success = true;
var document = Documents.Get(doc.Id);
try
{
if (document != null)
{
document = Documents.Update(doc);
}
else
{
success = false;
}
}
catch (Exception)
{
success = false;
}
return success ? new JsonResult($"Update successful {document.Id}") : new JsonResult("Update was not successful");
}
[HttpDelete]
public JsonResult Delete(Guid id)
{
bool success = true;
var document = Documents.Get(id);
try
{
if (document != null)
{
Documents.Delete(document.Id);
}
else
{
success = false;
}
}
catch (Exception)
{
success = false;
}
return success ? new JsonResult("Delete successful") : new JsonResult("Delete was not successful");
}
}
Application ContextApplicationContext – класс, который унаследован от класса DbContext. В нем прописываются все DbSet. С их помощью приложение знает, какие модели должны быть в базе данных, а какие нет.
public class ApplicationContext: DbContext
{
public DbSet<Car> Cars { get; set; }
public DbSet<Document> Documents { get; set; }
public DbSet<Worker> Workers { get; set; }
public ApplicationContext(DbContextOptions<ApplicationContext> options): base(options)
{
Database.EnsureCreated();
}
}
Настройка зависимостей и инжектированияА теперь немного про инжектирование. Правильная настройка зависимостей проекта Asp.net core позволяет упростить его работу и избежать лишнего написания кода. Все зависимости прописываются в файле «Startup.cs».Что я связывал? Я связывал интерфейс репозитория с репозиторием каждой модели (далее будет видно, что имеется ввиду), также я связал интерфейс сервиса с его реализацией.Также в этом же файле прописываются настройки для базы данных. Помните про строку подключения из начала статьи? Так вот сейчас мы ее и используем для настройки БД.Вот как выглядит мой файл «Startup.cs»:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
string connection = Configuration.GetConnectionString("DefaultConnection");
services.AddMvc();
services.AddDbContext<ApplicationContext>(options =>
options.UseSqlServer(connection));
services.AddTransient<IRepairService, RepairService>();
services.AddTransient<IBaseRepository<Document>, BaseRepository<Document>>();
services.AddTransient<IBaseRepository<Car>, BaseRepository<Car>>();
services.AddTransient<IBaseRepository<Worker>, BaseRepository<Worker>>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Не забудьте создать БД перед запуском приложения. Для этого в Консоле диспетчера пакетов нужно прописать следующие команды:Add-Migration init (или любое другое имя)Update-DatabaseПоздравляю, если все шаги выполнены корректно, то вы создали свою базу данных. Также эти команды используются и для ее обновления, если ваши модели поменяются.ТестированиеЗдесь я покажу как создать UNIT-тесты для контроллера и сервиса. Для тестов я сделал отдельный проект (библиотека классов .Net Core).Тест для контроллера
public class MainControllerTests
{
[Fact]
public void GetDataMessage()
{
var mockDocs = new Mock<IBaseRepository<Document>>();
var mockService = new Mock<IRepairService>();
var document = GetDoc();
mockDocs.Setup(x => x.GetAll()).Returns(new List<Document> { document });
// Arrange
MainController controller = new MainController(mockService.Object, mockDocs.Object);
// Act
JsonResult result = controller.Get() as JsonResult;
// Assert
Assert.Equal(new List<Document> { document }, result?.Value);
}
[Fact]
public void GetNotNull()
{
var mockDocs = new Mock<IBaseRepository<Document>>();
var mockService = new Mock<IRepairService>();
mockDocs.Setup(x => x.Create(GetDoc())).Returns(GetDoc());
// Arrange
MainController controller = new MainController(mockService.Object, mockDocs.Object);
// Act
JsonResult result = controller.Get() as JsonResult;
// Assert
Assert.NotNull(result);
}
[Fact]
public void PostDataMessage()
{
var mockDocs = new Mock<IBaseRepository<Document>>();
var mockService = new Mock<IRepairService>();
mockDocs.Setup(x => x.Create(GetDoc())).Returns(GetDoc());
// Arrange
MainController controller = new MainController(mockService.Object, mockDocs.Object);
// Act
JsonResult result = controller.Post() as JsonResult;
// Assert
Assert.Equal("Work was successfully done", result?.Value);
}
[Fact]
public void UpdateDataMessage()
{
var mockDocs = new Mock<IBaseRepository<Document>>();
var mockService = new Mock<IRepairService>();
var document = GetDoc();
mockDocs.Setup(x => x.Get(document.Id)).Returns(document);
mockDocs.Setup(x => x.Update(document)).Returns(document);
// Arrange
MainController controller = new MainController(mockService.Object, mockDocs.Object);
// Act
JsonResult result = controller.Put(document) as JsonResult;
// Assert
Assert.Equal($"Update successful {document.Id}", result?.Value);
}
[Fact]
public void DeleteDataMessage()
{
var mockDocs = new Mock<IBaseRepository<Document>>();
var mockService = new Mock<IRepairService>();
var doc = GetDoc();
mockDocs.Setup(x => x.Get(doc.Id)).Returns(doc);
mockDocs.Setup(x => x.Delete(doc.Id));
// Arrange
MainController controller = new MainController(mockService.Object, mockDocs.Object);
// Act
JsonResult result = controller.Delete(doc.Id) as JsonResult;
// Assert
Assert.Equal("Delete successful", result?.Value);
}
public Document GetDoc()
{
var mockCars = new Mock<IBaseRepository<Car>>();
var mockWorkers = new Mock<IBaseRepository<Worker>>();
var carId = Guid.NewGuid();
var workerId = Guid.NewGuid();
mockCars.Setup(x => x.Create(new Car()
{
Id = carId,
Name = "car",
Number = "123"
}));
mockWorkers.Setup(x => x.Create(new Worker()
{
Id = workerId,
Name = "worker",
Position = "manager",
Telephone = "89165555555"
}));
return new Document
{
Id = Guid.NewGuid(),
CarId = carId,
WorkerId = workerId
};
}
}
В данных тестах проверяется работа каждого метода контроллера на их корректное выполнение.Тест для сервиса
public class RepairServiceTests
{
[Fact]
public void WorkSuccessTest()
{
var serviceMock = new Mock<IRepairService>();
var mockCars = new Mock<IBaseRepository<Car>>();
var mockWorkers = new Mock<IBaseRepository<Worker>>();
var mockDocs = new Mock<IBaseRepository<Document>>();
var car = CreateCar(Guid.NewGuid());
var worker = CreateWorker(Guid.NewGuid());
var doc = CreateDoc(Guid.NewGuid(), worker.Id, car.Id);
mockCars.Setup(x => x.Create(car)).Returns(car);
mockDocs.Setup(x => x.Create(doc)).Returns(doc);
mockWorkers.Setup(x => x.Create(worker)).Returns(worker);
serviceMock.Object.Work();
serviceMock.Verify(x => x.Work());
}
private Car CreateCar(Guid carId)
{
return new Car()
{
Id = carId,
Name = "car",
Number = "123"
};
}
private Worker CreateWorker(Guid workerId)
{
return new Worker()
{
Id = workerId,
Name = "worker",
Position = "manager",
Telephone = "89165555555"
};
}
private Document CreateDoc(Guid docId, Guid workerId, Guid carId)
{
return new Document
{
Id = docId,
CarId = carId,
WorkerId = workerId
};
}
}
В тесте для сервиса есть всего один тест для метода Work. Тут проверяется отработал этот метод или нет.Запуск тестовЧтобы запустить тесты достаточно зайти во вкладку «Тест» и нажать выполнить все тесты.Выкладываем в DockerВ финале я покажу, как выложить данное приложение в Docker Hub. В Visual Studio 2019 это сделать крайне просто. Учтите, что у вас уже должен быть профиль в Docker и создан репозиторий в Docker Hub.Нажимаете ПКМ на ваш проект и выбираете пункт опубликовать.Там выбираем Docker Container Registry![Клик для увеличения](https://linkme.ufanet.ru/box/200x100/07a93f6055ac903dd34b642646e88c19.jpg)
На следующем окне, надо выбрать Docker Hub![Клик для увеличения](https://linkme.ufanet.ru/box/200x100/86ba131c0e65c5366302de269afc16ee.jpg)
Далее введите свои учетные данный Docker.Если все прошло успешно, то осталось сделать последнюю вещь, нажать кнопку «Опубликовать».Готово, вы опубликовали свое приложение в Docker Hub!ЗаключениеВ данной статье я показал, как использовать возможности C# ASP.NET Core для создания простого Rest API. Показал, как создавать модели, записывать их в БД, как создать свой репозиторий, как использовать сервисы и как создавать контроллеры, которые будут отправлять JSON ответы на ваш Front. Также показал, как сделать Unit-тесты для слоев контроллеров и сервисов. И в финале показал, как выложить приложение в Docker. Надеюсь, что данная статья будет вам полезна!
===========
Источник:
habr.com
===========
Похожие новости:
- [Высокая производительность, IT-инфраструктура, IT-стандарты, Исследования и прогнозы в IT] Прогнозы на 2021 год: технологии и клиентоориентированность помогают бизнесу выйти из кризиса (перевод)
- [Видеотехника, Транспорт, Урбанизм] Face ID для оплаты проезда в московском метро заработает в следующем году
- [Высокая производительность, Анализ и проектирование систем, Серверная оптимизация, Распределённые системы] Архитектура отказоустойчивого планировщика задач. Доклад Яндекса
- [Хостинг, Управление продажами, Финансы в IT] Ценообразование услуг размещения серверов в дата-центре отличное от конкурентов
- [Big Data, Визуализация данных, Хранилища данных, Data Engineering] Как мы Data-Office создавали
- [Браузеры] Vivaldi 3.5 для Android — Аккуратная работа
- [IT-инфраструктура, Развитие стартапа, Бизнес-модели, Облачные сервисы] Cloud4Y запускает маркетплейс технологических решений и услуг
- [Разработка под Android, DevOps] Прокачиваем Android проект с GitHub Actions. Часть 1
- [Open source, GitHub, Статистика в IT] GitHub опубликовал ежегодный статистический отчет
- [Data Mining, Управление e-commerce, Здоровье] Во время пандемии COVID-19 в онлайн-магазинах снизились оценки ароматических свечей
Теги для поиска: #_.net, #_asp, #_c, #_c#, #_asp.net_core, #_rest_api, #_.net, #_asp, #_c
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 02-Июл 12:54
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 4 месяца |
|
ВведениеВсем привет, в данной статье будет рассказано, как с использованием технологии C# ASP.NET Core написать простое Rest Api. Сделать Unit-тесты на слои приложений. Отправлять Json ответы. Также покажу, как выложить данное приложение в Docker. В данной статье не будет описано, как делать клиентскую (далее Front) часть приложения. Здесь я покажу только серверную (далее Back).Что используем?Писать код я буду в Visual Studio 2019. Для реализации приложения, я буду использовать такие библиотеки NuGet:
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=testdb;Trusted_Connection=True;" },
new JsonResult(Ваш объект)
![]() Выбор шаблона приложенияДалее приступим к самому приложению.СтруктураЯ разделил все приложение по папкам (также Unit-тесты в отдельном проекте) и получил вот такую структуру мое приложения: ![]() Структура приложенияМоделиДля реализации моделей я сделал абстрактный класс BaseModel. Он понадобиться в будущем для корректного наследования, а также в нем прописан Id каждой, модели (это помогает не дублировать код): public abstract class BaseModel
{ public Guid Id { get; set; } } public class Car : BaseModel
{ public string Name { get; set; } public string Number { get; set; } } public class Document : BaseModel
{ public Guid CarId { get; set; } public Guid WorkerId { get; set; } public virtual Car Car { get; set; } public virtual Worker Worker { get; set; } } public class Worker : BaseModel
{ public string Name { get; set; } public string Position { get; set; } public string Telephone { get; set; } } public interface IBaseRepository<TDbModel> where TDbModel : BaseModel
{ public List<TDbModel> GetAll(); public TDbModel Get(Guid id); public TDbModel Create(TDbModel model); public TDbModel Update(TDbModel model); public void Delete(Guid id); } public class BaseRepository<TDbModel> : IBaseRepository<TDbModel> where TDbModel : BaseModel
{ private ApplicationContext Context { get; set; } public BaseRepository(ApplicationContext context) { Context = context; } public TDbModel Create(TDbModel model) { Context.Set<TDbModel>().Add(model); Context.SaveChanges(); return model; } public void Delete(Guid id) { var toDelete = Context.Set<TDbModel>().FirstOrDefault(m => m.Id == id); Context.Set<TDbModel>().Remove(toDelete); Context.SaveChanges(); } public List<TDbModel> GetAll() { return Context.Set<TDbModel>().ToList(); } public TDbModel Update(TDbModel model) { var toUpdate = Context.Set<TDbModel>().FirstOrDefault(m => m.Id == model.Id); if (toUpdate != null) { toUpdate = model; } Context.Update(toUpdate); Context.SaveChanges(); return toUpdate; } public TDbModel Get(Guid id) { return Context.Set<TDbModel>().FirstOrDefault(m => m.Id == id); } } public interface IRepairService
{ public void Work(); } public class RepairService : IRepairService
{ private IBaseRepository<Document> Documents { get; set; } private IBaseRepository<Car> Cars { get; set; } private IBaseRepository<Worker> Workers { get; set; } public void Work() { var rand = new Random(); var carId = Guid.NewGuid(); var workerId = Guid.NewGuid(); Cars.Create(new Car { Id = carId, Name = String.Format($"Car{rand.Next()}"), Number = String.Format($"{rand.Next()}") }); Workers.Create(new Worker { Id = workerId, Name = String.Format($"Worker{rand.Next()}"), Position = String.Format($"Position{rand.Next()}"), Telephone = String.Format($"8916{rand.Next()}{rand.Next()}{rand.Next()}{rand.Next()}{rand.Next()}{rand.Next()}{rand.Next()}") }); var car = Cars.Get(carId); var worker = Workers.Get(workerId); Documents.Create(new Document { CarId = car.Id, WorkerId = worker.Id, Car = car, Worker = worker }); } } [ApiController]
[Route("[controller]")] public class MainController : ControllerBase { private IRepairService RepairService { get; set; } private IBaseRepository<Document> Documents { get; set; } public MainController(IRepairService repairService, IBaseRepository<Document> document ) { RepairService = repairService; Documents = document; } [HttpGet] public JsonResult Get() { return new JsonResult(Documents.GetAll()); } [HttpPost] public JsonResult Post() { RepairService.Work(); return new JsonResult("Work was successfully done"); } [HttpPut] public JsonResult Put(Document doc) { bool success = true; var document = Documents.Get(doc.Id); try { if (document != null) { document = Documents.Update(doc); } else { success = false; } } catch (Exception) { success = false; } return success ? new JsonResult($"Update successful {document.Id}") : new JsonResult("Update was not successful"); } [HttpDelete] public JsonResult Delete(Guid id) { bool success = true; var document = Documents.Get(id); try { if (document != null) { Documents.Delete(document.Id); } else { success = false; } } catch (Exception) { success = false; } return success ? new JsonResult("Delete successful") : new JsonResult("Delete was not successful"); } } public class ApplicationContext: DbContext
{ public DbSet<Car> Cars { get; set; } public DbSet<Document> Documents { get; set; } public DbSet<Worker> Workers { get; set; } public ApplicationContext(DbContextOptions<ApplicationContext> options): base(options) { Database.EnsureCreated(); } } public Startup(IConfiguration configuration)
{ Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { string connection = Configuration.GetConnectionString("DefaultConnection"); services.AddMvc(); services.AddDbContext<ApplicationContext>(options => options.UseSqlServer(connection)); services.AddTransient<IRepairService, RepairService>(); services.AddTransient<IBaseRepository<Document>, BaseRepository<Document>>(); services.AddTransient<IBaseRepository<Car>, BaseRepository<Car>>(); services.AddTransient<IBaseRepository<Worker>, BaseRepository<Worker>>(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } public class MainControllerTests
{ [Fact] public void GetDataMessage() { var mockDocs = new Mock<IBaseRepository<Document>>(); var mockService = new Mock<IRepairService>(); var document = GetDoc(); mockDocs.Setup(x => x.GetAll()).Returns(new List<Document> { document }); // Arrange MainController controller = new MainController(mockService.Object, mockDocs.Object); // Act JsonResult result = controller.Get() as JsonResult; // Assert Assert.Equal(new List<Document> { document }, result?.Value); } [Fact] public void GetNotNull() { var mockDocs = new Mock<IBaseRepository<Document>>(); var mockService = new Mock<IRepairService>(); mockDocs.Setup(x => x.Create(GetDoc())).Returns(GetDoc()); // Arrange MainController controller = new MainController(mockService.Object, mockDocs.Object); // Act JsonResult result = controller.Get() as JsonResult; // Assert Assert.NotNull(result); } [Fact] public void PostDataMessage() { var mockDocs = new Mock<IBaseRepository<Document>>(); var mockService = new Mock<IRepairService>(); mockDocs.Setup(x => x.Create(GetDoc())).Returns(GetDoc()); // Arrange MainController controller = new MainController(mockService.Object, mockDocs.Object); // Act JsonResult result = controller.Post() as JsonResult; // Assert Assert.Equal("Work was successfully done", result?.Value); } [Fact] public void UpdateDataMessage() { var mockDocs = new Mock<IBaseRepository<Document>>(); var mockService = new Mock<IRepairService>(); var document = GetDoc(); mockDocs.Setup(x => x.Get(document.Id)).Returns(document); mockDocs.Setup(x => x.Update(document)).Returns(document); // Arrange MainController controller = new MainController(mockService.Object, mockDocs.Object); // Act JsonResult result = controller.Put(document) as JsonResult; // Assert Assert.Equal($"Update successful {document.Id}", result?.Value); } [Fact] public void DeleteDataMessage() { var mockDocs = new Mock<IBaseRepository<Document>>(); var mockService = new Mock<IRepairService>(); var doc = GetDoc(); mockDocs.Setup(x => x.Get(doc.Id)).Returns(doc); mockDocs.Setup(x => x.Delete(doc.Id)); // Arrange MainController controller = new MainController(mockService.Object, mockDocs.Object); // Act JsonResult result = controller.Delete(doc.Id) as JsonResult; // Assert Assert.Equal("Delete successful", result?.Value); } public Document GetDoc() { var mockCars = new Mock<IBaseRepository<Car>>(); var mockWorkers = new Mock<IBaseRepository<Worker>>(); var carId = Guid.NewGuid(); var workerId = Guid.NewGuid(); mockCars.Setup(x => x.Create(new Car() { Id = carId, Name = "car", Number = "123" })); mockWorkers.Setup(x => x.Create(new Worker() { Id = workerId, Name = "worker", Position = "manager", Telephone = "89165555555" })); return new Document { Id = Guid.NewGuid(), CarId = carId, WorkerId = workerId }; } } public class RepairServiceTests
{ [Fact] public void WorkSuccessTest() { var serviceMock = new Mock<IRepairService>(); var mockCars = new Mock<IBaseRepository<Car>>(); var mockWorkers = new Mock<IBaseRepository<Worker>>(); var mockDocs = new Mock<IBaseRepository<Document>>(); var car = CreateCar(Guid.NewGuid()); var worker = CreateWorker(Guid.NewGuid()); var doc = CreateDoc(Guid.NewGuid(), worker.Id, car.Id); mockCars.Setup(x => x.Create(car)).Returns(car); mockDocs.Setup(x => x.Create(doc)).Returns(doc); mockWorkers.Setup(x => x.Create(worker)).Returns(worker); serviceMock.Object.Work(); serviceMock.Verify(x => x.Work()); } private Car CreateCar(Guid carId) { return new Car() { Id = carId, Name = "car", Number = "123" }; } private Worker CreateWorker(Guid workerId) { return new Worker() { Id = workerId, Name = "worker", Position = "manager", Telephone = "89165555555" }; } private Document CreateDoc(Guid docId, Guid workerId, Guid carId) { return new Document { Id = docId, CarId = carId, WorkerId = workerId }; } } ![]() На следующем окне, надо выбрать Docker Hub ![]() Далее введите свои учетные данный Docker.Если все прошло успешно, то осталось сделать последнюю вещь, нажать кнопку «Опубликовать».Готово, вы опубликовали свое приложение в Docker Hub!ЗаключениеВ данной статье я показал, как использовать возможности C# ASP.NET Core для создания простого Rest API. Показал, как создавать модели, записывать их в БД, как создать свой репозиторий, как использовать сервисы и как создавать контроллеры, которые будут отправлять JSON ответы на ваш Front. Также показал, как сделать Unit-тесты для слоев контроллеров и сервисов. И в финале показал, как выложить приложение в Docker. Надеюсь, что данная статья будет вам полезна! =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 02-Июл 12:54
Часовой пояс: UTC + 5