"> WEB API در ASP.NETCore | آموزش .NET Cor | ام اس پی سافت

WEB API در ASP.NETCore

WEB API در ASP.NETCore ، ما در این مقاله می خواهیم با استفاده از asp.net core 1x و Entityframework یک web api ایجاد کنیم.

برای دسترسی به اطلاعات سازمان دهی شده، امروزه یک Platform و یا Restful Api استفاده می شود که یکی از راه حل هایی است که برای دسترسی به اطلاعات از آن استفاده می شود.

مهارت هایی که نیاز دارید بلد باشید برای فهمیدن این مقاله:

  • c#
  • ORM
  • RESTful services

نرم افزارهایی که شما نیاز دارید:

  • Visual Studio 2015 with Update 3
  •  AdventureWorks database download

لینک دانلود نرم افزار AdventureWorks در بالا قرار داده شده است.

در مرحله ی اول باید یک پروژه ی خام ایجاد نمایید و از گزینه ی File > New > Project > Visual C# – Web > ASP.NET Core Web Application (.NET Core).

یک پروژه جدید ایجاد نمایید به صورت زیر:

WEB API در ASP.NETCore

WEB API در ASP.NETCore

نام پروژه را مانند تصویر بالا AdventureWorksAPI بنویسید و بعد OK را بزنید.

WEB API در ASP.NETCore

WEB API در ASP.NETCore

در مرحله ی بعد همان طور که در تصویر بالا می بینید گزینه ی WEB API را انتخاب نمایید و تیک Host In The Cloud را برمیدارید و یک پروژه ی جدید بدون هیچ احراز هویتی ایجاد نمایید زمانی که برای اولین بار پروژه تون اجرا می شود به صورت زیر است:

WEB API در ASP.NETCore

WEB API در ASP.NETCore

علاوه بر این رشته ی connection را باید در فایل appsettings.json اضافه کنید به صورت زیر:

WEB API در ASP.NETCore

WEB API در ASP.NETCore

افزودن api مربوط پروژه

ما نیاز داریم که بسته های Entity Framework را به پروژه خودمان اضافه کنیم فایل Project.json را باز کنید و مانند تصویر زیر خط ۷ و ۸ را اضافه کنید:

WEB API در ASP.NETCore

WEB API در ASP.NETCore

اگر همه چیز خوب است و هیچ اروری نداشتید و برنامه را Build کردید حالا نیاز است که یک مسیر پروژه ایجاد نمایید.

مسیر های زیر را برای پروژه ی خود ایجاد نمایید:

Extentions: یک مسیر برای Extentions های پروژه قرار دهید.
Model: یک پوشه برای دیتابیس و ایجاد ارتباط با برنامه ی خودتان ایجاد نمایید.
Response: برای شی هایی که درخواست های http را پاسخ می دهند.
ViewModels: برای شی هایی که خروجی http را نشان می دهد.

حال باید یک Controller جدید در مسیر دایرکتوری Controller ایجاد کنید مانند تصویر زیر:

WEB API در ASP.NETCore

WEB API در ASP.NETCore

 

کد داخل controller به صورت زیر است:


