feat(MetaTags) , feat(ProductCategoryMetaTags) , VER 1.6.18.28

subProduct
Amir Hossein Khademi 2024-10-25 14:36:19 +03:30
parent d17422d646
commit 82f9d604da
25 changed files with 2852 additions and 177 deletions

View File

@ -1 +1 @@
1.5.18.27 1.6.18.28

View File

@ -0,0 +1,17 @@
namespace Netina.Api.Controllers;
public class CustomerController : ICarterModule
{
public void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("Customer").MapGroup("api/customer")
.RequireAuthorization(builder=>builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetCustomersAsync)
.WithDisplayName("Get Customers")
.HasApiVersion(1.0);
}
private async Task<IResult> GetCustomersAsync([FromQuery] int page, [FromQuery] int? count, [FromServices] IMediator mediator, CancellationToken cancellationToken)
=> TypedResults.Ok(true);
}

View File

@ -6,8 +6,8 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization> <InvariantGlobalization>true</InvariantGlobalization>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<AssemblyVersion>1.5.18.27</AssemblyVersion> <AssemblyVersion>1.6.18.28</AssemblyVersion>
<FileVersion>1.5.18.27</FileVersion> <FileVersion>1.6.18.28</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <!--<PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
@ -12,9 +12,9 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" />
</ItemGroup> </ItemGroup>-->
<!--<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<LangVersion>10</LangVersion> <LangVersion>10</LangVersion>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
@ -25,7 +25,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" />
</ItemGroup>--> </ItemGroup>
<ItemGroup> <ItemGroup>
<Using Include="MD.PersianDateTime.Standard" /> <Using Include="MD.PersianDateTime.Standard" />

View File

@ -1,11 +1,8 @@
using System.IO.Compression; using System.IO.Compression;
using System.Net; using System.Net;
using System.Web;
using System.Xml; using System.Xml;
using Netina.Core.Models; using Netina.Core.Models;
using Netina.Domain.Entities.Brands;
using Netina.Domain.Entities.ProductCategories; using Netina.Domain.Entities.ProductCategories;
using Netina.Domain.Entities.Products;
namespace Netina.Core.BaseServices; namespace Netina.Core.BaseServices;
@ -14,8 +11,7 @@ public class SiteMapService(
IOptionsSnapshot<SiteSettings> snapshot, IOptionsSnapshot<SiteSettings> snapshot,
IUploadFileService uploadFileService, IUploadFileService uploadFileService,
IRepositoryWrapper repositoryWrapper, IRepositoryWrapper repositoryWrapper,
IPageService pageService) IPageService pageService) : ISiteMapService
: ISiteMapService
{ {
private readonly SiteSettings _siteSetting = snapshot.Value; private readonly SiteSettings _siteSetting = snapshot.Value;

View File

@ -0,0 +1,3 @@
namespace Netina.Domain.CommandQueries.Queries;
public record GetCustomersQuery(int Page = 0, int Count = Refers.SizeM) : IRequest<List<CustomerSDto>>;

View File

@ -10,4 +10,5 @@ public class ProductCategoryLDto : BaseDto<ProductCategoryLDto, ProductCategory>
public bool IsMain { get; set; } public bool IsMain { get; set; }
public List<ProductCategorySDto> Children { get; set; } = new(); public List<ProductCategorySDto> Children { get; set; } = new();
public List<StorageFileSDto> Files { get; internal set; } = new(); public List<StorageFileSDto> Files { get; internal set; } = new();
public List<MetaTagSDto> MetaTags { get; set; } = new();
} }

View File

@ -9,10 +9,19 @@ public class GetProductsResponseDto
public PagerResponseDto Pager { get; set; } = new PagerResponseDto(); public PagerResponseDto Pager { get; set; } = new PagerResponseDto();
public FilterResponseDto Filters { get; set; } = new FilterResponseDto(); public FilterResponseDto Filters { get; set; } = new FilterResponseDto();
public SeoResponseDto Seo { get; set; } = new SeoResponseDto();
} }
public class FilterResponseDto public class FilterResponseDto
{ {
public PriceFilterDto Price { get; set; } = new PriceFilterDto(); public PriceFilterDto Price { get; set; } = new PriceFilterDto();
public ExpressDeliveryFilter ExpressDelivery { get; set; } = new ExpressDeliveryFilter(); public ExpressDeliveryFilter ExpressDelivery { get; set; } = new ExpressDeliveryFilter();
}
public class SeoResponseDto
{
public string Description { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public Dictionary<string, string> MetaTags { get; set; } = new();
} }

View File

@ -0,0 +1,7 @@
namespace Netina.Domain.Dtos.SmallDtos;
public class MetaTagSDto : BaseDto<MetaTagSDto, MetaTag>
{
public string Type { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty;
}

View File

@ -19,8 +19,16 @@ public partial class ProductCategory
Files.Add(file); Files.Add(file);
return file; return file;
} }
public void AddMetaTag(string key, string value)
=> MetaTags.Add(ProductCategoryMetaTag.Create(key, value, Id));
} }
public partial class ProductCategoryMetaTag
{
public static ProductCategoryMetaTag Create(string key, string value, Guid productCategoryId)
=> new ProductCategoryMetaTag(key, value, productCategoryId);
}
public partial class ProductCategoryStorageFile public partial class ProductCategoryStorageFile
{ {
public static ProductCategoryStorageFile Create(string name, string fileLocation, string fileName, bool isHeader, bool isPrimary, StorageFileType fileType, Guid categoryId) public static ProductCategoryStorageFile Create(string name, string fileLocation, string fileName, bool isHeader, bool isPrimary, StorageFileType fileType, Guid categoryId)

View File

@ -27,6 +27,7 @@ public partial class ProductCategory : ApiEntity
public ProductCategory? Parent { get; internal set; } public ProductCategory? Parent { get; internal set; }
//public List<ProductCategory> Children { get; internal set; } = new(); //public List<ProductCategory> Children { get; internal set; } = new();
public List<ProductCategoryMetaTag> MetaTags { get; internal set; } = new();
public List<Product> Products { get; internal set; } = new(); public List<Product> Products { get; internal set; } = new();
public List<ProductCategoryStorageFile> Files { get; internal set; } = new(); public List<ProductCategoryStorageFile> Files { get; internal set; } = new();
} }

