المقدمة
مرحبًا بالجميع ، ستخبرك هذه المقالة بكيفية كتابة Rest Api بسيط باستخدام تقنية C # ASP.NET Core. قم بإجراء اختبارات الوحدة لطبقات التطبيق. إرسال ردود Json. سأوضح لك أيضًا كيفية نشر هذا التطبيق في Docker.
لن تصف هذه المقالة كيفية جعل العميل (المشار إليه فيما يلي باسم Front) جزءًا من التطبيق. سأعرض هنا غرفة الخادم فقط (يشار إليها فيما بعد بالعودة).
ماذا نستعمل؟
سأكتب الكود في Visual Studio 2019.
لتنفيذ التطبيق ، سأستخدم مكتبات NuGet التالية:
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore. الأدوات
للاختبارات ، هذه المكتبات هي:
Microsoft.NET.Test.Sdk
Microsoft.NETCore.App
موك
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.

.
( 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!
في هذه المقالة ، أوضحت لك كيفية استخدام ميزات C # ASP.NET Core لإنشاء Rest API بسيط. لقد أوضح كيفية إنشاء النماذج ، وكتابتها في قاعدة البيانات ، وكيفية إنشاء مستودعك الخاص ، وكيفية استخدام الخدمات ، وكيفية إنشاء وحدات تحكم ترسل ردود JSON إلى Front الخاص بك. كما أوضح كيفية إجراء اختبارات الوحدة لوحدات التحكم وطبقات الخدمة. وفي النهاية ، أوضح كيفية نشر تطبيق في Docker.
آمل أن تجد هذه المقالة مفيدة!