using System;
using System.Linq;
using System.Threading.Tasks;
using AdventureWorksAPI.Core.DataLayer;
using AdventureWorksAPI.Core.EntityLayer;
using AdventureWorksAPI.Responses;
using AdventureWorksAPI.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace AdventureWorksAPI.Controllers
{
    [Route("api/[controller]")]
    public class ProductionController : Controller
    {
        private IAdventureWorksRepository AdventureWorksRepository;

        public ProductionController(IAdventureWorksRepository repository)
        {
            AdventureWorksRepository = repository;
        }

        protected override void Dispose(Boolean disposing)
        {
            AdventureWorksRepository?.Dispose();

            base.Dispose(disposing);
        }

        // GET Production/Product
        /// 

















<summary>
        /// Retrieves a list of products
        /// </summary>


















        /// <param name="pageSize">Page size</param>
        /// <param name="pageNumber">Page number</param>
        /// <param name="name">Name</param>
        /// <returns>List response</returns>
        [HttpGet]
        [Route("Product")]
        public async Task<IActionResult> GetProductsAsync(Int32? pageSize = 10, Int32? pageNumber = 1, String name = null)
        {
            var response = new ListModelResponse<ProductViewModel>();

            try
            {
                response.PageSize = (Int32)pageSize;
                response.PageNumber = (Int32)pageNumber;

                response.Model = await AdventureWorksRepository
                        .GetProducts(response.PageSize, response.PageNumber, name)
                        .Select(item => item.ToViewModel())
                        .ToListAsync();

                response.Message = String.Format("Total of records: {0}", response.Model.Count());
            }
            catch (Exception ex)
            {
                response.DidError = true;
                response.ErrorMessage = ex.Message;
            }

            return response.ToHttpResponse();
        }

        // GET Production/Product/5
        /// 

















<summary>
        /// Retrieves a specific product by id
        /// </summary>


















        /// <param name="id">Product ID</param>
        /// <returns>Single response</returns>
        [HttpGet]
        [Route("Product/{id}")]
        public async Task<IActionResult> GetProductAsync(Int32 id)
        {
            var response = new SingleModelResponse<ProductViewModel>();

            try
            {
                var entity = await AdventureWorksRepository.GetProductAsync(new Product { ProductID = id });

                response.Model = entity?.ToViewModel();
            }
            catch (Exception ex)
            {
                response.DidError = true;
                response.ErrorMessage = ex.Message;
            }

            return response.ToHttpResponse();
        }

        // POST Production/Product/
        /// 

















<summary>
        /// Creates a new product on Production catalog
        /// </summary>


















        /// <param name="request">Product entry</param>
        /// <returns>Single response</returns>
        [HttpPost]
        [Route("Product")]
        public async Task<IActionResult> PostProductAsync([FromBody]ProductViewModel request)
        {
            var response = new SingleModelResponse<ProductViewModel>();

            try
            {
                var entity = await AdventureWorksRepository.AddProductAsync(request.ToEntity());

                response.Model = entity?.ToViewModel();
                response.Message = "The data was saved successfully";
            }
            catch (Exception ex)
            {
                response.DidError = true;
                response.ErrorMessage = ex.ToString();
            }

            return response.ToHttpResponse();
        }

        // PUT Production/Product/5
        /// 

















<summary>
        /// Updates an existing product
        /// </summary>


















        /// <param name="id">Product ID</param>
        /// <param name="request">Product entry</param>
        /// <returns>Single response</returns>
        [HttpPut]
        [Route("Product/{id}")]
        public async Task<IActionResult> PutProductAsync(Int32 id, [FromBody]ProductViewModel request)
        {
            var response = new SingleModelResponse<ProductViewModel>();

            try
            {
                var entity = await AdventureWorksRepository.UpdateProductAsync(request.ToEntity());

                response.Model = entity?.ToViewModel();
                response.Message = "The record was updated successfully";
            }
            catch (Exception ex)
            {
                response.DidError = true;
                response.ErrorMessage = ex.Message;
            }

            return response.ToHttpResponse();
        }

        // DELETE Production/Product/5
        /// 

















<summary>
        /// Delete an existing product
        /// </summary>


















        /// <param name="id">Product ID</param>
        /// <returns>Single response</returns>
        [HttpDelete]
        [Route("Product/{id}")]
        public async Task<IActionResult> DeleteProductAsync(Int32 id)
        {
            var response = new SingleModelResponse<ProductViewModel>();

            try
            {
                var entity = await AdventureWorksRepository.DeleteProductAsync(new Product { ProductID = id });

                response.Model = entity?.ToViewModel();
                response.Message = "The record was deleted successfully";
            }
            catch (Exception ex)
            {
                response.DidError = true;
                response.ErrorMessage = ex.Message;
            }

            return response.ToHttpResponse();
        }
    }
}

برای اجرای برنامه ما به کد های زیاد نیاز داریم.

ما باید تمام موجودیت ها و Namespace های مورد نیاز مان در کلاس خود را تعریف کنیم با استفاده از یک کلاس بزرگ می توانیم کلاس های دیگری را هم تعریف کنیم.

