Generator Changes at 9/27/2025 8:46:36 AM

This commit is contained in:
generator
2025-09-27 08:46:36 +03:30
parent fd82e3edcf
commit fd8614f72e
261 changed files with 6333 additions and 0 deletions

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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();
}
}

View File

@@ -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.")
{
}
}

View File

@@ -0,0 +1,8 @@
namespace CMSMicroservice.Application.Common.Exceptions;
public class ForbiddenAccessException : Exception
{
public ForbiddenAccessException() : base()
{
}
}

View File

@@ -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.")
{
}
}

View File

@@ -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; }
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -0,0 +1,6 @@
namespace CMSMicroservice.Application.Common.Interfaces;
public interface ICurrentUserService
{
string? UserId { get; }
}

View File

@@ -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}");
}
}

View File

@@ -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}");
}
}

View File

@@ -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}");
}
}

View File

@@ -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}");
}
}

View File

@@ -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}");
}
}

View File

@@ -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}");
}
}

View 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; }
}

View File

@@ -0,0 +1,10 @@
namespace CMSMicroservice.Application.Common.Models;
public class PaginationState
{
//شماره صفحه
public int PageNumber { get; set; }
//اندازه صفحه
public int PageSize { get; set; }
}