diff --git a/API.Core/Interfaces/IGenericRepository.cs b/API.Core/Interfaces/IGenericRepository.cs index 75df90e..99dc12e 100644 --- a/API.Core/Interfaces/IGenericRepository.cs +++ b/API.Core/Interfaces/IGenericRepository.cs @@ -1,4 +1,5 @@ using API.Core.DbModels; +using API.Core.Spesicifications; using System; using System.Collections.Generic; using System.Text; @@ -11,6 +12,7 @@ public interface IGenericRepository { Task GetByIdAsync(int id); Task> ListAllAsync(); - + Task GetEntityWithSpec(ISpesification spec); + Task> ListAsync(ISpesification spec); } } diff --git a/API.Core/Spesicifications/BaseSpesification.cs b/API.Core/Spesicifications/BaseSpesification.cs index 0358774..24b4555 100644 --- a/API.Core/Spesicifications/BaseSpesification.cs +++ b/API.Core/Spesicifications/BaseSpesification.cs @@ -7,9 +7,13 @@ namespace API.Core.Spesicifications { public class BaseSpesification : ISpesification { + public BaseSpesification() + { + + } public BaseSpesification(Expression> criteria) { - Creteria = Creteria; + Creteria = criteria; } public Expression> Creteria { get; } diff --git a/API.Core/Spesicifications/ProductsWithProductTypeAndBrandSpecification.cs b/API.Core/Spesicifications/ProductsWithProductTypeAndBrandSpecification.cs new file mode 100644 index 0000000..1444b7e --- /dev/null +++ b/API.Core/Spesicifications/ProductsWithProductTypeAndBrandSpecification.cs @@ -0,0 +1,23 @@ +using API.Core.DbModels; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text; + +namespace API.Core.Spesicifications +{ + public class ProductsWithProductTypeAndBrandSpecification:BaseSpesification + { + public ProductsWithProductTypeAndBrandSpecification() + { + AddInlcude(x => x.ProductBrand); + AddInlcude(x => x.ProductType); + } + public ProductsWithProductTypeAndBrandSpecification(int id) + :base(x=>x.Id==id) + { + AddInlcude(x => x.ProductBrand); + AddInlcude(x => x.ProductType); + } + } +} diff --git a/API.Infrastructure/Data/SpesificationEveluator.cs b/API.Infrastructure/Data/SpesificationEveluator.cs new file mode 100644 index 0000000..c78b824 --- /dev/null +++ b/API.Infrastructure/Data/SpesificationEveluator.cs @@ -0,0 +1,24 @@ +using API.Core.DbModels; +using API.Core.Spesicifications; +using Microsoft.EntityFrameworkCore; +using System.Linq; + +namespace API.Infrastructure.Data +{ + public class SpesificationEveluator + where TEntiy:BaseEntity + { + public static IQueryable GetQuery(IQueryable inputQuery,ISpesification spec) + { + var query = inputQuery; + + if (spec.Creteria !=null) + { + query = query.Where(spec.Creteria); + } + + query = spec.Includes.Aggregate(query, (current, include) => current.Include(include)); + return query; + } + } +} diff --git "a/API.Infrastructure/\304\260mplements/GenericRepository.cs" "b/API.Infrastructure/\304\260mplements/GenericRepository.cs" index 1242d06..e30369f 100644 --- "a/API.Infrastructure/\304\260mplements/GenericRepository.cs" +++ "b/API.Infrastructure/\304\260mplements/GenericRepository.cs" @@ -1,9 +1,12 @@ using API.Core.DbModels; using API.Core.Interfaces; +using API.Core.Spesicifications; +using API.Infrastructure.Data; using API.Infrastructure.DataContext; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; +using System.Linq; using System.Text; using System.Threading.Tasks; @@ -21,9 +24,23 @@ public async Task GetByIdAsync(int id) return await _ctx.Set().FindAsync(id); } - public async Task> ListAllAsync() + public async Task> ListAllAsync() { return await _ctx.Set().ToListAsync(); } + public async Task GetEntityWithSpec(ISpesification spec) + { + return await ApplySpesification(spec).FirstOrDefaultAsync(); + } + + public async Task> ListAsync(ISpesification spec) + { + return await ApplySpesification(spec).ToListAsync(); + } + + private IQueryable ApplySpesification(ISpesification spec) + { + return SpesificationEveluator.GetQuery(_ctx.Set().AsQueryable(), spec); + } } } diff --git a/API/API.csproj b/API/API.csproj index 2b8773c..b3a3d75 100644 --- a/API/API.csproj +++ b/API/API.csproj @@ -5,11 +5,13 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/API/Controllers/ProductsController.cs b/API/Controllers/ProductsController.cs index 41afc8e..803ceec 100644 --- a/API/Controllers/ProductsController.cs +++ b/API/Controllers/ProductsController.cs @@ -5,6 +5,10 @@ using System.Collections.Generic; using System.Threading.Tasks; using API.Core.Interfaces; +using API.Core.Spesicifications; +using API.Dtos; +using System.Linq; +using AutoMapper; namespace API.Controllers { @@ -15,25 +19,34 @@ public class ProductsController : ControllerBase private readonly IGenericRepository _productRepo; private readonly IGenericRepository _brandRepo; private readonly IGenericRepository _typeRepo; + private readonly IMapper _mapper; - public ProductsController(IGenericRepository productRepo,IGenericRepository brandRepo,IGenericRepository typeRepo) + public ProductsController(IGenericRepository productRepo, + IGenericRepository brandRepo,IGenericRepository typeRepo,IMapper mapper) { _productRepo = productRepo; _brandRepo = brandRepo; _typeRepo = typeRepo; + _mapper = mapper; } [HttpGet] - public async Task>> GetProducts() + public async Task>> GetProducts() { - var data = await _productRepo.ListAllAsync(); - return Ok(data); - + var spec = new ProductsWithProductTypeAndBrandSpecification(); + var data = await _productRepo.ListAsync(spec); + // return Ok(data); + return Ok(_mapper.Map, IReadOnlyList>(data)); } [HttpGet("{id}")] - public async Task> GetProduct(int id) + public async Task> GetProduct(int id) { - return await _productRepo.GetByIdAsync(id); + var spec = new ProductsWithProductTypeAndBrandSpecification(id); + + //return await _productRepo.GetEntityWithSpec(spec); + + var product = await _productRepo.GetEntityWithSpec(spec); + return _mapper.Map(product); } [HttpGet("brands")] public async Task>> GetProductBrands() @@ -45,5 +58,6 @@ public async Task>> GetProductTypes() { return Ok(await _typeRepo.ListAllAsync()); } + } } diff --git a/API/Dtos/ProductToReturnDto.cs b/API/Dtos/ProductToReturnDto.cs new file mode 100644 index 0000000..5328f12 --- /dev/null +++ b/API/Dtos/ProductToReturnDto.cs @@ -0,0 +1,14 @@ +namespace API.Dtos +{ + public class ProductToReturnDto + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public decimal? Price { get; set; } + public string PictureUrl { get; set; } + public string ProductType { get; set; } + public string ProductBrand { get; set; } + + } +} diff --git a/API/Helpers/MappingProfiles.cs b/API/Helpers/MappingProfiles.cs new file mode 100644 index 0000000..8caf7b5 --- /dev/null +++ b/API/Helpers/MappingProfiles.cs @@ -0,0 +1,17 @@ +using API.Core.DbModels; +using API.Dtos; +using AutoMapper; + +namespace API.Helpers +{ + public class MappingProfiles : Profile + { + public MappingProfiles() + { + CreateMap() + .ForMember(x => x.ProductBrand, o => o.MapFrom(s => s.ProductBrand.Name)) + .ForMember(x => x.ProductType, o => o.MapFrom(s => s.ProductType.Name)) + .ForMember(x=>x.PictureUrl,o=>o.MapFrom()); + } + } +} diff --git a/API/Helpers/ProductUrlResolver.cs b/API/Helpers/ProductUrlResolver.cs new file mode 100644 index 0000000..4d9377a --- /dev/null +++ b/API/Helpers/ProductUrlResolver.cs @@ -0,0 +1,29 @@ +using API.Core.DbModels; +using API.Dtos; +using AutoMapper; +using AutoMapper.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace API.Helpers +{ + public class ProductUrlResolver : IValueResolver + { + private readonly Microsoft.Extensions.Configuration.IConfiguration _config; + + public ProductUrlResolver(Microsoft.Extensions.Configuration.IConfiguration config) + { + _config = config; + } + public string Resolve(Product source, ProductToReturnDto destination, string destMember, ResolutionContext context) + { + if (!string.IsNullOrEmpty(source.PictureUrl)) + { + return _config["ApiUrl"] + source.PictureUrl; + } + return null; + } + } +} diff --git a/API/Startup.cs b/API/Startup.cs index 4b4c64b..4653ba1 100644 --- a/API/Startup.cs +++ b/API/Startup.cs @@ -1,5 +1,6 @@ using API.Core.Interfaces; +using API.Helpers; using API.Infrastructure.DataContext; using API.Infrastructure.Ýmplements; using Microsoft.AspNetCore.Builder; @@ -25,7 +26,8 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { services.AddScoped(); - services.AddScoped(typeof(IGenericRepository<>),(typeof(GenericRepository<>))); + services.AddScoped(typeof(IGenericRepository<>),(typeof(GenericRepository<>))); + services.AddAutoMapper(typeof(MappingProfiles)); services.AddControllers(); services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); //services.AddSwaggerGen(c => diff --git a/API/appsettings.json b/API/appsettings.json index d9b77b5..f764b86 100644 --- a/API/appsettings.json +++ b/API/appsettings.json @@ -10,5 +10,6 @@ "AllowedHosts": "*", "ConnectionStrings": { "DefaultConnection": "Server = DESKTOP-NKKGRR6;DataBase = StoreDataBase;Trusted_Connection=True;MultipleActiveResultSets=True" - } + }, + "ApiUrl": "https://localhost:44322/" }