داخل دایرکتوری مدل باید فایل های زیر را داشته باشیم:

  • AdventureWorksDbContext.cs: دسترسی به پایگاه داده با استفاده از entity framework
  • AdventureWorksDbContext.cs:پیاده سازی Repository
  • AppSettings.cs: نوع appsettings
  • IAdventureWorksRepository.cs:Interface ها
  • Products: کلاس product
  • ProductMap:map کلاس Product

همه آن‌ها بخشی از فضای نامی هستند ، چون آن‌ها نشان‌دهنده اتصال پایگاه‌داده در API هستند.

کد interface در IAdventureWorksRepository


using System;
using System.Linq;
using System.Threading.Tasks;
using AdventureWorksAPI.Core.EntityLayer;

namespace AdventureWorksAPI.Core.DataLayer
{
    public interface IAdventureWorksRepository : IDisposable
    {
        IQueryable<Product> GetProducts(Int32 pageSize, Int32 pageNumber, String name);

        Task<Product> GetProductAsync(Product entity);

        Task<Product> AddProductAsync(Product entity);

        Task<Product> UpdateProductAsync(Product changes);

        Task<Product> DeleteProductAsync(Product changes);
    }
}

کد کلاس AdventureWorksRepository


using System;
using System.Linq;
using System.Threading.Tasks;
using AdventureWorksAPI.Core.EntityLayer;
using Microsoft.EntityFrameworkCore;

namespace AdventureWorksAPI.Core.DataLayer
{
    public class AdventureWorksRepository : IAdventureWorksRepository
    {
        private readonly AdventureWorksDbContext DbContext;
        private Boolean Disposed;

        public AdventureWorksRepository(AdventureWorksDbContext dbContext)
        {
            DbContext = dbContext;
        }

        public void Dispose()
        {
            if (!Disposed)
            {
                DbContext?.Dispose();

                Disposed = true;
            }
        }

        public IQueryable<Product> GetProducts(Int32 pageSize, Int32 pageNumber, String name)
        {
            var query = DbContext.Set<Product>().Skip((pageNumber - 1) * pageSize).Take(pageSize);

            if (!String.IsNullOrEmpty(name))
            {
                query = query.Where(item => item.Name.ToLower().Contains(name.ToLower()));
            }

            return query;
        }

        public Task<Product> GetProductAsync(Product entity)
        {
            return DbContext.Set<Product>().FirstOrDefaultAsync(item => item.ProductID == entity.ProductID);
        }

        public async Task<Product> AddProductAsync(Product entity)
        {
            entity.MakeFlag = false;
            entity.FinishedGoodsFlag = false;
            entity.SafetyStockLevel = 1;
            entity.ReorderPoint = 1;
            entity.StandardCost = 0.0m;
            entity.ListPrice = 0.0m;
            entity.DaysToManufacture = 0;
            entity.SellStartDate = DateTime.Now;
            entity.rowguid = Guid.NewGuid();
            entity.ModifiedDate = DateTime.Now;

            DbContext.Set<Product>().Add(entity);

            await DbContext.SaveChangesAsync();

            return entity;
        }

        public async Task<Product> UpdateProductAsync(Product changes)
        {
            var entity = await GetProductAsync(changes);

            if (entity != null)
            {
                entity.Name = changes.Name;
                entity.ProductNumber = changes.ProductNumber;

                await DbContext.SaveChangesAsync();
            }

            return entity;
        }

        public async Task<Product> DeleteProductAsync(Product changes)
        {
            var entity = await GetProductAsync(changes);

            if (entity != null)
            {
                DbContext.Set<Product>().Remove(entity);

                await DbContext.SaveChangesAsync();
            }

            return entity;
        }
    }
}

کد کلاس AdventureWorksDbContext


using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;

namespace AdventureWorksAPI.Models
{
    public class AdventureWorksDbContext : Microsoft.EntityFrameworkCore.DbContext
    {
        public AdventureWorksDbContext(IOptions<AppSettings> appSettings)
        {
            ConnectionString = appSettings.Value.ConnectionString;
        }

