Generator Changes at 9/27/2025 8:46:36 AM
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
using MediatR.Pipeline;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CMSMicroservice.Application.Common.Behaviours;
|
||||
|
||||
public class LoggingBehaviour<TRequest> : IRequestPreProcessor<TRequest> where TRequest : notnull
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly ICurrentUserService _currentUserService;
|
||||
|
||||
public LoggingBehaviour(ILogger<TRequest> logger, ICurrentUserService currentUserService)
|
||||
{
|
||||
_logger = logger;
|
||||
_currentUserService = currentUserService;
|
||||
}
|
||||
|
||||
public async Task Process(TRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var requestName = typeof(TRequest).Name;
|
||||
var userId = _currentUserService.UserId ?? string.Empty;
|
||||
_logger.LogInformation("Request: {Name} {@UserId} {@Request}",
|
||||
requestName, userId, request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Diagnostics;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CMSMicroservice.Application.Common.Behaviours;
|
||||
|
||||
public class PerformanceBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : IRequest<TResponse>
|
||||
{
|
||||
private readonly Stopwatch _timer;
|
||||
private readonly ILogger<TRequest> _logger;
|
||||
private readonly ICurrentUserService _currentUserService;
|
||||
|
||||
public PerformanceBehaviour(ILogger<TRequest> logger, ICurrentUserService currentUserService)
|
||||
{
|
||||
_timer = new Stopwatch();
|
||||
_logger = logger;
|
||||
_currentUserService = currentUserService;
|
||||
}
|
||||
|
||||
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
_timer.Start();
|
||||
|
||||
var response = await next();
|
||||
|
||||
_timer.Stop();
|
||||
|
||||
var elapsedMilliseconds = _timer.ElapsedMilliseconds;
|
||||
|
||||
if (elapsedMilliseconds > 500)
|
||||
{
|
||||
var requestName = typeof(TRequest).Name;
|
||||
var userId = _currentUserService.UserId ?? string.Empty;
|
||||
|
||||
_logger.LogWarning("Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@UserId} {@Request}",
|
||||
requestName, elapsedMilliseconds, userId, request);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CMSMicroservice.Application.Common.Behaviours;
|
||||
|
||||
public class UnhandledExceptionBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : IRequest<TResponse>
|
||||
{
|
||||
private readonly ILogger<TRequest> _logger;
|
||||
|
||||
public UnhandledExceptionBehaviour(ILogger<TRequest> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await next();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var requestName = typeof(TRequest).Name;
|
||||
|
||||
_logger.LogError(ex, "Request: Unhandled Exception for Request {Name} {@Request}", requestName, request);
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using ValidationException = CMSMicroservice.Application.Common.Exceptions.ValidationException;
|
||||
|
||||
namespace CMSMicroservice.Application.Common.Behaviours;
|
||||
|
||||
public class ValidationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : IRequest<TResponse>
|
||||
{
|
||||
private readonly IEnumerable<IValidator<TRequest>> _validators;
|
||||
|
||||
public ValidationBehaviour(IEnumerable<IValidator<TRequest>> validators)
|
||||
{
|
||||
_validators = validators;
|
||||
}
|
||||
|
||||
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (_validators.Any())
|
||||
{
|
||||
var context = new ValidationContext<TRequest>(request);
|
||||
|
||||
var validationResults = await Task.WhenAll(
|
||||
_validators.Select(v =>
|
||||
v.ValidateAsync(context, cancellationToken)));
|
||||
|
||||
var failures = validationResults
|
||||
.Where(r => r.Errors.Any())
|
||||
.SelectMany(r => r.Errors)
|
||||
.ToList();
|
||||
|
||||
if (failures.Any())
|
||||
throw new ValidationException(failures);
|
||||
}
|
||||
|
||||
return await next();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace CMSMicroservice.Application.Common.Exceptions;
|
||||
|
||||
public class DuplicateException : Exception
|
||||
{
|
||||
public DuplicateException()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public DuplicateException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public DuplicateException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public DuplicateException(string name, object key)
|
||||
: base($"Entity \"{name}\" ({key}) already exists.")
|
||||
{
|
||||
}
|
||||
|
||||
public DuplicateException(string name, string field, object? key)
|
||||
: base($"Entity \"{name}\" field \"{field}\" ({key}) already exists.")
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace CMSMicroservice.Application.Common.Exceptions;
|
||||
|
||||
public class ForbiddenAccessException : Exception
|
||||
{
|
||||
public ForbiddenAccessException() : base()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace CMSMicroservice.Application.Common.Exceptions;
|
||||
|
||||
public class NotFoundException : Exception
|
||||
{
|
||||
public NotFoundException()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public NotFoundException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public NotFoundException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public NotFoundException(string name, object key)
|
||||
: base($"Entity \"{name}\" ({key}) was not found.")
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using FluentValidation.Results;
|
||||
|
||||
namespace CMSMicroservice.Application.Common.Exceptions;
|
||||
|
||||
public class ValidationException : Exception
|
||||
{
|
||||
public ValidationException()
|
||||
: base("One or more validation failures have occurred.")
|
||||
{
|
||||
Errors = new Dictionary<string, string[]>();
|
||||
}
|
||||
|
||||
public ValidationException(IEnumerable<ValidationFailure> failures)
|
||||
: this()
|
||||
{
|
||||
Errors = failures
|
||||
.GroupBy(e => e.PropertyName, e => e.ErrorMessage)
|
||||
.ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray());
|
||||
}
|
||||
|
||||
public IDictionary<string, string[]> Errors { get; }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace CMSMicroservice.Application.Common.Extensions;
|
||||
|
||||
public static class MetaDataExtensions
|
||||
{
|
||||
public static async Task<MetaData> GetMetaData<T>(this IQueryable<T> source, PaginationState? paginationState,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (paginationState is null)
|
||||
return new MetaData
|
||||
{
|
||||
TotalCount = await source.CountAsync(cancellationToken)
|
||||
};
|
||||
|
||||
var pageSize = paginationState.PageSize > 0 ? paginationState.PageSize : PaginationDefaults.PageSize;
|
||||
var pageNumber = paginationState.PageNumber > 0 ? paginationState.PageNumber : PaginationDefaults.PageNumber;
|
||||
var totalCount = await source.CountAsync(cancellationToken);
|
||||
var totalPageCount = (int)Math.Ceiling(totalCount / (double)pageSize);
|
||||
|
||||
var metaData = new MetaData
|
||||
{
|
||||
CurrentPage = pageNumber,
|
||||
HasNext = pageNumber < totalPageCount,
|
||||
HasPrevious = pageNumber > 1,
|
||||
PageSize = pageSize,
|
||||
TotalCount = totalCount,
|
||||
TotalPage = totalPageCount
|
||||
};
|
||||
return metaData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace CMSMicroservice.Application.Common.Extensions;
|
||||
|
||||
public static class PaginationStateExtensions
|
||||
{
|
||||
public static IQueryable<TSource> PaginatedListAsync<TSource>(this IQueryable<TSource> source,
|
||||
PaginationState? paginationState)
|
||||
{
|
||||
if (paginationState is null)
|
||||
return source;
|
||||
|
||||
var pageSize = paginationState.PageSize > 0 ? paginationState.PageSize : PaginationDefaults.PageSize;
|
||||
var pageNumber = paginationState.PageNumber > 0 ? paginationState.PageNumber : PaginationDefaults.PageNumber;
|
||||
var paginationSkip = pageSize * (pageNumber - 1);
|
||||
|
||||
return source.Skip(paginationSkip).Take(pageSize);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PaginationDefaults
|
||||
{
|
||||
public const int PageSize = 10;
|
||||
public const int PageNumber = 1;
|
||||
public const int Skip = 0;
|
||||
public const int Take = PageSize;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Linq.Dynamic.Core;
|
||||
using CMSMicroservice.Domain.Common;
|
||||
|
||||
namespace CMSMicroservice.Application.Common.Extensions;
|
||||
|
||||
public static class SortByExtensions
|
||||
{
|
||||
public static IQueryable<TSource> ApplyOrder<TSource>(this IQueryable<TSource> source,
|
||||
string? sortBy) where TSource : BaseAuditableEntity
|
||||
{
|
||||
// default sort approach
|
||||
if (sortBy is null or "")
|
||||
{
|
||||
source = source.OrderByDescending(p => p.Created);
|
||||
return source;
|
||||
}
|
||||
|
||||
// sort using dynamic linq
|
||||
source = source.OrderBy(sortBy);
|
||||
|
||||
return source;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace CMSMicroservice.Application.Common.Interfaces;
|
||||
|
||||
public interface IApplicationDbContext
|
||||
{
|
||||
DbSet<User> Users { get; }
|
||||
DbSet<UserAddress> UserAddresss { get; }
|
||||
DbSet<Package> Packages { get; }
|
||||
DbSet<UserOrder> UserOrders { get; }
|
||||
DbSet<Role> Roles { get; }
|
||||
DbSet<UserRole> UserRoles { get; }
|
||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace CMSMicroservice.Application.Common.Interfaces;
|
||||
|
||||
public interface ICurrentUserService
|
||||
{
|
||||
string? UserId { get; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace CMSMicroservice.Application.Common.Mappings;
|
||||
|
||||
public class PackageProfile : IRegister
|
||||
{
|
||||
void IRegister.Register(TypeAdapterConfig config)
|
||||
{
|
||||
//config.NewConfig<Source,Destination>()
|
||||
// .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace CMSMicroservice.Application.Common.Mappings;
|
||||
|
||||
public class RoleProfile : IRegister
|
||||
{
|
||||
void IRegister.Register(TypeAdapterConfig config)
|
||||
{
|
||||
//config.NewConfig<Source,Destination>()
|
||||
// .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace CMSMicroservice.Application.Common.Mappings;
|
||||
|
||||
public class UserAddressProfile : IRegister
|
||||
{
|
||||
void IRegister.Register(TypeAdapterConfig config)
|
||||
{
|
||||
//config.NewConfig<Source,Destination>()
|
||||
// .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace CMSMicroservice.Application.Common.Mappings;
|
||||
|
||||
public class UserOrderProfile : IRegister
|
||||
{
|
||||
void IRegister.Register(TypeAdapterConfig config)
|
||||
{
|
||||
//config.NewConfig<Source,Destination>()
|
||||
// .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace CMSMicroservice.Application.Common.Mappings;
|
||||
|
||||
public class UserProfile : IRegister
|
||||
{
|
||||
void IRegister.Register(TypeAdapterConfig config)
|
||||
{
|
||||
//config.NewConfig<Source,Destination>()
|
||||
// .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace CMSMicroservice.Application.Common.Mappings;
|
||||
|
||||
public class UserRoleProfile : IRegister
|
||||
{
|
||||
void IRegister.Register(TypeAdapterConfig config)
|
||||
{
|
||||
//config.NewConfig<Source,Destination>()
|
||||
// .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
|
||||
}
|
||||
}
|
||||
22
src/CMSMicroservice.Application/Common/Models/MetaData.cs
Normal file
22
src/CMSMicroservice.Application/Common/Models/MetaData.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace CMSMicroservice.Application.Common.Models;
|
||||
|
||||
public class MetaData
|
||||
{
|
||||
//صفحه جاری
|
||||
public long CurrentPage { get; set; }
|
||||
|
||||
//تعداد کل صفحات
|
||||
public long TotalPage { get; set; }
|
||||
|
||||
//تعداد در هر صفحه
|
||||
public long PageSize { get; set; }
|
||||
|
||||
//تعداد کل آیتمها
|
||||
public long TotalCount { get; set; }
|
||||
|
||||
//قبلی دارد؟
|
||||
public bool HasPrevious { get; set; }
|
||||
|
||||
//بعدی دارد؟
|
||||
public bool HasNext { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace CMSMicroservice.Application.Common.Models;
|
||||
|
||||
public class PaginationState
|
||||
{
|
||||
//شماره صفحه
|
||||
public int PageNumber { get; set; }
|
||||
|
||||
//اندازه صفحه
|
||||
public int PageSize { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user