diff --git a/aspnet-core/common.props b/aspnet-core/common.props
index 22d34c4..03d453c 100644
--- a/aspnet-core/common.props
+++ b/aspnet-core/common.props
@@ -16,4 +16,9 @@
+
+ true
+ true
+
+
\ No newline at end of file
diff --git a/aspnet-core/src/BookStore.Application.Contracts/BookStore.Application.Contracts.csproj b/aspnet-core/src/BookStore.Application.Contracts/BookStore.Application.Contracts.csproj
index f544d0a..3ff8fed 100644
--- a/aspnet-core/src/BookStore.Application.Contracts/BookStore.Application.Contracts.csproj
+++ b/aspnet-core/src/BookStore.Application.Contracts/BookStore.Application.Contracts.csproj
@@ -1,4 +1,4 @@
-
+
diff --git a/aspnet-core/src/BookStore.Application.Contracts/Books/BookDto.cs b/aspnet-core/src/BookStore.Application.Contracts/Books/BookDto.cs
new file mode 100644
index 0000000..8acb3f8
--- /dev/null
+++ b/aspnet-core/src/BookStore.Application.Contracts/Books/BookDto.cs
@@ -0,0 +1,13 @@
+using System;
+using Volo.Abp.Application.Dtos;
+
+namespace BookStore.Books;
+
+public class BookDto : AuditedEntityDto
+{
+ public string Name { get; set; }
+
+ public float Price { get; set; }
+
+ public Guid AuthorId { get; set; }
+}
\ No newline at end of file
diff --git a/aspnet-core/src/BookStore.Application.Contracts/Books/CreateBookDto.cs b/aspnet-core/src/BookStore.Application.Contracts/Books/CreateBookDto.cs
new file mode 100644
index 0000000..aef4b4d
--- /dev/null
+++ b/aspnet-core/src/BookStore.Application.Contracts/Books/CreateBookDto.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Volo.Abp.Application.Dtos;
+using Volo.Abp.Application.Services;
+
+namespace BookStore.Books;
+
+public class CreateBookDto
+{
+ public string Name { get; set; }
+
+ public float Price { get; set; }
+
+ public Guid AuthorId { get; set; }
+}
diff --git a/aspnet-core/src/BookStore.Application.Contracts/Books/IBookAppService.cs b/aspnet-core/src/BookStore.Application.Contracts/Books/IBookAppService.cs
new file mode 100644
index 0000000..059febb
--- /dev/null
+++ b/aspnet-core/src/BookStore.Application.Contracts/Books/IBookAppService.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+using Volo.Abp.Application.Services;
+
+namespace BookStore.Books;
+
+public interface IBookAppService : IApplicationService
+{
+ Task CreateAsync(CreateBookDto input);
+}
\ No newline at end of file
diff --git a/aspnet-core/src/BookStore.Application/BookStore.Application.csproj b/aspnet-core/src/BookStore.Application/BookStore.Application.csproj
index 5c7f0e2..2c245ba 100644
--- a/aspnet-core/src/BookStore.Application/BookStore.Application.csproj
+++ b/aspnet-core/src/BookStore.Application/BookStore.Application.csproj
@@ -1,4 +1,4 @@
-
+
@@ -15,6 +15,7 @@
+
diff --git a/aspnet-core/src/BookStore.Application/BookStoreApplicationAutoMapperProfile.cs b/aspnet-core/src/BookStore.Application/BookStoreApplicationAutoMapperProfile.cs
index 2f15e6a..736ae67 100644
--- a/aspnet-core/src/BookStore.Application/BookStoreApplicationAutoMapperProfile.cs
+++ b/aspnet-core/src/BookStore.Application/BookStoreApplicationAutoMapperProfile.cs
@@ -1,4 +1,5 @@
using AutoMapper;
+using BookStore.Books;
namespace BookStore;
@@ -9,5 +10,6 @@ public BookStoreApplicationAutoMapperProfile()
/* You can configure your AutoMapper mapping configuration here.
* Alternatively, you can split your mapping configurations
* into multiple profile classes for a better organization. */
+ CreateMap();
}
}
diff --git a/aspnet-core/src/BookStore.Application/BookStoreApplicationModule.cs b/aspnet-core/src/BookStore.Application/BookStoreApplicationModule.cs
index 565103a..a716186 100644
--- a/aspnet-core/src/BookStore.Application/BookStoreApplicationModule.cs
+++ b/aspnet-core/src/BookStore.Application/BookStoreApplicationModule.cs
@@ -1,6 +1,7 @@
using Volo.Abp.Account;
using Volo.Abp.AutoMapper;
using Volo.Abp.FeatureManagement;
+using Volo.Abp.FluentValidation;
using Volo.Abp.Identity;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement;
@@ -17,7 +18,8 @@ namespace BookStore;
typeof(AbpPermissionManagementApplicationModule),
typeof(AbpTenantManagementApplicationModule),
typeof(AbpFeatureManagementApplicationModule),
- typeof(AbpSettingManagementApplicationModule)
+ typeof(AbpSettingManagementApplicationModule),
+ typeof(AbpFluentValidationModule)
)]
public class BookStoreApplicationModule : AbpModule
{
diff --git a/aspnet-core/src/BookStore.Application/Books/BookAppService.cs b/aspnet-core/src/BookStore.Application/Books/BookAppService.cs
new file mode 100644
index 0000000..66518cc
--- /dev/null
+++ b/aspnet-core/src/BookStore.Application/Books/BookAppService.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Threading.Tasks;
+
+namespace BookStore.Books;
+
+public class BookAppService : BookStoreAppService, IBookAppService
+{
+ public Task CreateAsync(CreateBookDto input)
+ {
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/src/BookStore.Application/Books/CreateBookValidator.cs b/aspnet-core/src/BookStore.Application/Books/CreateBookValidator.cs
new file mode 100644
index 0000000..7e258df
--- /dev/null
+++ b/aspnet-core/src/BookStore.Application/Books/CreateBookValidator.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using FluentValidation;
+using Volo.Abp.Application.Dtos;
+using Volo.Abp.Application.Services;
+using Volo.Abp.Domain.Repositories;
+
+namespace BookStore.Books;
+
+public class CreateBookValidator : AbstractValidator
+{
+ public CreateBookValidator()
+ {
+ RuleFor(o => o.Name).NotNull().WithMessage("TEst");
+ RuleFor(o => o.Price).NotEmpty();
+ RuleFor(o => o.AuthorId).NotEmpty();
+ }
+}
diff --git a/aspnet-core/src/BookStore.HttpApi.Host/AbpFluentValidationActionFilter.cs b/aspnet-core/src/BookStore.HttpApi.Host/AbpFluentValidationActionFilter.cs
new file mode 100644
index 0000000..0792b61
--- /dev/null
+++ b/aspnet-core/src/BookStore.HttpApi.Host/AbpFluentValidationActionFilter.cs
@@ -0,0 +1,94 @@
+using System.Linq;
+using System.Threading.Tasks;
+using FluentValidation;
+using Microsoft.AspNetCore.Mvc.Abstractions;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Volo.Abp.AspNetCore.Mvc;
+using Volo.Abp.Reflection;
+using Volo.Abp.Validation;
+
+namespace BookStore;
+
+public class AbpFluentValidationActionFilter : IAsyncActionFilter
+{
+ public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
+ {
+ if (!context.ActionDescriptor.IsControllerAction())
+ {
+ await next();
+ return;
+ }
+
+ if (!context.GetRequiredService>().Value.AutoModelValidation)
+ {
+ await next();
+ return;
+ }
+
+ if (ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(context.ActionDescriptor.GetMethodInfo()) != null)
+ {
+ await next();
+ return;
+ }
+
+ if (ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(context.Controller.GetType()) != null)
+ {
+ await next();
+ return;
+ }
+
+ if (context.ActionDescriptor.GetMethodInfo().DeclaringType != context.Controller.GetType())
+ {
+ var baseMethod = context.ActionDescriptor.GetMethodInfo();
+
+ var overrideMethod = context.Controller.GetType().GetMethods().FirstOrDefault(x =>
+ x.DeclaringType == context.Controller.GetType() &&
+ x.Name == baseMethod.Name &&
+ x.ReturnType == baseMethod.ReturnType &&
+ x.GetParameters().Select(p => p.ToString()).SequenceEqual(baseMethod.GetParameters().Select(p => p.ToString())));
+
+ if (overrideMethod != null)
+ {
+ if (ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(overrideMethod) != null)
+ {
+ await next();
+ return;
+ }
+ }
+ }
+
+ var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
+ var serviceProvider = context.HttpContext.RequestServices;
+
+ foreach (var parameter in controllerActionDescriptor.Parameters)
+ {
+ if (context.ActionArguments.TryGetValue(parameter.Name, out var value))
+ {
+ var parameterInfo = (parameter as ControllerParameterDescriptor)?.ParameterInfo;
+ var parameterType = parameter.ParameterType;
+
+ if (value != null &&
+ !TypeHelper.IsPrimitiveExtended(parameterType) &&
+ serviceProvider.GetService(typeof(IValidator<>).MakeGenericType(parameterType)) is IValidator validator)
+ {
+ var validationContext = new ValidationContext