        public String ConnectionString { get; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(ConnectionString);
            
            base.OnConfiguring(optionsBuilder);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.MapProduct();

            base.OnModelCreating(modelBuilder);
        }
    }
}

کد کلاس appsetting


using System;

namespace AdventureWorksAPI.Models
{
    public class AppSettings
    {
        public String ConnectionString { get; set; }
    }
}

کد کلاس Product

using System;

namespace AdventureWorksAPI.Models
{
    public class Product
    {
        public Int32? ProductID { get; set; }

        public String Name { get; set; }

        public String ProductNumber { get; set; }

        public Boolean? MakeFlag { get; set; }

        public Boolean? FinishedGoodsFlag { get; set; }

        public Int16? SafetyStockLevel { get; set; }

        public Int16? ReorderPoint { get; set; }

        public Decimal? StandardCost { get; set; }

        public Decimal? ListPrice { get; set; }

        public Int32? DaysToManufacture { get; set; }

        public DateTime? SellStartDate { get; set; }

        public Guid? rowguid { get; set; }

        public DateTime? ModifiedDate { get; set; }
    }
}

کد کلاس ProductMap

using Microsoft.EntityFrameworkCore;

namespace AdventureWorksAPI.Models
{
    public static class ProductMap
    {
        public static ModelBuilder MapProduct(this ModelBuilder modelBuilder)
        {
            var entity = modelBuilder.Entity<Product>();

            entity.ToTable("Product", "Production");

            entity.HasKey(p => new { p.ProductID });

            entity.Property(p => p.ProductID).UseSqlServerIdentityColumn();

            return modelBuilder;
        }
    }
}

همان طور که میبیند ما کلاس های مختلف برای هر جدول داریم که به صورت زیر است:

Poco:نمایش هر جدولی به عنوان یک شی CLR
Mapping:تنظیم یک شی poco داخل DbContext
Mapper:برای تطبیق مقدار ها با شی های تعریف شده

یک سوال پیش می آید که اگر ما ۲۰۰ جدول داشته باشیم پس نیاز داریم ۲۰۰ تا کلاس کد داشته باشیم .

پاسخ بله است گزینه های زیادی برای حل این مشکل وجود دارد یکی از ان ها تولید کد است.

در هر صورت ما نیاز داریم که یک شی تعریف کنیم.

داخل دایرکتوری Extentions فایل های زیر را داریم:

  • ProductViewModelMapper: یک Extentions برای کلاس POCO
  • ResponseExtensions:متدهایی برای ایجاد درخواست های http

کد کلاس ProductViewModelMapper

using AdventureWorksAPI.Models;
using AdventureWorksAPI.ViewModels;

namespace AdventureWorksAPI.Extensions
{
    public static class ProductViewModelMapper
    {
        public static ProductViewModel ToViewModel(this Product entity)
        {
            return new ProductViewModel
            {
                ProductID = entity.ProductID,
                ProductName = entity.Name,
                ProductNumber = entity.ProductNumber
            };
        }
        
        public static Product ToEntity(this ProductViewModel viewModel)
        {
            return new Product
            {
                Name = viewModel.ProductName,
                ProductNumber = viewModel.ProductNumber
            };
        }
    }
}

چرا باید از mapper استفاده کنیم؟

ما می توانیم با توجه به اولویت های خودمان mapper را تغییر دهیم.
می توانید از یک متد mapper داینامیک استفاده کنید:

کد کلاس ResponseExtensions

using System;
using System.Net;
using Microsoft.AspNetCore.Mvc;

namespace AdventureWorksAPI.Responses
{
    public static class ResponseExtensions
    {
        public static IActionResult ToHttpResponse<TModel>(this IListModelResponse<TModel> response)
        {
            var status = HttpStatusCode.OK;

            if (response.DidError)
            {
                status = HttpStatusCode.InternalServerError;
            }
            else if (response.Model == null)
            {
                status = HttpStatusCode.NoContent;
            }

            return new ObjectResult(response)
            {
                StatusCode = (Int32)status
            };
        }

