pengantar
Halo semuanya, artikel ini akan memberi tahu Anda cara menulis Rest Api sederhana menggunakan teknologi C # ASP.NET Core. Buat tes Unit untuk lapisan aplikasi. Kirim tanggapan Json. Saya juga akan menunjukkan kepada Anda cara menerapkan aplikasi ini di Docker.
Artikel ini tidak akan menjelaskan cara menjadikan klien (selanjutnya disebut Depan) sebagai bagian dari aplikasi. Di sini saya hanya akan menampilkan ruang server (selanjutnya disebut Kembali).
Apa yang kami gunakan?
Saya akan menulis kode di Visual Studio 2019.
Untuk mengimplementasikan aplikasi, saya akan menggunakan pustaka NuGet berikut:
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Untuk pengujian, pustaka ini adalah:
Microsoft.NET.Test.Sdk
Microsoft.NETCore.App
Moq
xunit
xunit.runner.visualstudio
Untuk menginstal paket, Anda perlu pergi ke browser paket NuGet, Anda dapat melakukannya dengan mengklik kanan pada proyek, dan memilih di sana item "kelola paket NuGet"
Apa Program?
Sebagai contoh, saya akan mengambil model layanan perbaikan mobil yang sangat disederhanakan. Model saya akan memiliki pekerja yang akan melakukan perbaikan, mobil yang datang untuk diperbaiki, dan dokumentasi perbaikan yang akan dikirim kembali.
Konfigurasi Basis Data
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.

.
( 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
});
}
}
, . , 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 Context
ApplicationContext – , 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

, Docker Hub

Docker.
, , «».
, Docker Hub!
Pada artikel ini, saya menunjukkan kepada Anda cara menggunakan kekuatan ASP.NET Core C # untuk membuat Rest API sederhana. Menunjukkan cara membuat model, menulisnya ke database, cara membuat repositori Anda sendiri, cara menggunakan layanan dan cara membuat pengontrol yang akan mengirim tanggapan JSON ke Front Anda. Dia juga menunjukkan bagaimana membuat tes Unit untuk controller dan service layer. Dan pada akhirnya, dia menunjukkan bagaimana cara men-deploy aplikasi di Docker.
Semoga artikel ini bermanfaat bagi Anda!