So erstellen Sie eine einfache Rest-API in .NET Core

Einführung

Hallo allerseits, in diesem Artikel erfahren Sie, wie Sie eine einfache Rest-API mit der C # ASP.NET Core-Technologie schreiben. Machen Sie Unit-Tests für Anwendungsebenen. Senden Sie Json-Antworten. Ich werde Ihnen auch zeigen, wie Sie diese Anwendung in Docker bereitstellen.





In diesem Artikel wird nicht beschrieben, wie der Client (im Folgenden "Front") Teil der Anwendung wird. Hier zeige ich nur den Serverraum (im Folgenden Zurück).





Was benutzen wir?

Ich werde den Code in Visual Studio 2019 schreiben.





Um die Anwendung zu implementieren, werde ich die folgenden NuGet-Bibliotheken verwenden:





  1. Microsoft.EntityFrameworkCore





  2. Microsoft.EntityFrameworkCore.SqlServer





  3. Microsoft.EntityFrameworkCore.Tools





Für Tests sind diese Bibliotheken:





  1. Microsoft.NET.Test.Sdk





  2. Microsoft.NETCore.App





  3. Moq





  4. xunit





  5. xunit.runner.visualstudio





Um Pakete zu installieren, müssen Sie zum NuGet-Paketbrowser gehen. Klicken Sie dazu mit der rechten Maustaste auf das Projekt und wählen Sie dort den Punkt "NuGet-Pakete verwalten" aus.





Was programmieren?

Als Beispiel nehme ich ein stark vereinfachtes Modell eines Autoreparaturdienstes. In meinem Modell gibt es Arbeiter, die die Reparaturen durchführen, Autos, die zur Reparatur kommen, und die Reparaturdokumentation, die zurückgeschickt wird.





Datenbankkonfiguration

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.





Auswählen einer Anwendungsvorlage

.





( Unit- ) :





Anwendungsstruktur

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!





In diesem Artikel habe ich Ihnen gezeigt, wie Sie die Leistung von ASP.NET Core C # zum Erstellen einer einfachen Rest-API nutzen können. Ich habe Ihnen gezeigt, wie Sie Modelle erstellen, in die Datenbank schreiben, wie Sie Ihr eigenes Repository erstellen, wie Sie Dienste verwenden und wie Sie Controller erstellen, die JSON-Antworten an Ihre Front senden. Er zeigte auch, wie Unit-Tests für die Controller- und Service-Schichten durchgeführt werden. Am Ende zeigte er, wie eine Anwendung in Docker bereitgestellt wird.





Ich hoffe, Sie finden diesen Artikel hilfreich!








All Articles