        public static IActionResult ToHttpResponse<TModel>(this ISingleModelResponse<TModel> response)
        {
            var status = HttpStatusCode.OK;

            if (response.DidError)
            {
                status = HttpStatusCode.InternalServerError;
            }
            else if (response.Model == null)
            {
                status = HttpStatusCode.NotFound;
            }

            return new ObjectResult(response)
            {
                StatusCode = (Int32)status
            };
        }
    }
}

داخل دایرکتوری response ها باید فایل های زیر را داشته باشیم:

  • IListModelResponse.cs :یک interface برای نمایش لیست responde ها.
  • IResponse.cs:یک interface عمومی برای پاسخ response ها.
  • ISingleModelResponse.cs:interface برای نمایش یک پاسخ واحد.
  • ListModelResponse.cs:اجرای لیست response ها.
  • ListModelResponse.cs:پیاده سازی response های تک.

کد interface به نام ListModelResponse.cs به صورت زیر است:

using System;
using System.Collections.Generic;

namespace AdventureWorksAPI.Responses
{
    public interface IListModelResponse<TModel> : IResponse
    {
        Int32 PageSize { get; set; }

        Int32 PageNumber { get; set; }
        
        IEnumerable<TModel> Model { get; set; }
    }
}

کد interface به نام IResponse به صورت زیر است:

Hide   Copy Code
using System;

namespace AdventureWorksAPI.Responses
{
    public interface IResponse
    {
        String Message { get; set; }

        Boolean DidError { get; set; }

        String ErrorMessage { get; set; }
    }
}

کد interface به نام ISingleModelResponse به صورت زیر است:

namespace AdventureWorksAPI.Responses
{
    public interface ISingleModelResponse<TModel> : IResponse
    {
        TModel Model { get; set; }
    }
}

کد کلاس ListModelResponse

using System;
using System.Collections.Generic;

namespace AdventureWorksAPI.Responses
{
    public class ListModelResponse<TModel> : IListModelResponse<TModel>
    {
        public String Message { get; set; }

        public Boolean DidError { get; set; }

        public String ErrorMessage { get; set; }
        
        public Int32 PageSize { get; set; }

        public Int32 PageNumber { get; set; }

        public IEnumerable<TModel> Model { get; set; }
    }
}

کد کلاس SingleModelResponse

using System;

namespace AdventureWorksAPI.Responses
{
    public class SingleModelResponse<TModel> : ISingleModelResponse<TModel>
    {
        public String Message { get; set; }

        public Boolean DidError { get; set; }

        public String ErrorMessage { get; set; }

        public TModel Model { get; set; }
    }
}

داخل دایرکتوری ViewModels، فایل‌های زیر را داریم:

  • ProductViewModelr : نمایش مدل برای نمایش اطلاعات درباره محصولات.

کد کلاس ProductViewModel

using System;

namespace AdventureWorksAPI.ViewModels
{
    public class ProductViewModel
    {
        public Int32? ProductID { get; set; }

        public String ProductName { get; set; }

        public String ProductNumber { get; set; }
    }
}

View Model تنها ویژگی هایی را شامل می شود که می خواهیم برای client تعریف کنیم در این حالت ما همه مقادیر پیش فرض را برای موجودیت محصول داخل repository مدیریت می کنیم.

یکی از تغییرات اصلی asp.net core تزریق وابستگی است که ما نیاز داریم بسته های زیر را اضافه کنیم.

ما نیاز داریم که تمام سرویس ها را در کلاس startup اضافه کنیم در متد ConfigureServices ما تمام وابستگی ها را اضافه می کنیم و باید تمام وابستگی ها را به controller ها اضافه نماییم.

using AdventureWorksAPI.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Serialization;

namespace AdventureWorksAPI
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddMvc().AddJsonOptions
            (a => a.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());

            services.AddEntityFrameworkSqlServer().AddDbContext<AdventureWorksDbContext>();

            services.AddScoped<IAdventureWorksRepository, AdventureWorksRepository>();

            services.AddOptions();

            services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

            services.AddSingleton<IConfiguration>(Configuration);
        }

        // This method gets called by the runtime. 
        // Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
                              ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            app.UseMvc();
        }
    }
}

 