View File

@ -0,0 +1,16 @@
namespace Netina.Domain.Entities.ProductCategories;
public partial class ProductCategoryMetaTag : MetaTag
{
public ProductCategoryMetaTag()
{
}
public ProductCategoryMetaTag(string type, string value, Guid productCategoryId) : base(type, value)
{
ProductCategoryId = productCategoryId;
}
public Guid ProductCategoryId { get; set; }
public ProductCategory? ProductCategory { get; set; }
}

View File

@ -0,0 +1,27 @@
namespace Netina.Domain.Entities.Seo;
[AdaptTwoWays("[name]LDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget | MapType.Projection)]
[AdaptTwoWays("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget)]
[AdaptTo("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Projection)]
[GenerateMapper]
public partial class MetaTag : ApiEntity
{
public MetaTag()
{
}
public MetaTag(string type, string value)
{
Type = type;
Value = value;
}
public string Type { get; internal set; } = string.Empty;
public string Value { get; internal set; } = string.Empty;
}
public partial class MetaTag
{
public static MetaTag Create(string type, string value)
=> new(type, value);
}

View File

@ -0,0 +1,68 @@
using System;
using System.Linq.Expressions;
using Netina.Domain.Dtos.SmallDtos;
using Netina.Domain.Entities.Seo;
namespace Netina.Domain.Mappers
{
public static partial class MetaTagMapper
{
public static MetaTag AdaptToMetaTag(this MetaTagSDto p1)
{
return p1 == null ? null : new MetaTag()
{
Type = p1.Type,
Value = p1.Value,
Id = p1.Id,
CreatedAt = p1.CreatedAt
};
}
public static MetaTag AdaptTo(this MetaTagSDto p2, MetaTag p3)
{
if (p2 == null)
{
return null;
}
MetaTag result = p3 ?? new MetaTag();
result.Type = p2.Type;
result.Value = p2.Value;
result.Id = p2.Id;
result.CreatedAt = p2.CreatedAt;
return result;
}
public static MetaTagSDto AdaptToSDto(this MetaTag p4)
{
return p4 == null ? null : new MetaTagSDto()
{
Type = p4.Type,
Value = p4.Value,
Id = p4.Id,
CreatedAt = p4.CreatedAt
};
}
public static MetaTagSDto AdaptTo(this MetaTag p5, MetaTagSDto p6)
{
if (p5 == null)
{
return null;
}
MetaTagSDto result = p6 ?? new MetaTagSDto();
result.Type = p5.Type;
result.Value = p5.Value;
result.Id = p5.Id;
result.CreatedAt = p5.CreatedAt;
return result;
}
public static Expression<Func<MetaTag, MetaTagSDto>> ProjectToSDto => p7 => new MetaTagSDto()
{
Type = p7.Type,
Value = p7.Value,
Id = p7.Id,
CreatedAt = p7.CreatedAt
};
}
}

View File

@ -25,212 +25,257 @@ namespace Netina.Domain.Mappers
Name = p1.ParentName, Name = p1.ParentName,
Id = p1.ParentId Id = p1.ParentId
}, },
Files = funcMain1(p1.Files), MetaTags = funcMain1(p1.MetaTags),
Files = funcMain2(p1.Files),
Id = p1.Id, Id = p1.Id,
CreatedAt = p1.CreatedAt CreatedAt = p1.CreatedAt
}; };
} }
public static ProductCategory AdaptTo(this ProductCategoryLDto p3, ProductCategory p4) public static ProductCategory AdaptTo(this ProductCategoryLDto p4, ProductCategory p5)
{ {
if (p3 == null) if (p4 == null)
{ {
return null; return null;
} }
ProductCategory result = p4 ?? new ProductCategory(); ProductCategory result = p5 ?? new ProductCategory();
result.Name = p3.Name; result.Name = p4.Name;
result.Slug = p3.Slug; result.Slug = p4.Slug;
result.Description = p3.Description; result.Description = p4.Description;
result.IsMain = p3.IsMain; result.IsMain = p4.IsMain;
result.ParentId = (Guid?)p3.ParentId; result.ParentId = (Guid?)p4.ParentId;
result.Parent = funcMain2(new Never(), result.Parent, p3); result.Parent = funcMain3(new Never(), result.Parent, p4);
result.Files = funcMain3(p3.Files, result.Files); result.MetaTags = funcMain4(p4.MetaTags, result.MetaTags);
result.Id = p3.Id; result.Files = funcMain5(p4.Files, result.Files);
result.CreatedAt = p3.CreatedAt; result.Id = p4.Id;
result.CreatedAt = p4.CreatedAt;
return result; return result;
} }
public static Expression<Func<ProductCategoryLDto, ProductCategory>> ProjectToProductCategory => p9 => new ProductCategory() public static Expression<Func<ProductCategoryLDto, ProductCategory>> ProjectToProductCategory => p12 => new ProductCategory()
{ {
Name = p9.Name, Name = p12.Name,
Slug = p9.Slug, Slug = p12.Slug,
Description = p9.Description, Description = p12.Description,
IsMain = p9.IsMain, IsMain = p12.IsMain,
ParentId = (Guid?)p9.ParentId, ParentId = (Guid?)p12.ParentId,
Parent = new ProductCategory() Parent = new ProductCategory()
{ {
Name = p9.ParentName, Name = p12.ParentName,
Id = p9.ParentId Id = p12.ParentId
}, },
Files = p9.Files.Select<StorageFileSDto, ProductCategoryStorageFile>(p10 => new ProductCategoryStorageFile() MetaTags = p12.MetaTags.Select<MetaTagSDto, ProductCategoryMetaTag>(p13 => new ProductCategoryMetaTag()
{ {
Name = p10.Name, Type = p13.Type,
FileLocation = p10.FileLocation, Value = p13.Value,
FileName = p10.FileName, Id = p13.Id,
IsHeader = p10.IsHeader, CreatedAt = p13.CreatedAt
IsPrimary = p10.IsPrimary, }).ToList<ProductCategoryMetaTag>(),
FileType = p10.FileType, Files = p12.Files.Select<StorageFileSDto, ProductCategoryStorageFile>(p14 => new ProductCategoryStorageFile()
Id = p10.Id, {
CreatedAt = p10.CreatedAt Name = p14.Name,
FileLocation = p14.FileLocation,
FileName = p14.FileName,
IsHeader = p14.IsHeader,
IsPrimary = p14.IsPrimary,
FileType = p14.FileType,
Id = p14.Id,
CreatedAt = p14.CreatedAt
}).ToList<ProductCategoryStorageFile>(), }).ToList<ProductCategoryStorageFile>(),
Id = p9.Id, Id = p12.Id,
CreatedAt = p9.CreatedAt CreatedAt = p12.CreatedAt
}; };
public static ProductCategoryLDto AdaptToLDto(this ProductCategory p11) public static ProductCategoryLDto AdaptToLDto(this ProductCategory p15)
{ {
return p11 == null ? null : new ProductCategoryLDto() return p15 == null ? null : new ProductCategoryLDto()
{ {
Name = p11.Name, Name = p15.Name,
Description = p11.Description, Description = p15.Description,
ParentId = p11.ParentId == null ? default(Guid) : (Guid)p11.ParentId, ParentId = p15.ParentId == null ? default(Guid) : (Guid)p15.ParentId,
ParentName = p11.Parent != null ? p11.Parent.Name : string.Empty, ParentName = p15.Parent != null ? p15.Parent.Name : string.Empty,
Slug = p11.Slug, Slug = p15.Slug,
IsMain = p11.IsMain, IsMain = p15.IsMain,
Files = funcMain4(p11.Files), Files = funcMain6(p15.Files),
Id = p11.Id, MetaTags = funcMain7(p15.MetaTags),
CreatedAt = p11.CreatedAt Id = p15.Id,
CreatedAt = p15.CreatedAt
}; };
} }
public static ProductCategoryLDto AdaptTo(this ProductCategory p13, ProductCategoryLDto p14) public static ProductCategoryLDto AdaptTo(this ProductCategory p18, ProductCategoryLDto p19)
{ {
if (p13 == null) if (p18 == null)
{ {
return null; return null;
} }
ProductCategoryLDto result = p14 ?? new ProductCategoryLDto(); ProductCategoryLDto result = p19 ?? new ProductCategoryLDto();
result.Name = p13.Name; result.Name = p18.Name;
result.Description = p13.Description; result.Description = p18.Description;
result.ParentId = p13.ParentId == null ? default(Guid) : (Guid)p13.ParentId; result.ParentId = p18.ParentId == null ? default(Guid) : (Guid)p18.ParentId;
result.ParentName = p13.Parent != null ? p13.Parent.Name : string.Empty; result.ParentName = p18.Parent != null ? p18.Parent.Name : string.Empty;
result.Slug = p13.Slug; result.Slug = p18.Slug;
result.IsMain = p13.IsMain; result.IsMain = p18.IsMain;
result.Files = funcMain5(p13.Files, result.Files); result.Files = funcMain8(p18.Files, result.Files);
result.Id = p13.Id; result.MetaTags = funcMain9(p18.MetaTags, result.MetaTags);
result.CreatedAt = p13.CreatedAt; result.Id = p18.Id;
result.CreatedAt = p18.CreatedAt;
return result; return result;
} }
public static Expression<Func<ProductCategory, ProductCategoryLDto>> ProjectToLDto => p17 => new ProductCategoryLDto() public static Expression<Func<ProductCategory, ProductCategoryLDto>> ProjectToLDto => p24 => new ProductCategoryLDto()
{ {
Name = p17.Name, Name = p24.Name,
Description = p17.Description, Description = p24.Description,
ParentId = p17.ParentId == null ? default(Guid) : (Guid)p17.ParentId, ParentId = p24.ParentId == null ? default(Guid) : (Guid)p24.ParentId,
ParentName = p17.Parent != null ? p17.Parent.Name : string.Empty, ParentName = p24.Parent != null ? p24.Parent.Name : string.Empty,
Slug = p17.Slug, Slug = p24.Slug,
IsMain = p17.IsMain, IsMain = p24.IsMain,
Files = p17.Files.Select<ProductCategoryStorageFile, StorageFileSDto>(p18 => new StorageFileSDto() Files = p24.Files.Select<ProductCategoryStorageFile, StorageFileSDto>(p25 => new StorageFileSDto()
{ {
Name = p18.Name, Name = p25.Name,
FileLocation = p18.FileLocation, FileLocation = p25.FileLocation,
FileName = p18.FileName, FileName = p25.FileName,
IsHeader = p18.IsHeader, IsHeader = p25.IsHeader,
IsPrimary = p18.IsPrimary, IsPrimary = p25.IsPrimary,
FileType = p18.FileType, FileType = p25.FileType,
Id = p18.Id Id = p25.Id
}).ToList<StorageFileSDto>(), }).ToList<StorageFileSDto>(),
Id = p17.Id, MetaTags = p24.MetaTags.Select<ProductCategoryMetaTag, MetaTagSDto>(p26 => new MetaTagSDto()
CreatedAt = p17.CreatedAt
};
public static ProductCategory AdaptToProductCategory(this ProductCategorySDto p19)
{
return p19 == null ? null : new ProductCategory()
{ {
Name = p19.Name, Type = p26.Type,
Slug = p19.Slug, Value = p26.Value,
Description = p19.Description, Id = p26.Id,
IsMain = p19.IsMain, CreatedAt = p26.CreatedAt
ParentId = (Guid?)p19.ParentId, }).ToList<MetaTagSDto>(),
Id = p24.Id,
CreatedAt = p24.CreatedAt
};
public static ProductCategory AdaptToProductCategory(this ProductCategorySDto p27)
{
return p27 == null ? null : new ProductCategory()
{
Name = p27.Name,
Slug = p27.Slug,
Description = p27.Description,
IsMain = p27.IsMain,
ParentId = (Guid?)p27.ParentId,
Parent = new ProductCategory() Parent = new ProductCategory()
{ {
Name = p19.ParentName, Name = p27.ParentName,
Id = p19.ParentId Id = p27.ParentId
}, },
Id = p19.Id, Id = p27.Id,
CreatedAt = p19.CreatedAt CreatedAt = p27.CreatedAt
}; };
} }
public static ProductCategory AdaptTo(this ProductCategorySDto p20, ProductCategory p21) public static ProductCategory AdaptTo(this ProductCategorySDto p28, ProductCategory p29)
{ {
if (p20 == null) if (p28 == null)
{ {
return null; return null;
} }
ProductCategory result = p21 ?? new ProductCategory(); ProductCategory result = p29 ?? new ProductCategory();
result.Name = p20.Name; result.Name = p28.Name;
result.Slug = p20.Slug; result.Slug = p28.Slug;
result.Description = p20.Description; result.Description = p28.Description;
result.IsMain = p20.IsMain; result.IsMain = p28.IsMain;
result.ParentId = (Guid?)p20.ParentId; result.ParentId = (Guid?)p28.ParentId;
result.Parent = funcMain6(new Never(), result.Parent, p20); result.Parent = funcMain10(new Never(), result.Parent, p28);
result.Id = p20.Id; result.Id = p28.Id;
result.CreatedAt = p20.CreatedAt; result.CreatedAt = p28.CreatedAt;
return result; return result;
} }
public static ProductCategorySDto AdaptToSDto(this ProductCategory p24) public static ProductCategorySDto AdaptToSDto(this ProductCategory p32)
{ {
return p24 == null ? null : new ProductCategorySDto() return p32 == null ? null : new ProductCategorySDto()
{ {
Name = p24.Name, Name = p32.Name,
Description = p24.Description, Description = p32.Description,
Slug = p24.Slug, Slug = p32.Slug,
IsMain = p24.IsMain, IsMain = p32.IsMain,
ParentId = p24.ParentId == null ? default(Guid) : (Guid)p24.ParentId, ParentId = p32.ParentId == null ? default(Guid) : (Guid)p32.ParentId,
ParentName = p24.Parent != null ? p24.Parent.Name : string.Empty, ParentName = p32.Parent != null ? p32.Parent.Name : string.Empty,
MainImage = p24.Files.FirstOrDefault<ProductCategoryStorageFile>(funcMain7) != null ? p24.Files.FirstOrDefault<ProductCategoryStorageFile>(funcMain8).FileLocation : (p24.Files.Count > 0 ? p24.Files.FirstOrDefault<ProductCategoryStorageFile>().FileLocation : string.Empty), MainImage = p32.Files.FirstOrDefault<ProductCategoryStorageFile>(funcMain11) != null ? p32.Files.FirstOrDefault<ProductCategoryStorageFile>(funcMain12).FileLocation : (p32.Files.Count > 0 ? p32.Files.FirstOrDefault<ProductCategoryStorageFile>().FileLocation : string.Empty),
Id = p24.Id, Id = p32.Id,
CreatedAt = p24.CreatedAt CreatedAt = p32.CreatedAt
}; };
} }
public static ProductCategorySDto AdaptTo(this ProductCategory p25, ProductCategorySDto p26) public static ProductCategorySDto AdaptTo(this ProductCategory p33, ProductCategorySDto p34)
{ {
if (p25 == null) if (p33 == null)
{ {
return null; return null;
} }
ProductCategorySDto result = p26 ?? new ProductCategorySDto(); ProductCategorySDto result = p34 ?? new ProductCategorySDto();
result.Name = p25.Name; result.Name = p33.Name;
result.Description = p25.Description; result.Description = p33.Description;
result.Slug = p25.Slug; result.Slug = p33.Slug;
result.IsMain = p25.IsMain; result.IsMain = p33.IsMain;
result.ParentId = p25.ParentId == null ? default(Guid) : (Guid)p25.ParentId; result.ParentId = p33.ParentId == null ? default(Guid) : (Guid)p33.ParentId;
result.ParentName = p25.Parent != null ? p25.Parent.Name : string.Empty; result.ParentName = p33.Parent != null ? p33.Parent.Name : string.Empty;
result.MainImage = p25.Files.FirstOrDefault<ProductCategoryStorageFile>(funcMain7) != null ? p25.Files.FirstOrDefault<ProductCategoryStorageFile>(funcMain8).FileLocation : (p25.Files.Count > 0 ? p25.Files.FirstOrDefault<ProductCategoryStorageFile>().FileLocation : string.Empty); result.MainImage = p33.Files.FirstOrDefault<ProductCategoryStorageFile>(funcMain11) != null ? p33.Files.FirstOrDefault<ProductCategoryStorageFile>(funcMain12).FileLocation : (p33.Files.Count > 0 ? p33.Files.FirstOrDefault<ProductCategoryStorageFile>().FileLocation : string.Empty);
result.Id = p25.Id; result.Id = p33.Id;
result.CreatedAt = p25.CreatedAt; result.CreatedAt = p33.CreatedAt;
return result; return result;
} }
public static Expression<Func<ProductCategory, ProductCategorySDto>> ProjectToSDto => p27 => new ProductCategorySDto() public static Expression<Func<ProductCategory, ProductCategorySDto>> ProjectToSDto => p35 => new ProductCategorySDto()
{ {
Name = p27.Name, Name = p35.Name,
Description = p27.Description, Description = p35.Description,
Slug = p27.Slug, Slug = p35.Slug,
IsMain = p27.IsMain, IsMain = p35.IsMain,
ParentId = p27.ParentId == null ? default(Guid) : (Guid)p27.ParentId, ParentId = p35.ParentId == null ? default(Guid) : (Guid)p35.ParentId,
ParentName = p27.Parent != null ? p27.Parent.Name : string.Empty, ParentName = p35.Parent != null ? p35.Parent.Name : string.Empty,
MainImage = p27.Files.FirstOrDefault<ProductCategoryStorageFile>(f => f.IsPrimary) != null ? p27.Files.FirstOrDefault<ProductCategoryStorageFile>(f => f.IsPrimary).FileLocation : (p27.Files.Count > 0 ? p27.Files.FirstOrDefault<ProductCategoryStorageFile>().FileLocation : string.Empty), MainImage = p35.Files.FirstOrDefault<ProductCategoryStorageFile>(f => f.IsPrimary) != null ? p35.Files.FirstOrDefault<ProductCategoryStorageFile>(f => f.IsPrimary).FileLocation : (p35.Files.Count > 0 ? p35.Files.FirstOrDefault<ProductCategoryStorageFile>().FileLocation : string.Empty),
Id = p27.Id, Id = p35.Id,
CreatedAt = p27.CreatedAt CreatedAt = p35.CreatedAt
}; };
private static List<ProductCategoryStorageFile> funcMain1(List<StorageFileSDto> p2) private static List<ProductCategoryMetaTag> funcMain1(List<MetaTagSDto> p2)
{ {
if (p2 == null) if (p2 == null)
{ {
return null; return null;
} }
List<ProductCategoryStorageFile> result = new List<ProductCategoryStorageFile>(p2.Count); List<ProductCategoryMetaTag> result = new List<ProductCategoryMetaTag>(p2.Count);
int i = 0; int i = 0;
int len = p2.Count; int len = p2.Count;
while (i < len) while (i < len)
{ {
StorageFileSDto item = p2[i]; MetaTagSDto item = p2[i];
result.Add(item == null ? null : new ProductCategoryMetaTag()
{
Type = item.Type,
Value = item.Value,
Id = item.Id,
CreatedAt = item.CreatedAt
});
i++;
}
return result;
}
private static List<ProductCategoryStorageFile> funcMain2(List<StorageFileSDto> p3)
{
if (p3 == null)
{
return null;
}
List<ProductCategoryStorageFile> result = new List<ProductCategoryStorageFile>(p3.Count);
int i = 0;
int len = p3.Count;
while (i < len)
{
StorageFileSDto item = p3[i];
result.Add(item == null ? null : new ProductCategoryStorageFile() result.Add(item == null ? null : new ProductCategoryStorageFile()
{ {
Name = item.Name, Name = item.Name,
@ -248,30 +293,57 @@ namespace Netina.Domain.Mappers
} }
private static ProductCategory funcMain2(Never p5, ProductCategory p6, ProductCategoryLDto p3) private static ProductCategory funcMain3(Never p6, ProductCategory p7, ProductCategoryLDto p4)
{ {
ProductCategory result = p6 ?? new ProductCategory(); ProductCategory result = p7 ?? new ProductCategory();
result.Name = p3.ParentName; result.Name = p4.ParentName;
result.Id = p3.ParentId; result.Id = p4.ParentId;
return result; return result;
} }
private static List<ProductCategoryStorageFile> funcMain3(List<StorageFileSDto> p7, List<ProductCategoryStorageFile> p8) private static List<ProductCategoryMetaTag> funcMain4(List<MetaTagSDto> p8, List<ProductCategoryMetaTag> p9)
{ {
if (p7 == null) if (p8 == null)
{ {
return null; return null;
} }
List<ProductCategoryStorageFile> result = new List<ProductCategoryStorageFile>(p7.Count); List<ProductCategoryMetaTag> result = new List<ProductCategoryMetaTag>(p8.Count);
int i = 0; int i = 0;
int len = p7.Count; int len = p8.Count;
while (i < len) while (i < len)
{ {
StorageFileSDto item = p7[i]; MetaTagSDto item = p8[i];
result.Add(item == null ? null : new ProductCategoryMetaTag()
{
Type = item.Type,
Value = item.Value,
Id = item.Id,
CreatedAt = item.CreatedAt
});
i++;
}
return result;
}
private static List<ProductCategoryStorageFile> funcMain5(List<StorageFileSDto> p10, List<ProductCategoryStorageFile> p11)
{
if (p10 == null)
{
return null;
}
List<ProductCategoryStorageFile> result = new List<ProductCategoryStorageFile>(p10.Count);
int i = 0;
int len = p10.Count;
while (i < len)
{
StorageFileSDto item = p10[i];
result.Add(item == null ? null : new ProductCategoryStorageFile() result.Add(item == null ? null : new ProductCategoryStorageFile()
{ {
Name = item.Name, Name = item.Name,
@ -289,20 +361,20 @@ namespace Netina.Domain.Mappers
} }
private static List<StorageFileSDto> funcMain4(List<ProductCategoryStorageFile> p12) private static List<StorageFileSDto> funcMain6(List<ProductCategoryStorageFile> p16)
{ {
if (p12 == null) if (p16 == null)
{ {
return null; return null;
} }
List<StorageFileSDto> result = new List<StorageFileSDto>(p12.Count); List<StorageFileSDto> result = new List<StorageFileSDto>(p16.Count);
int i = 0; int i = 0;
int len = p12.Count; int len = p16.Count;
while (i < len) while (i < len)
{ {
ProductCategoryStorageFile item = p12[i]; ProductCategoryStorageFile item = p16[i];
result.Add(item == null ? null : new StorageFileSDto() result.Add(item == null ? null : new StorageFileSDto()
{ {
Name = item.Name, Name = item.Name,
@ -319,20 +391,47 @@ namespace Netina.Domain.Mappers
} }
private static List<StorageFileSDto> funcMain5(List<ProductCategoryStorageFile> p15, List<StorageFileSDto> p16) private static List<MetaTagSDto> funcMain7(List<ProductCategoryMetaTag> p17)
{ {
if (p15 == null) if (p17 == null)
{ {
return null; return null;
} }
List<StorageFileSDto> result = new List<StorageFileSDto>(p15.Count); List<MetaTagSDto> result = new List<MetaTagSDto>(p17.Count);
int i = 0; int i = 0;
int len = p15.Count; int len = p17.Count;
while (i < len) while (i < len)
{ {
ProductCategoryStorageFile item = p15[i]; ProductCategoryMetaTag item = p17[i];
result.Add(item == null ? null : new MetaTagSDto()
{
Type = item.Type,
Value = item.Value,
Id = item.Id,
CreatedAt = item.CreatedAt
});
i++;
}
return result;
}
private static List<StorageFileSDto> funcMain8(List<ProductCategoryStorageFile> p20, List<StorageFileSDto> p21)
{
if (p20 == null)
{
return null;
}
List<StorageFileSDto> result = new List<StorageFileSDto>(p20.Count);
int i = 0;
int len = p20.Count;
while (i < len)
{
ProductCategoryStorageFile item = p20[i];
result.Add(item == null ? null : new StorageFileSDto() result.Add(item == null ? null : new StorageFileSDto()
{ {
Name = item.Name, Name = item.Name,
@ -349,22 +448,49 @@ namespace Netina.Domain.Mappers
} }
private static ProductCategory funcMain6(Never p22, ProductCategory p23, ProductCategorySDto p20) private static List<MetaTagSDto> funcMain9(List<ProductCategoryMetaTag> p22, List<MetaTagSDto> p23)
{ {
ProductCategory result = p23 ?? new ProductCategory(); if (p22 == null)
{
return null;
}
List<MetaTagSDto> result = new List<MetaTagSDto>(p22.Count);
result.Name = p20.ParentName; int i = 0;
result.Id = p20.ParentId; int len = p22.Count;
while (i < len)
{
ProductCategoryMetaTag item = p22[i];
result.Add(item == null ? null : new MetaTagSDto()
{
Type = item.Type,
Value = item.Value,
Id = item.Id,
CreatedAt = item.CreatedAt
});
i++;
}
return result; return result;
} }
private static bool funcMain7(ProductCategoryStorageFile f) private static ProductCategory funcMain10(Never p30, ProductCategory p31, ProductCategorySDto p28)
{
ProductCategory result = p31 ?? new ProductCategory();
result.Name = p28.ParentName;
result.Id = p28.ParentId;
return result;
}
private static bool funcMain11(ProductCategoryStorageFile f)
{ {
return f.IsPrimary; return f.IsPrimary;
} }
private static bool funcMain8(ProductCategoryStorageFile f) private static bool funcMain12(ProductCategoryStorageFile f)
{ {
return f.IsPrimary; return f.IsPrimary;
} }

View File

@ -0,0 +1,6 @@
namespace Netina.Domain.Mappers
{
public static partial class ProductCategoryMetaTagMapper
{
}
}

View File

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <!--<PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
@ -15,9 +15,9 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.8" />
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="8.0.8" /> <PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="8.0.8" />
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" /> <PackageReference Include="PropertyChanged.Fody" Version="4.1.0" />
</ItemGroup> </ItemGroup>-->
<!--<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<LangVersion>10</LangVersion> <LangVersion>10</LangVersion>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
@ -33,7 +33,7 @@
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="5.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0" />
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" /> <PackageReference Include="PropertyChanged.Fody" Version="4.1.0" />
</ItemGroup>--> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -76,6 +76,7 @@
<Using Include="Netina.Domain.Entities.Orders" /> <Using Include="Netina.Domain.Entities.Orders" />
<Using Include="Netina.Domain.Entities.ProductCategories" /> <Using Include="Netina.Domain.Entities.ProductCategories" />
<Using Include="Netina.Domain.Entities.Products" /> <Using Include="Netina.Domain.Entities.Products" />
<Using Include="Netina.Domain.Entities.Seo" />
<Using Include="Netina.Domain.Entities.StorageFiles" /> <Using Include="Netina.Domain.Entities.StorageFiles" />
<Using Include="Netina.Domain.Entities.Users" /> <Using Include="Netina.Domain.Entities.Users" />
<Using Include="Netina.Domain.Entities.Warehouses" /> <Using Include="Netina.Domain.Entities.Warehouses" />

View File

@ -0,0 +1,16 @@
namespace Netina.Repository.Handlers.Customers;
public class GetCustomersQueryHandler(IRepositoryWrapper repositoryWrapper) : IRequestHandler<GetCustomersQuery,List<CustomerSDto>>
{
public async Task<List<CustomerSDto>> Handle(GetCustomersQuery request, CancellationToken cancellationToken)
{
var response = await repositoryWrapper.SetRepository<Customer>()
.TableNoTracking
.Skip(request.Page * request.Count)
.Take(request.Page)
.Select(CustomerMapper.ProjectToSDto)
.ToListAsync(cancellationToken);
return response;
}
}

View File

@ -9,9 +9,11 @@ public class CreateProductCategoryCommandHandler(IRepositoryWrapper repositoryWr
if (request.ParentId != default) if (request.ParentId != default)
ent.SetParent(request.ParentId); ent.SetParent(request.ParentId);
foreach (var file in request.Files) foreach (var file in request.Files)
{
ent.AddFile(file.Name, file.FileLocation, file.FileName, file.IsHeader, file.IsPrimary, file.FileType); ent.AddFile(file.Name, file.FileLocation, file.FileName, file.IsHeader, file.IsPrimary, file.FileType);
}
foreach (var (key, value) in request.MetaTags)
ent.AddMetaTag(key, value);
repositoryWrapper.SetRepository<ProductCategory>().Add(ent); repositoryWrapper.SetRepository<ProductCategory>().Add(ent);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await repositoryWrapper.SaveChangesAsync(cancellationToken);
await UpdateFaqAsync(ent, request.Faqs, cancellationToken); await UpdateFaqAsync(ent, request.Faqs, cancellationToken);

View File

@ -32,6 +32,20 @@ public class UpdateProductCategoryCommandHandler(IRepositoryWrapper repositoryWr
{ {
newEnt.AddFile(file.Name, file.FileLocation, file.FileName, file.IsHeader, file.IsPrimary, file.FileType); newEnt.AddFile(file.Name, file.FileLocation, file.FileName, file.IsHeader, file.IsPrimary, file.FileType);
} }
var dbMetaTags = await repositoryWrapper.SetRepository<ProductCategoryMetaTag>()
.TableNoTracking
.Where(f => f.ProductCategoryId == ent.Id)
.ToListAsync(cancellationToken);
foreach (var feature in dbMetaTags.Where(feature => request.MetaTags.Any(f => f.Key == feature.Type) == false))
{
repositoryWrapper.SetRepository<ProductCategoryMetaTag>()
.Delete(feature);
await repositoryWrapper.SaveChangesAsync(cancellationToken);
}
foreach (var (key, value) in request.MetaTags.Where(f => dbMetaTags.Any(dbf => dbf.Type == f.Key) == false))
newEnt.AddMetaTag(key, value);
repositoryWrapper.SetRepository<ProductCategory>().Update(newEnt); repositoryWrapper.SetRepository<ProductCategory>().Update(newEnt);
await repositoryWrapper.SaveChangesAsync(cancellationToken); await repositoryWrapper.SaveChangesAsync(cancellationToken);
await UpdateFaqAsync(newEnt, request.Faqs, cancellationToken); await UpdateFaqAsync(newEnt, request.Faqs, cancellationToken);

View File

@ -13,7 +13,7 @@ public class GetProductsQueryHandler(
if (currentUserService.JwtToken == null) if (currentUserService.JwtToken == null)
products = products.Where(p => p.BeDisplayed); products = products.Where(p => p.BeDisplayed);
var roleClaim = currentUserService.JwtToken?.Claims.FirstOrDefault(c => c.Type == "role"); var roleClaim = currentUserService.JwtToken?.Claims.FirstOrDefault(c => c.Type == "role");
if (roleClaim != null && roleClaim.Value.Contains("Customer")) if (roleClaim != null && roleClaim.Value.Contains("Customer"))
products = products.Where(p => p.BeDisplayed); products = products.Where(p => p.BeDisplayed);
if (request.IsActive != null) if (request.IsActive != null)
@ -39,6 +39,7 @@ public class GetProductsQueryHandler(
{ {
var cats = await mediator.Send(new GetProductCategoryChildrenQuery(request.CategoryId), cancellationToken); var cats = await mediator.Send(new GetProductCategoryChildrenQuery(request.CategoryId), cancellationToken);
products = products.Where(p => cats.Contains(p.CategoryId)); products = products.Where(p => cats.Contains(p.CategoryId));
response.Seo = await GetSeoResponse(request.CategoryId, cancellationToken);
} }
if (request.BrandIds is { Length: > 0 }) if (request.BrandIds is { Length: > 0 })
products = products.Where(p => request.BrandIds.Contains(p.BrandId)); products = products.Where(p => request.BrandIds.Contains(p.BrandId));
@ -46,7 +47,7 @@ public class GetProductsQueryHandler(
products = products.Where(p => p.Cost >= request.MinPrice); products = products.Where(p => p.Cost >= request.MinPrice);
if (request.MaxPrice > 0) if (request.MaxPrice > 0)
products = products.Where(p => p.Cost <= request.MaxPrice); products = products.Where(p => p.Cost <= request.MaxPrice);
if (request.SpecialOffer != null) if (request.SpecialOffer != null)
{ {
@ -90,4 +91,29 @@ public class GetProductsQueryHandler(
return response; return response;
} }
private async Task<SeoResponseDto> GetSeoResponse(Guid categoryId, CancellationToken cancellationToken = default)
{
var response = new SeoResponseDto();
var metaTags = await repositoryWrapper.SetRepository<ProductCategoryMetaTag>().TableNoTracking
.Where(c => c.ProductCategoryId == categoryId)
.ToListAsync(cancellationToken);
var titleMeta = metaTags.FirstOrDefault(m => m.Type.ToLower().Contains("title"));
if (titleMeta != null)
{
response.Title = titleMeta.Value;
metaTags.Remove(titleMeta);
}
var descriptionMeta = metaTags.FirstOrDefault(m => m.Type.ToLower().Contains("description"));
if (descriptionMeta != null)
{
response.Description = descriptionMeta.Value;
metaTags.Remove(descriptionMeta);
}
foreach (var metaTag in metaTags)
response.MetaTags.Add(metaTag.Type, metaTag.Value);
return response;
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,59 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace NetinaShop.Repository.Migrations
{
/// <inheritdoc />
public partial class addMetaTag : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "MetaTags",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Type = table.Column<string>(type: "text", nullable: false),
Value = table.Column<string>(type: "text", nullable: false),
Discriminator = table.Column<string>(type: "character varying(34)", maxLength: 34, nullable: false),
ProductCategoryId = table.Column<Guid>(type: "uuid", nullable: true),
RemovedAt = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
CreatedBy = table.Column<string>(type: "text", nullable: false),
IsRemoved = table.Column<bool>(type: "boolean", nullable: false),
RemovedBy = table.Column<string>(type: "text", nullable: false),
ModifiedAt = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
ModifiedBy = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_MetaTags", x => x.Id);
table.ForeignKey(
name: "FK_MetaTags_ProductCategories_ProductCategoryId",
column: x => x.ProductCategoryId,
principalSchema: "public",
principalTable: "ProductCategories",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_MetaTags_ProductCategoryId",
schema: "public",
table: "MetaTags",
column: "ProductCategoryId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "MetaTags",
schema: "public");
}
}
}

View File

@ -1032,6 +1032,58 @@ namespace NetinaShop.Repository.Migrations
b.ToTable("Specifications", "public"); b.ToTable("Specifications", "public");
}); });
modelBuilder.Entity("Netina.Domain.Entities.Seo.MetaTag", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp without time zone");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Discriminator")
.IsRequired()
.HasMaxLength(34)
.HasColumnType("character varying(34)");
b.Property<bool>("IsRemoved")
.HasColumnType("boolean");
b.Property<DateTime>("ModifiedAt")
.HasColumnType("timestamp without time zone");
b.Property<string>("ModifiedBy")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("RemovedAt")
.HasColumnType("timestamp without time zone");
b.Property<string>("RemovedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Value")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("MetaTags", "public");
b.HasDiscriminator().HasValue("MetaTag");
b.UseTphMappingStrategy();
});
modelBuilder.Entity("Netina.Domain.Entities.StorageFiles.StorageFile", b => modelBuilder.Entity("Netina.Domain.Entities.StorageFiles.StorageFile", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@ -1634,6 +1686,18 @@ namespace NetinaShop.Repository.Migrations
b.HasDiscriminator().HasValue("ProductDiscount"); b.HasDiscriminator().HasValue("ProductDiscount");
}); });
modelBuilder.Entity("Netina.Domain.Entities.ProductCategories.ProductCategoryMetaTag", b =>
{
b.HasBaseType("Netina.Domain.Entities.Seo.MetaTag");
b.Property<Guid>("ProductCategoryId")
.HasColumnType("uuid");
b.HasIndex("ProductCategoryId");
b.HasDiscriminator().HasValue("ProductCategoryMetaTag");
});
modelBuilder.Entity("Netina.Domain.Entities.Blogs.BlogStorageFile", b => modelBuilder.Entity("Netina.Domain.Entities.Blogs.BlogStorageFile", b =>
{ {
b.HasBaseType("Netina.Domain.Entities.StorageFiles.StorageFile"); b.HasBaseType("Netina.Domain.Entities.StorageFiles.StorageFile");
@ -1996,6 +2060,16 @@ namespace NetinaShop.Repository.Migrations
b.Navigation("Product"); b.Navigation("Product");
}); });
modelBuilder.Entity("Netina.Domain.Entities.ProductCategories.ProductCategoryMetaTag", b =>
{
b.HasOne("Netina.Domain.Entities.ProductCategories.ProductCategory", "ProductCategory")
.WithMany("MetaTags")
.HasForeignKey("ProductCategoryId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("ProductCategory");
});
modelBuilder.Entity("Netina.Domain.Entities.Blogs.BlogStorageFile", b => modelBuilder.Entity("Netina.Domain.Entities.Blogs.BlogStorageFile", b =>
{ {
b.HasOne("Netina.Domain.Entities.Blogs.Blog", "Blog") b.HasOne("Netina.Domain.Entities.Blogs.Blog", "Blog")
@ -2076,6 +2150,8 @@ namespace NetinaShop.Repository.Migrations
{ {
b.Navigation("Files"); b.Navigation("Files");
b.Navigation("MetaTags");
b.Navigation("Products"); b.Navigation("Products");
}); });

View File

@ -30,6 +30,7 @@
<ItemGroup> <ItemGroup>
<Folder Include="Handlers\Blogs\" /> <Folder Include="Handlers\Blogs\" />
<Folder Include="Handlers\Customers\" />
<Folder Include="Models\" /> <Folder Include="Models\" />
<Folder Include="Extensions\" /> <Folder Include="Extensions\" />
<Folder Include="Services\Abstracts\" /> <Folder Include="Services\Abstracts\" />