قبل از اینکه کد را انتشار دهید باید آن را تست نمایید یکی از آزمون هایی که کد را تست می کنند که مشکلی نداشته باشد استفاده از TDD است که متدی است برای آزمون و تست کد های ما.

ASP.NET Core شامل تغییرات زیادی است، در مورد آزمایش، یک خط فرمان برای اجرای آزمون‌های واحد وجود دارد، ما باید کد فعلی را برای افزودن تست‌های واحد تغییر دهیم.

ساختار پروژه باید به صورت زیر باشد:

WEB API در ASP.NETCore

WEB API در ASP.NETCore

 

روی فولدر solution’s name > Open Command Line > Default (cmd) راست کلیک کنید و یک پوشه ی mkdir test درست نمایید.

یک پوشه ای به نام cd test ایجاد کنید.

یک مسیری به نام “AdventureWorksAPI.Tests” ایجاد کنید.

وارد این AdventureWorksAPI.Tests شوید.

یک پروژه تست ایجاد نمایید.

یک پوشه ی solution تست برای خود ایجاد می کنید.

حال باید فایل test را حذف کنید و یک کلاس به نام ProductionControllerTest.cs ایجاد کنید.

کد برای کلاس RepositoryMocker

using AdventureWorksAPI.Core.DataLayer;
using Microsoft.Extensions.Options;

namespace AdventureWorksAPI.Tests
{
    public static class RepositoryMocker
    {
        public static IAdventureWorksRepository GetAdventureWorksRepository()
        {
            var appSettings = Options.Create(new AppSettings
            {
                ConnectionString = "server=(local);database=AdventureWorks2012;integrated security=yes;"
            });

            return new AdventureWorksRepository(new AdventureWorksDbContext(appSettings, new AdventureWorksEntityMapper()));
        }
    }
}

کد کلاس ProductionControllerTest

using System;
using System.Threading.Tasks;
using AdventureWorksAPI.Controllers;
using AdventureWorksAPI.Responses;
using AdventureWorksAPI.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Xunit;

namespace AdventureWorksAPI.Tests
{
    public class ProductionControllerTest
    {
        [Fact]
        public async Task TestGetProductsAsync()
        {
            // Arrange
            var repository = RepositoryMocker.GetAdventureWorksRepository();
            var controller = new ProductionController(repository);

            // Act
            var response = await controller.GetProductsAsync() as ObjectResult;
            var value = response.Value as IListModelResponse<ProductViewModel>;

            controller.Dispose();

            // Assert
            Assert.False(value.DidError);
        }

        [Fact]
        public async Task TestGetProductAsync()
        {
            // Arrange
            var repository = RepositoryMocker.GetAdventureWorksRepository();
            var controller = new ProductionController(repository);
            var id = 1;

            // Act
            var response = await controller.GetProductAsync(id) as ObjectResult;
            var value = response.Value as ISingleModelResponse<ProductViewModel>;

            repository.Dispose();

            // Assert
            Assert.False(value.DidError);
        }

        [Fact]
        public async Task TestGetNonExistingProductAsync()
        {
            // Arrange
            var repository = RepositoryMocker.GetAdventureWorksRepository();
            var controller = new ProductionController(repository);
            var id = 0;

            // Act
            var response = await controller.GetProductAsync(id) as ObjectResult;
            var value = response.Value as ISingleModelResponse<ProductViewModel>;

            repository.Dispose();

            // Assert
            Assert.False(value.DidError);
        }

        [Fact]
        public async Task TestPostProductAsync()
        {
            // Arrange
            var repository = RepositoryMocker.GetAdventureWorksRepository();
            var controller = new ProductionController(repository);
            var request = new ProductViewModel
            {
                ProductName = String.Format("New test product {0}{1}{2}", DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond),
                ProductNumber = String.Format("{0}{1}{2}", DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond)
            };

            // Act
            var response = await controller.PostProductAsync(request) as ObjectResult;
            var value = response.Value as ISingleModelResponse<ProductViewModel>;

            repository.Dispose();

            // Assert
            Assert.False(value.DidError);
        }

        [Fact]
        public async Task TestPutProductAsync()
        {
            // Arrange
            var repository = RepositoryMocker.GetAdventureWorksRepository();
            var controller = new ProductionController(repository);
            var id = 1;
            var request = new ProductViewModel
            {
                ProductID = id,
                ProductName = "New product test II",
                ProductNumber = "XYZ"
            };

            // Act
            var response = await controller.PutProductAsync(id, request) as ObjectResult;
            var value = response.Value as ISingleModelResponse<ProductViewModel>;

            repository.Dispose();

            // Assert
            Assert.False(value.DidError);
        }

        [Fact]
        public async Task TestDeleteProductAsync()
        {
            // Arrange
            var repository = RepositoryMocker.GetAdventureWorksRepository();
            var controller = new ProductionController(repository);
            var id = 1000;

            // Act
            var response = await controller.DeleteProductAsync(id) as ObjectResult;
            var value = response.Value as ISingleModelResponse<ProductViewModel>;

            repository.Dispose();

            // Assert
            Assert.False(value.DidError);
        }
    }
}

همان طور که تا کنون دیدید، ما می‌توانیم تست‌های واحد را برای پروژه API Web اضافه کنیم، هم اکنون می‌توانیم تست‌های واحد را از خط فرمان اجرا کنیم، یک پنجره خط فرمان باز کنیم و دایرکتوری را تغییر دهیم: تست dotnet، ما یک خروجی مثل این پیدا خواهیم دید:

WEB API در ASP.NETCore

WEB API در ASP.NETCore

IIS از پورت شماره ۳۸۱۲۶ استفاده می کند ما می توانیم داخل کلاس ProductionController صفات مربوط به Route را تغییر دهیم.

api/Production/Product/ به صورت زیر است :

WEB API در ASP.NETCore

WEB API در ASP.NETCore

لیست بالا شماره صفحه و پارامترهای داخل صفحه را نمایش می دهد.

WEB API در ASP.NETCore

خروجی api/Production/Product/4

WEB API در ASP.NETCore

WEB API در ASP.NETCore

 

اگر شما نمی توانید فایل json را ببنید یک افزونه در مرورگر کروم JSON Chrome وجود دارد.

می توانید با ابزار های postman هم ببینید.

لینک دانلود :download.

ما موضوعات زیادی را در پروژه اضافه کرده ایم شما می توانید برای اینکه اشیا از هم جدا باشد روی پروژه کلیک راست کنید و یک پروژه ی جدید از asp.net core ایجاد نمایید:

شما باید برای این پروژه ی جدید مانند تصویر زیر:

  • DataLayer
  •  EntityLayer

ایجاد کنید.

WEB API در ASP.NETCore

WEB API در ASP.NETCore

شما می توانید یک چالش برای خودتان ایجاد کنید یک پروژه ی جدید دیگر اضافه نمایید و مانند تمام مراحل بالا  پیش ببرید و داخل solution خودتان آن را ذخیره کنید اگر در build کردن به خطا نخوردید پروژه را پیش ببرید.

نکته های مقاله ی  WEB API در ASP.NETCore 1x

  1.  Entity framework به صورت Entity Framework core است
  2. چرا ما به نوع بازگشتی ها نیاز داریم ؟ما باید نوع داده هایی که در پاسخ یک درخواست بر می گردند دقت کنیم این کمک می کند که اگر جایی سرور خطایی داشت آن را به ما نشان دهد
  3. چرا ما باید از viewModels استفاده کنیم ؟ فرض کنید که ما ۱۰۰ تا جدول داریم که می خواهیم اطلاعات مشتری را نمایش دهیم به هر حال ما نیاز به یک ساختاری داریم که بتوانیم تمام اطلاعات مشتری را مانند تلفن ایمیل و .. داشته باشیم.
  • پسورد: www.mspsoft.com
زهره سلطانیان

نوشته‌های مرتبط

دیدگاه‌ها

*
*

این سایت از اکیسمت برای کاهش هرزنامه استفاده می کند. بیاموزید که چگونه اطلاعات دیدگاه های شما پردازش می‌شوند.