diff --git a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Factories/CustomApplicationFactory.cs b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Factories/CustomApplicationFactory.cs index cdf0da3..73757b3 100644 --- a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Factories/CustomApplicationFactory.cs +++ b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Factories/CustomApplicationFactory.cs @@ -19,9 +19,8 @@ namespace BuildingBlocks.Test.Factories; public class CustomApplicationFactory : WebApplicationFactory where TEntryPoint : class { - public CustomApplicationFactory() : this(null) - { - } + public CustomApplicationFactory() + : this(null) { } public CustomApplicationFactory(Action testRegistrationServices = null) { @@ -38,15 +37,18 @@ protected override IHostBuilder CreateHostBuilder() { var builder = base.CreateHostBuilder(); - builder = builder.UseSerilog((_, _, configuration) => - { - if (OutputHelper is not null) - configuration.WriteTo.Xunit(OutputHelper); + builder = builder.UseSerilog( + (_, _, configuration) => + { + if (OutputHelper is not null) + configuration.WriteTo.Xunit(OutputHelper); - configuration.MinimumLevel.Is(LogEventLevel.Information) - .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) - .WriteTo.Console(); - }); + configuration + .MinimumLevel.Is(LogEventLevel.Information) + .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) + .WriteTo.Console(); + } + ); return builder; } @@ -77,16 +79,19 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) using var scope = sp.CreateScope(); var seeders = scope.ServiceProvider.GetServices(); - foreach (var seeder in seeders) seeder.SeedAllAsync().GetAwaiter().GetResult(); + foreach (var seeder in seeders) + seeder.SeedAllAsync().GetAwaiter().GetResult(); }); - builder.UseDefaultServiceProvider((env, c) => - { - // Handling Captive Dependency Problem - // https://ankitvijay.net/2020/03/17/net-core-and-di-beware-of-captive-dependency/ - // https://blog.ploeh.dk/2014/06/02/captive-dependency/ - if (env.HostingEnvironment.IsEnvironment("test") || env.HostingEnvironment.IsDevelopment()) - c.ValidateScopes = true; - }); + builder.UseDefaultServiceProvider( + (env, c) => + { + // Handling Captive Dependency Problem + // https://ankitvijay.net/2020/03/17/net-core-and-di-beware-of-captive-dependency/ + // https://blog.ploeh.dk/2014/06/02/captive-dependency/ + if (env.HostingEnvironment.IsEnvironment("test") || env.HostingEnvironment.IsDevelopment()) + c.ValidateScopes = true; + } + ); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/IntegrationTestFixture.cs b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/IntegrationTestFixture.cs index 1129575..d38c2bd 100644 --- a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/IntegrationTestFixture.cs +++ b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/IntegrationTestFixture.cs @@ -81,12 +81,14 @@ public Task ExecuteDbContextAsync(Func> act return ExecuteScopeAsync(sp => action(sp.GetService(), sp.GetService())); } - public Task InsertAsync(params T[] entities) where T : class, IAggregate + public Task InsertAsync(params T[] entities) + where T : class, IAggregate { return ExecuteDbContextAsync(db => db.GetCollection().InsertManyAsync(entities)); } - public Task InsertAsync(TEntity entity) where TEntity : class, IAggregate + public Task InsertAsync(TEntity entity) + where TEntity : class, IAggregate { return ExecuteDbContextAsync(db => db.GetCollection().InsertOneAsync(entity)); } @@ -117,8 +119,12 @@ public Task InsertAsync(TEntity entity, TEntity2 en }); } - public Task InsertAsync(TEntity entity, TEntity2 entity2, - TEntity3 entity3, TEntity4 entity4) + public Task InsertAsync( + TEntity entity, + TEntity2 entity2, + TEntity3 entity3, + TEntity4 entity4 + ) where TEntity : class, IAggregate where TEntity2 : class, IAggregate where TEntity3 : class, IAggregate @@ -134,10 +140,10 @@ public Task InsertAsync(TEntity entity, T }); } - public Task FindAsync(int id) where T : class, IAggregate + public Task FindAsync(int id) + where T : class, IAggregate { - return ExecuteDbContextAsync(db => - db.GetCollection().AsQueryable().SingleOrDefaultAsync(x => x.Id == id)); + return ExecuteDbContextAsync(db => db.GetCollection().AsQueryable().SingleOrDefaultAsync(x => x.Id == id)); } public override Task InitializeAsync() @@ -161,16 +167,14 @@ public IntegrationTestFixture() { Factory = new CustomApplicationFactory(); } + // protected readonly LaunchSettingsFixture LaunchSettings; protected HttpClient Client => Factory.CreateClient(); + public IHttpClientFactory HttpClientFactory => ServiceProvider.GetRequiredService(); - public IHttpClientFactory HttpClientFactory => - ServiceProvider.GetRequiredService(); - - public IHttpContextAccessor HttpContextAccessor => - ServiceProvider.GetRequiredService(); + public IHttpContextAccessor HttpContextAccessor => ServiceProvider.GetRequiredService(); public IServiceProvider ServiceProvider => Factory.Services; public IConfiguration Configuration => Factory.Configuration; @@ -234,7 +238,8 @@ public Task SendAsync(ICommand request, Cancell }); } - public Task SendAsync(T request, CancellationToken cancellationToken) where T : class, ICommand + public Task SendAsync(T request, CancellationToken cancellationToken) + where T : class, ICommand { return ExecuteScopeAsync(sp => { @@ -254,4 +259,4 @@ public Task QueryAsync(IQuery query, Cancellati return mediator.Send(query, cancellationToken); }); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/LaunchSettingsFixture.cs b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/LaunchSettingsFixture.cs index 8e441b7..7213b61 100644 --- a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/LaunchSettingsFixture.cs +++ b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/LaunchSettingsFixture.cs @@ -35,4 +35,4 @@ public void Dispose() { // ... clean up } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/Mongo2GoFixture.cs b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/Mongo2GoFixture.cs index c698902..f62d9b9 100644 --- a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/Mongo2GoFixture.cs +++ b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/Mongo2GoFixture.cs @@ -34,4 +34,4 @@ public void Dispose() { _mongoRunner.Dispose(); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/MongoDbFixture.cs b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/MongoDbFixture.cs index 88bc613..2f968e7 100644 --- a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/MongoDbFixture.cs +++ b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/MongoDbFixture.cs @@ -21,4 +21,4 @@ public void Dispose() var client = new MongoClient(MongoOptions.ConnectionString); client.DropDatabase(MongoOptions.DatabaseName); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/WebApiTestFixture.cs b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/WebApiTestFixture.cs index f8a68cc..aea6815 100644 --- a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/WebApiTestFixture.cs +++ b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Fixtures/WebApiTestFixture.cs @@ -13,12 +13,13 @@ public abstract class WebApiTestFixture : IntegrationTe where TEntryPoint : class where TDbContext : class, IMongoDbContext { - private static readonly JsonSerializerOptions SerializerOptions = new() - { - PropertyNameCaseInsensitive = true, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - Converters = {new JsonStringEnumConverter()} - }; + private static readonly JsonSerializerOptions SerializerOptions = + new() + { + PropertyNameCaseInsensitive = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + Converters = { new JsonStringEnumConverter() } + }; private string _route; @@ -30,9 +31,11 @@ protected void SetPath(string route) return; } - if (route.StartsWith("/")) route = route.Substring(1, route.Length - 1); + if (route.StartsWith("/")) + route = route.Substring(1, route.Length - 1); - if (route.EndsWith("/")) route = route.Substring(0, route.Length - 1); + if (route.EndsWith("/")) + route = route.Substring(0, route.Length - 1); _route = $"{route}/"; } @@ -104,19 +107,19 @@ protected static async Task ReadAsync(HttpResponseMessage response) return JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync(), SerializerOptions); } - protected virtual void ConfigureServices(IServiceCollection services) - { - } + protected virtual void ConfigureServices(IServiceCollection services) { } } -public abstract class WebApiTestFixture : IntegrationTestFixture where TEntryPoint : class +public abstract class WebApiTestFixture : IntegrationTestFixture + where TEntryPoint : class { - private static readonly JsonSerializerOptions SerializerOptions = new() - { - PropertyNameCaseInsensitive = true, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - Converters = {new JsonStringEnumConverter()} - }; + private static readonly JsonSerializerOptions SerializerOptions = + new() + { + PropertyNameCaseInsensitive = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + Converters = { new JsonStringEnumConverter() } + }; private string _route; @@ -128,9 +131,11 @@ protected void SetPath(string route) return; } - if (route.StartsWith("/")) route = route.Substring(1, route.Length - 1); + if (route.StartsWith("/")) + route = route.Substring(1, route.Length - 1); - if (route.EndsWith("/")) route = route.Substring(0, route.Length - 1); + if (route.EndsWith("/")) + route = route.Substring(0, route.Length - 1); _route = $"{route}/"; } @@ -202,7 +207,5 @@ protected static async Task ReadAsync(HttpResponseMessage response) return JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync(), SerializerOptions); } - protected virtual void ConfigureServices(IServiceCollection services) - { - } -} \ No newline at end of file + protected virtual void ConfigureServices(IServiceCollection services) { } +} diff --git a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Helpers/OptionsHelper.cs b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Helpers/OptionsHelper.cs index 2b26461..5ce8e91 100644 --- a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Helpers/OptionsHelper.cs +++ b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Helpers/OptionsHelper.cs @@ -10,18 +10,13 @@ public static TSettings GetOptions(string section, string settingsFil settingsFileName ??= "appsettings.test.json"; var configuration = new TSettings(); - GetConfigurationRoot(settingsFileName) - .GetSection(section) - .Bind(configuration); + GetConfigurationRoot(settingsFileName).GetSection(section).Bind(configuration); return configuration; } private static IConfigurationRoot GetConfigurationRoot(string settingsFileName) { - return new ConfigurationBuilder() - .AddJsonFile(settingsFileName, true) - .AddEnvironmentVariables() - .Build(); + return new ConfigurationBuilder().AddJsonFile(settingsFileName, true).AddEnvironmentVariables().Build(); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Mock/NullDataSeeder.cs b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Mock/NullDataSeeder.cs index e6ce3aa..4bdd695 100644 --- a/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Mock/NullDataSeeder.cs +++ b/src/BuildingBlocks/BuildingBlocks.IntegrationTest/Mock/NullDataSeeder.cs @@ -9,4 +9,4 @@ public Task SeedAllAsync() { return Task.CompletedTask; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Caching/CacheKey.cs b/src/BuildingBlocks/BulidingBlocks/Caching/CacheKey.cs index e692c06..bde26ec 100644 --- a/src/BuildingBlocks/BulidingBlocks/Caching/CacheKey.cs +++ b/src/BuildingBlocks/BulidingBlocks/Caching/CacheKey.cs @@ -14,4 +14,4 @@ public static string With(Type ownerType, params string[] keys) { return With($"{ownerType.GetCacheKey()}:{string.Join("-", keys)}"); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Caching/CachingBehavior.cs b/src/BuildingBlocks/BulidingBlocks/Caching/CachingBehavior.cs index 1de6eb6..4e3f8a1 100644 --- a/src/BuildingBlocks/BulidingBlocks/Caching/CachingBehavior.cs +++ b/src/BuildingBlocks/BulidingBlocks/Caching/CachingBehavior.cs @@ -18,18 +18,22 @@ public class CachingBehavior : IPipelineBehavior> _logger; private readonly int defaultCacheExpirationInHours = 1; - - public CachingBehavior(IEasyCachingProviderFactory cachingFactory, + public CachingBehavior( + IEasyCachingProviderFactory cachingFactory, ILogger> logger, - IEnumerable> cachePolicies) + IEnumerable> cachePolicies + ) { _logger = logger; _cachingProvider = cachingFactory.GetCachingProvider("mem"); _cachePolicies = cachePolicies; } - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken - cancellationToken) + public async Task Handle( + TRequest request, + RequestHandlerDelegate next, + CancellationToken cancellationToken + ) { var cachePolicy = _cachePolicies.FirstOrDefault(); if (cachePolicy == null) @@ -40,20 +44,25 @@ public async Task Handle(TRequest request, RequestHandlerDelegate(cacheKey); if (cachedResponse.Value != null) { - _logger.LogDebug("Response retrieved {TRequest} from cache. CacheKey: {CacheKey}", - typeof(TRequest).FullName, cacheKey); + _logger.LogDebug( + "Response retrieved {TRequest} from cache. CacheKey: {CacheKey}", + typeof(TRequest).FullName, + cacheKey + ); return cachedResponse.Value; } var response = await next(); - var time = cachePolicy.AbsoluteExpirationRelativeToNow ?? - DateTime.Now.AddHours(defaultCacheExpirationInHours); + var time = cachePolicy.AbsoluteExpirationRelativeToNow ?? DateTime.Now.AddHours(defaultCacheExpirationInHours); await _cachingProvider.SetAsync(cacheKey, response, time.TimeOfDay); - _logger.LogDebug("Caching response for {TRequest} with cache key: {CacheKey}", typeof(TRequest).FullName, - cacheKey); + _logger.LogDebug( + "Caching response for {TRequest} with cache key: {CacheKey}", + typeof(TRequest).FullName, + cacheKey + ); return response; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Caching/ExpirationOptions.cs b/src/BuildingBlocks/BulidingBlocks/Caching/ExpirationOptions.cs index 29f2a2d..a3f1d36 100644 --- a/src/BuildingBlocks/BulidingBlocks/Caching/ExpirationOptions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Caching/ExpirationOptions.cs @@ -10,4 +10,4 @@ public ExpirationOptions(DateTimeOffset absoluteExpiration) } public DateTimeOffset AbsoluteExpiration { get; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Caching/Extensions.cs b/src/BuildingBlocks/BulidingBlocks/Caching/Extensions.cs index 8397f50..4abb240 100644 --- a/src/BuildingBlocks/BulidingBlocks/Caching/Extensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Caching/Extensions.cs @@ -7,25 +7,27 @@ namespace BuildingBlocks.Caching; public static class Extensions { - public static IServiceCollection AddCachingRequestPolicies(this IServiceCollection services, - IList assembliesToScan) + public static IServiceCollection AddCachingRequestPolicies( + this IServiceCollection services, + IList assembliesToScan + ) { // ICachePolicy discovery and registration - services.Scan(scan => scan - .FromAssemblies(assembliesToScan ?? AppDomain.CurrentDomain.GetAssemblies()) - .AddClasses(classes => classes.AssignableTo(typeof(ICachePolicy<,>)), - false) - .AsImplementedInterfaces() - .WithTransientLifetime()); + services.Scan(scan => + scan.FromAssemblies(assembliesToScan ?? AppDomain.CurrentDomain.GetAssemblies()) + .AddClasses(classes => classes.AssignableTo(typeof(ICachePolicy<,>)), false) + .AsImplementedInterfaces() + .WithTransientLifetime() + ); // IInvalidateCachePolicy discovery and registration - services.Scan(scan => scan - .FromAssemblies(assembliesToScan ?? AppDomain.CurrentDomain.GetAssemblies()) - .AddClasses(classes => classes.AssignableTo(typeof(IInvalidateCachePolicy<,>)), - false) - .AsImplementedInterfaces() - .WithTransientLifetime()); + services.Scan(scan => + scan.FromAssemblies(assembliesToScan ?? AppDomain.CurrentDomain.GetAssemblies()) + .AddClasses(classes => classes.AssignableTo(typeof(IInvalidateCachePolicy<,>)), false) + .AsImplementedInterfaces() + .WithTransientLifetime() + ); return services; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Caching/ICachePolicy.cs b/src/BuildingBlocks/BulidingBlocks/Caching/ICachePolicy.cs index 92f3844..0ea4efa 100644 --- a/src/BuildingBlocks/BulidingBlocks/Caching/ICachePolicy.cs +++ b/src/BuildingBlocks/BulidingBlocks/Caching/ICachePolicy.cs @@ -4,14 +4,15 @@ namespace BuildingBlocks.Caching; -public interface ICachePolicy where TRequest : IRequest +public interface ICachePolicy + where TRequest : IRequest { DateTime? AbsoluteExpirationRelativeToNow { get; } string GetCacheKey(TRequest request) { - var r = new {request}; + var r = new { request }; var props = r.request.GetType().GetProperties().Select(pi => $"{pi.Name}:{pi.GetValue(r.request, null)}"); return $"{typeof(TRequest).FullName}{{{string.Join(",", props)}}}"; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Caching/IInvalidateCachePolicy.cs b/src/BuildingBlocks/BulidingBlocks/Caching/IInvalidateCachePolicy.cs index 8a0fa72..0b8e922 100644 --- a/src/BuildingBlocks/BulidingBlocks/Caching/IInvalidateCachePolicy.cs +++ b/src/BuildingBlocks/BulidingBlocks/Caching/IInvalidateCachePolicy.cs @@ -3,17 +3,16 @@ namespace BuildingBlocks.Caching; -public interface IInvalidateCachePolicy where TRequest : IRequest +public interface IInvalidateCachePolicy + where TRequest : IRequest { string GetCacheKey(TRequest request) { - var r = new {request}; + var r = new { request }; var props = r.request.GetType().GetProperties().Select(pi => $"{pi.Name}:{pi.GetValue(r.request, null)}"); return $"{typeof(TRequest).FullName}{{{string.Join(",", props)}}}"; } } public interface IInvalidateCachePolicy : IInvalidateCachePolicy - where TRequest : IRequest -{ -} \ No newline at end of file + where TRequest : IRequest { } diff --git a/src/BuildingBlocks/BulidingBlocks/Caching/InvalidateCachingBehavior.cs b/src/BuildingBlocks/BulidingBlocks/Caching/InvalidateCachingBehavior.cs index 5f3c000..440992f 100644 --- a/src/BuildingBlocks/BulidingBlocks/Caching/InvalidateCachingBehavior.cs +++ b/src/BuildingBlocks/BulidingBlocks/Caching/InvalidateCachingBehavior.cs @@ -16,18 +16,22 @@ public class InvalidateCachingBehavior : IPipelineBehavior< private readonly IEnumerable> _invalidateCachePolicies; private readonly ILogger> _logger; - - public InvalidateCachingBehavior(IEasyCachingProviderFactory cachingFactory, + public InvalidateCachingBehavior( + IEasyCachingProviderFactory cachingFactory, ILogger> logger, - IEnumerable> invalidateCachingPolicies) + IEnumerable> invalidateCachingPolicies + ) { _logger = logger; _cachingProvider = cachingFactory.GetCachingProvider("mem"); _invalidateCachePolicies = invalidateCachingPolicies; } - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken - cancellationToken) + public async Task Handle( + TRequest request, + RequestHandlerDelegate next, + CancellationToken cancellationToken + ) { var cachePolicy = _invalidateCachePolicies.FirstOrDefault(); if (cachePolicy == null) @@ -43,4 +47,4 @@ public async Task Handle(TRequest request, RequestHandlerDelegate : IRequest where T : notnull -{ -} +public interface ICommand : IRequest + where T : notnull { } -public interface ICommand : IRequest -{ -} +public interface ICommand : IRequest { } public interface IQuery : IRequest - where T : notnull -{ -} + where T : notnull { } public interface ICreateCommand : ICommand, ITxRequest - where TResponse : notnull -{ -} + where TResponse : notnull { } -public interface ICreateCommand : ICommand, ITxRequest -{ -} +public interface ICreateCommand : ICommand, ITxRequest { } -public interface IUpdateCommand : ICommand, ITxRequest -{ -} +public interface IUpdateCommand : ICommand, ITxRequest { } public interface IUpdateCommand : ICommand, ITxRequest - where TResponse : notnull -{ -} + where TResponse : notnull { } public interface IDeleteCommand : ICommand where TId : struct @@ -43,7 +30,8 @@ public interface IDeleteCommand : ICommand public TId Id { get; init; } } -public interface IDeleteCommand : ICommand where TId : struct +public interface IDeleteCommand : ICommand + where TId : struct { public TId Id { get; init; } } @@ -58,9 +46,7 @@ public interface IPageList } public interface IListQuery : IQuery, IPageList - where TResponse : notnull -{ -} + where TResponse : notnull { } public interface IItemQuery : IQuery where TId : struct @@ -72,19 +58,18 @@ public interface IItemQuery : IQuery public record FilterModel(string FieldName, string Comparision, string FieldValue); -public record ListResultModel(List Items, long TotalItems, int Page, int PageSize) where T : notnull +public record ListResultModel(List Items, long TotalItems, int Page, int PageSize) + where T : notnull { public static ListResultModel Empty => new(Enumerable.Empty().ToList(), 0, 0, 0); - public static ListResultModel Create(List items, long totalItems = 0, int page = default, - int pageSize = 20) + public static ListResultModel Create(List items, long totalItems = 0, int page = default, int pageSize = 20) { return new ListResultModel(items, totalItems, page, pageSize); } public ListResultModel Map(Func map) { - return ListResultModel.Create( - Items.Select(map).ToList(), TotalItems, Page, PageSize); + return ListResultModel.Create(Items.Select(map).ToList(), TotalItems, Page, PageSize); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Domain/IAggregate.cs b/src/BuildingBlocks/BulidingBlocks/Domain/IAggregate.cs index d4a1c6e..d6ba884 100644 --- a/src/BuildingBlocks/BulidingBlocks/Domain/IAggregate.cs +++ b/src/BuildingBlocks/BulidingBlocks/Domain/IAggregate.cs @@ -1,10 +1,8 @@ namespace BuildingBlocks.Domain; -public interface IAggregate : IAggregate -{ -} +public interface IAggregate : IAggregate { } public interface IAggregate { public T Id { get; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Domain/ITxRequest.cs b/src/BuildingBlocks/BulidingBlocks/Domain/ITxRequest.cs index aa2295c..9884ac8 100644 --- a/src/BuildingBlocks/BulidingBlocks/Domain/ITxRequest.cs +++ b/src/BuildingBlocks/BulidingBlocks/Domain/ITxRequest.cs @@ -1,5 +1,3 @@ namespace BuildingBlocks.Domain; -public interface ITxRequest -{ -} \ No newline at end of file +public interface ITxRequest { } diff --git a/src/BuildingBlocks/BulidingBlocks/EFCore/DesignTimeDbContextFactoryBase.cs b/src/BuildingBlocks/BulidingBlocks/EFCore/DesignTimeDbContextFactoryBase.cs index 134a590..9f28424 100644 --- a/src/BuildingBlocks/BulidingBlocks/EFCore/DesignTimeDbContextFactoryBase.cs +++ b/src/BuildingBlocks/BulidingBlocks/EFCore/DesignTimeDbContextFactoryBase.cs @@ -36,17 +36,14 @@ private TContext Create(string basePath, string environmentName) var connstr = config.GetConnectionString("DefaultConnection"); if (string.IsNullOrWhiteSpace(connstr)) - throw new InvalidOperationException( - "Could not find a connection string named 'Default'."); + throw new InvalidOperationException("Could not find a connection string named 'Default'."); return Create(connstr); } private TContext Create(string connectionString) { if (string.IsNullOrEmpty(connectionString)) - throw new ArgumentException( - $"{nameof(connectionString)} is null or empty.", - nameof(connectionString)); + throw new ArgumentException($"{nameof(connectionString)} is null or empty.", nameof(connectionString)); var optionsBuilder = new DbContextOptionsBuilder(); @@ -57,4 +54,4 @@ private TContext Create(string connectionString) var options = optionsBuilder.Options; return CreateNewInstance(options); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/EFCore/QueryableExtensions.cs b/src/BuildingBlocks/BulidingBlocks/EFCore/QueryableExtensions.cs index 5df3402..9c567ca 100644 --- a/src/BuildingBlocks/BulidingBlocks/EFCore/QueryableExtensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/EFCore/QueryableExtensions.cs @@ -8,24 +8,29 @@ namespace BuildingBlocks.EFCore; public static class QueryableExtensions { - public static async Task> PaginateAsync(this IQueryable collection, - IPageList query) + public static async Task> PaginateAsync(this IQueryable collection, IPageList query) { return await collection.PaginateAsync(query.Page, query.PageSize); } - public static async Task> PaginateAsync(this IQueryable collection, int page = 1, int - pageSize = 10) + public static async Task> PaginateAsync( + this IQueryable collection, + int page = 1, + int pageSize = 10 + ) { - if (page <= 0) page = 1; + if (page <= 0) + page = 1; - if (pageSize <= 0) pageSize = 10; + if (pageSize <= 0) + pageSize = 10; var isEmpty = await collection.AnyAsync() == false; - if (isEmpty) return ListResultModel.Empty; + if (isEmpty) + return ListResultModel.Empty; var totalItems = await collection.CountAsync(); - var totalPages = (int) Math.Ceiling((decimal) totalItems / pageSize); + var totalPages = (int)Math.Ceiling((decimal)totalItems / pageSize); var data = await collection.Limit(page, pageSize).ToListAsync(); return ListResultModel.Create(data, totalItems, page, pageSize); @@ -36,17 +41,17 @@ public static IQueryable Limit(this IQueryable collection, IPageList qu return collection.Limit(query.Page, query.PageSize); } - public static IQueryable Limit(this IQueryable collection, - int page = 1, int resultsPerPage = 10) + public static IQueryable Limit(this IQueryable collection, int page = 1, int resultsPerPage = 10) { - if (page <= 0) page = 1; + if (page <= 0) + page = 1; - if (resultsPerPage <= 0) resultsPerPage = 10; + if (resultsPerPage <= 0) + resultsPerPage = 10; var skip = (page - 1) * resultsPerPage; - var data = collection.Skip(skip) - .Take(resultsPerPage); + var data = collection.Skip(skip).Take(resultsPerPage); return data; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Exception/ApiException.cs b/src/BuildingBlocks/BulidingBlocks/Exception/ApiException.cs index e390fa7..a6b4dec 100644 --- a/src/BuildingBlocks/BulidingBlocks/Exception/ApiException.cs +++ b/src/BuildingBlocks/BulidingBlocks/Exception/ApiException.cs @@ -5,16 +5,11 @@ namespace BuildingBlocks.Exception; public class ApiException : ApplicationException { - public ApiException() - { - } + public ApiException() { } - public ApiException(string message) : base(message) - { - } + public ApiException(string message) + : base(message) { } public ApiException(string message, params object[] args) - : base(string.Format(CultureInfo.CurrentCulture, message, args)) - { - } -} \ No newline at end of file + : base(string.Format(CultureInfo.CurrentCulture, message, args)) { } +} diff --git a/src/BuildingBlocks/BulidingBlocks/Exception/AppException.cs b/src/BuildingBlocks/BulidingBlocks/Exception/AppException.cs index 67629f8..88eac6e 100644 --- a/src/BuildingBlocks/BulidingBlocks/Exception/AppException.cs +++ b/src/BuildingBlocks/BulidingBlocks/Exception/AppException.cs @@ -2,10 +2,11 @@ namespace BuildingBlocks.Exception; public class AppException : System.Exception { - public AppException(string message, string code = default!) : base(message) + public AppException(string message, string code = default!) + : base(message) { Code = code; } public virtual string Code { get; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Exception/BadRequestException.cs b/src/BuildingBlocks/BulidingBlocks/Exception/BadRequestException.cs index 9876e74..52ae106 100644 --- a/src/BuildingBlocks/BulidingBlocks/Exception/BadRequestException.cs +++ b/src/BuildingBlocks/BulidingBlocks/Exception/BadRequestException.cs @@ -4,7 +4,6 @@ namespace BuildingBlocks.Exception; public class BadRequestException : ApplicationException { - public BadRequestException(string message) : base(message) - { - } -} \ No newline at end of file + public BadRequestException(string message) + : base(message) { } +} diff --git a/src/BuildingBlocks/BulidingBlocks/Exception/InvalidCommandException.cs b/src/BuildingBlocks/BulidingBlocks/Exception/InvalidCommandException.cs index 04670a3..673af08 100644 --- a/src/BuildingBlocks/BulidingBlocks/Exception/InvalidCommandException.cs +++ b/src/BuildingBlocks/BulidingBlocks/Exception/InvalidCommandException.cs @@ -10,4 +10,4 @@ public InvalidCommandException(List errors) } public List Errors { get; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Exception/NotFoundException.cs b/src/BuildingBlocks/BulidingBlocks/Exception/NotFoundException.cs index c9a65ae..219e2ea 100644 --- a/src/BuildingBlocks/BulidingBlocks/Exception/NotFoundException.cs +++ b/src/BuildingBlocks/BulidingBlocks/Exception/NotFoundException.cs @@ -2,7 +2,6 @@ namespace BuildingBlocks.Exception; public class NotFoundException : System.Exception { - public NotFoundException(string message) : base(message) - { - } -} \ No newline at end of file + public NotFoundException(string message) + : base(message) { } +} diff --git a/src/BuildingBlocks/BulidingBlocks/Logging/Extensions.cs b/src/BuildingBlocks/BulidingBlocks/Logging/Extensions.cs index b8398a4..4a64ef4 100644 --- a/src/BuildingBlocks/BulidingBlocks/Logging/Extensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Logging/Extensions.cs @@ -13,57 +13,67 @@ public static class Extensions { public static WebApplicationBuilder AddCustomSerilog( this WebApplicationBuilder builder, - Action? extraConfigure = null) + Action? extraConfigure = null + ) { - builder.Host.UseSerilog((context, serviceProvider, loggerConfiguration) => - { - var loggerOptions = context.Configuration.GetSection(nameof(LoggerOptions)).Get(); + builder.Host.UseSerilog( + (context, serviceProvider, loggerConfiguration) => + { + var loggerOptions = context.Configuration.GetSection(nameof(LoggerOptions)).Get(); - extraConfigure?.Invoke(loggerConfiguration); + extraConfigure?.Invoke(loggerConfiguration); - loggerConfiguration - .ReadFrom.Configuration(context.Configuration) - .ReadFrom.Services(serviceProvider) - .Enrich.WithExceptionDetails() - .Enrich.WithCorrelationId() - .Enrich.FromLogContext(); + loggerConfiguration + .ReadFrom.Configuration(context.Configuration) + .ReadFrom.Services(serviceProvider) + .Enrich.WithExceptionDetails() + .Enrich.WithCorrelationId() + .Enrich.FromLogContext(); - var level = Enum.TryParse(loggerOptions?.Level, true, out var logLevel) - ? logLevel - : LogEventLevel.Information; + var level = Enum.TryParse(loggerOptions?.Level, true, out var logLevel) + ? logLevel + : LogEventLevel.Information; - // https://andrewlock.net/using-serilog-aspnetcore-in-asp-net-core-3-reducing-log-verbosity/ - loggerConfiguration.MinimumLevel.Is(level) - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .MinimumLevel - // Filter out ASP.NET Core infrastructure logs that are Information and below - .Override("Microsoft.AspNetCore", LogEventLevel.Warning); + // https://andrewlock.net/using-serilog-aspnetcore-in-asp-net-core-3-reducing-log-verbosity/ + loggerConfiguration + .MinimumLevel.Is(level) + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel + // Filter out ASP.NET Core infrastructure logs that are Information and below + .Override("Microsoft.AspNetCore", LogEventLevel.Warning); - if (context.HostingEnvironment.IsDevelopment()) - { - loggerConfiguration.WriteTo.Async(writeTo => writeTo.SpectreConsole( - loggerOptions?.LogTemplate ?? - "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", - level)); - } - else - { - if (!string.IsNullOrEmpty(loggerOptions?.ElasticSearchUrl)) - loggerConfiguration.WriteTo.Async(writeTo => writeTo.Elasticsearch(loggerOptions.ElasticSearchUrl)); + if (context.HostingEnvironment.IsDevelopment()) + { + loggerConfiguration.WriteTo.Async(writeTo => + writeTo.SpectreConsole( + loggerOptions?.LogTemplate + ?? "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", + level + ) + ); + } + else + { + if (!string.IsNullOrEmpty(loggerOptions?.ElasticSearchUrl)) + loggerConfiguration.WriteTo.Async(writeTo => + writeTo.Elasticsearch(loggerOptions.ElasticSearchUrl) + ); - if (!string.IsNullOrEmpty(loggerOptions?.SeqUrl)) - loggerConfiguration.WriteTo.Async(writeTo => writeTo.Seq(loggerOptions.SeqUrl)); - } + if (!string.IsNullOrEmpty(loggerOptions?.SeqUrl)) + loggerConfiguration.WriteTo.Async(writeTo => writeTo.Seq(loggerOptions.SeqUrl)); + } - if (!string.IsNullOrEmpty(loggerOptions?.LogPath)) - loggerConfiguration.WriteTo.File( - loggerOptions.LogPath, - outputTemplate: loggerOptions.LogTemplate ?? - "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level} - {Message:lj}{NewLine}{Exception}", - rollingInterval: RollingInterval.Day, - rollOnFileSizeLimit: true); - }); + if (!string.IsNullOrEmpty(loggerOptions?.LogPath)) + loggerConfiguration.WriteTo.File( + loggerOptions.LogPath, + outputTemplate: loggerOptions.LogTemplate + ?? "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level} - {Message:lj}{NewLine}{Exception}", + rollingInterval: RollingInterval.Day, + rollOnFileSizeLimit: true + ); + } + ); return builder; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Logging/LoggerOptions.cs b/src/BuildingBlocks/BulidingBlocks/Logging/LoggerOptions.cs index 6139181..8edb8af 100644 --- a/src/BuildingBlocks/BulidingBlocks/Logging/LoggerOptions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Logging/LoggerOptions.cs @@ -7,4 +7,4 @@ public class LoggerOptions public string? ElasticSearchUrl { get; set; } public string? LogTemplate { get; set; } public string? LogPath { get; set; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Logging/LoggingBehavior.cs b/src/BuildingBlocks/BulidingBlocks/Logging/LoggingBehavior.cs index 25b01e8..707d269 100644 --- a/src/BuildingBlocks/BulidingBlocks/Logging/LoggingBehavior.cs +++ b/src/BuildingBlocks/BulidingBlocks/Logging/LoggingBehavior.cs @@ -17,13 +17,20 @@ public LoggingBehavior(ILogger> logger) _logger = logger; } - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken - cancellationToken) + public async Task Handle( + TRequest request, + RequestHandlerDelegate next, + CancellationToken cancellationToken + ) { const string prefix = nameof(LoggingBehavior); - _logger.LogInformation("[{Prefix}] Handle request={X-RequestData} and response={X-ResponseData}", - prefix, typeof(TRequest).Name, typeof(TResponse).Name); + _logger.LogInformation( + "[{Prefix}] Handle request={X-RequestData} and response={X-ResponseData}", + prefix, + typeof(TRequest).Name, + typeof(TResponse).Name + ); var timer = new Stopwatch(); timer.Start(); @@ -33,10 +40,14 @@ public async Task Handle(TRequest request, RequestHandlerDelegate 3) // if the request is greater than 3 seconds, then log the warnings - _logger.LogWarning("[{Perf-Possible}] The request {X-RequestData} took {TimeTaken} seconds", - prefix, typeof(TRequest).Name, timeTaken.Seconds); + _logger.LogWarning( + "[{Perf-Possible}] The request {X-RequestData} took {TimeTaken} seconds", + prefix, + typeof(TRequest).Name, + timeTaken.Seconds + ); _logger.LogInformation("[{Prefix}] Handled {X-RequestData}", prefix, typeof(TRequest).Name); return response; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Mongo/Extensions.cs b/src/BuildingBlocks/BulidingBlocks/Mongo/Extensions.cs index 94beec9..a34013b 100644 --- a/src/BuildingBlocks/BulidingBlocks/Mongo/Extensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Mongo/Extensions.cs @@ -9,16 +9,22 @@ public static class Extensions private const string SectionName = "Mongo"; public static IServiceCollection AddMongoDbContext( - this IServiceCollection services, IConfiguration configuration, - string sectionName = SectionName, Action optionsAction = null) + this IServiceCollection services, + IConfiguration configuration, + string sectionName = SectionName, + Action optionsAction = null + ) where TContext : MongoDbContext { return services.AddMongoDbContext(configuration, sectionName, optionsAction); } public static IServiceCollection AddMongoDbContext( - this IServiceCollection services, IConfiguration configuration, - string sectionName = SectionName, Action optionsAction = null) + this IServiceCollection services, + IConfiguration configuration, + string sectionName = SectionName, + Action optionsAction = null + ) where TContextService : IMongoDbContext where TContextImplementation : MongoDbContext, TContextService { @@ -37,4 +43,4 @@ public static IServiceCollection AddMongoDbContext GetCollection(); -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Mongo/ImmutablePocoConvention.cs b/src/BuildingBlocks/BulidingBlocks/Mongo/ImmutablePocoConvention.cs index d31410b..a7fad34 100644 --- a/src/BuildingBlocks/BulidingBlocks/Mongo/ImmutablePocoConvention.cs +++ b/src/BuildingBlocks/BulidingBlocks/Mongo/ImmutablePocoConvention.cs @@ -16,9 +16,7 @@ public class ImmutablePocoConvention : ConventionBase, IClassMapConvention private readonly BindingFlags _bindingFlags; public ImmutablePocoConvention() - : this(BindingFlags.Instance | BindingFlags.Public) - { - } + : this(BindingFlags.Instance | BindingFlags.Public) { } public ImmutablePocoConvention(BindingFlags bindingFlags) { @@ -27,7 +25,8 @@ public ImmutablePocoConvention(BindingFlags bindingFlags) public void Apply(BsonClassMap classMap) { - var readOnlyProperties = classMap.ClassType.GetTypeInfo() + var readOnlyProperties = classMap + .ClassType.GetTypeInfo() .GetProperties(_bindingFlags) .Where(p => IsReadOnlyProperty(classMap, p)) .ToList(); @@ -48,8 +47,7 @@ public void Apply(BsonClassMap classMap) } } - private static List GetMatchingProperties(ConstructorInfo constructor, - List properties) + private static List GetMatchingProperties(ConstructorInfo constructor, List properties) { var matchProperties = new List(); @@ -66,11 +64,10 @@ private static List GetMatchingProperties(ConstructorInfo construc return matchProperties; } - private static bool ParameterMatchProperty(ParameterInfo parameter, PropertyInfo property) { return string.Equals(property.Name, parameter.Name, StringComparison.InvariantCultureIgnoreCase) - && parameter.ParameterType == property.PropertyType; + && parameter.ParameterType == property.PropertyType; } private static bool IsReadOnlyProperty(BsonClassMap classMap, PropertyInfo propertyInfo) @@ -94,4 +91,4 @@ private static bool IsReadOnlyProperty(BsonClassMap classMap, PropertyInfo prope return true; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Mongo/MongoDbContext.cs b/src/BuildingBlocks/BulidingBlocks/Mongo/MongoDbContext.cs index 42d0ad8..6c1de0f 100644 --- a/src/BuildingBlocks/BulidingBlocks/Mongo/MongoDbContext.cs +++ b/src/BuildingBlocks/BulidingBlocks/Mongo/MongoDbContext.cs @@ -61,13 +61,17 @@ public async Task RollbackTransactionAsync() private static void RegisterConventions() { - ConventionRegistry.Register("conventions", new ConventionPack - { - new CamelCaseElementNameConvention(), - new IgnoreExtraElementsConvention(true), - new EnumRepresentationConvention(BsonType.String), - new IgnoreIfDefaultConvention(true), - new ImmutablePocoConvention() - }, _ => true); + ConventionRegistry.Register( + "conventions", + new ConventionPack + { + new CamelCaseElementNameConvention(), + new IgnoreExtraElementsConvention(true), + new EnumRepresentationConvention(BsonType.String), + new IgnoreIfDefaultConvention(true), + new ImmutablePocoConvention() + }, + _ => true + ); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Mongo/MongoOptions.cs b/src/BuildingBlocks/BulidingBlocks/Mongo/MongoOptions.cs index cb70b60..d96f562 100644 --- a/src/BuildingBlocks/BulidingBlocks/Mongo/MongoOptions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Mongo/MongoOptions.cs @@ -7,4 +7,4 @@ public class MongoOptions public string ConnectionString { get; set; } public string DatabaseName { get; set; } public static Guid UniqueId { get; set; } = Guid.NewGuid(); -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Mongo/MongoQueryableExtensions.cs b/src/BuildingBlocks/BulidingBlocks/Mongo/MongoQueryableExtensions.cs index da9a763..7db9601 100644 --- a/src/BuildingBlocks/BulidingBlocks/Mongo/MongoQueryableExtensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Mongo/MongoQueryableExtensions.cs @@ -8,24 +8,29 @@ namespace MicroBootstrap.Mongo; public static class MongoQueryableExtensions { - public static async Task> PaginateAsync(this IMongoQueryable collection, - IPageList query) + public static async Task> PaginateAsync(this IMongoQueryable collection, IPageList query) { return await collection.PaginateAsync(query.Page, query.PageSize); } - public static async Task> PaginateAsync(this IMongoQueryable collection, int page = 1, - int pageSize = 10) + public static async Task> PaginateAsync( + this IMongoQueryable collection, + int page = 1, + int pageSize = 10 + ) { - if (page <= 0) page = 1; + if (page <= 0) + page = 1; - if (pageSize <= 0) pageSize = 10; + if (pageSize <= 0) + pageSize = 10; var isEmpty = await collection.AnyAsync() == false; - if (isEmpty) return ListResultModel.Empty; + if (isEmpty) + return ListResultModel.Empty; var totalItems = await collection.CountAsync(); - var totalPages = (int) Math.Ceiling((decimal) totalItems / pageSize); + var totalPages = (int)Math.Ceiling((decimal)totalItems / pageSize); var data = await collection.Limit(page, pageSize).ToListAsync(); return ListResultModel.Create(data, totalItems, page, pageSize); @@ -36,17 +41,17 @@ public static IMongoQueryable Limit(this IMongoQueryable collection, IP return collection.Limit(query.Page, query.PageSize); } - public static IMongoQueryable Limit(this IMongoQueryable collection, - int page = 1, int resultsPerPage = 10) + public static IMongoQueryable Limit(this IMongoQueryable collection, int page = 1, int resultsPerPage = 10) { - if (page <= 0) page = 1; + if (page <= 0) + page = 1; - if (resultsPerPage <= 0) resultsPerPage = 10; + if (resultsPerPage <= 0) + resultsPerPage = 10; var skip = (page - 1) * resultsPerPage; - var data = collection.Skip(skip) - .Take(resultsPerPage); + var data = collection.Skip(skip).Take(resultsPerPage); return data; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Mongo/MongoRepository.cs b/src/BuildingBlocks/BulidingBlocks/Mongo/MongoRepository.cs index 5670ef7..b87d35e 100644 --- a/src/BuildingBlocks/BulidingBlocks/Mongo/MongoRepository.cs +++ b/src/BuildingBlocks/BulidingBlocks/Mongo/MongoRepository.cs @@ -33,7 +33,6 @@ public Task GetAsync(Expression> predicate) return DbSet.Find(predicate).SingleOrDefaultAsync(); } - public async Task> FindAsync(Expression> predicate) { return await DbSet.Find(predicate).ToListAsync(); @@ -44,8 +43,8 @@ public IAsyncEnumerable GetAllAsync(Expression> pre return DbSet.AsQueryable().ToAsyncEnumerable(); } - public Task> BrowseAsync(Expression> predicate, - TQuery query) where TQuery : IPageList + public Task> BrowseAsync(Expression> predicate, TQuery query) + where TQuery : IPageList { return DbSet.AsQueryable().Where(predicate).PaginateAsync(query); } @@ -84,4 +83,4 @@ public void Dispose() { _context?.Dispose(); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Mongo/TxBehavior.cs b/src/BuildingBlocks/BulidingBlocks/Mongo/TxBehavior.cs index f5f232c..0c0ee82 100644 --- a/src/BuildingBlocks/BulidingBlocks/Mongo/TxBehavior.cs +++ b/src/BuildingBlocks/BulidingBlocks/Mongo/TxBehavior.cs @@ -23,17 +23,31 @@ public TxBehavior(IMongoDbContext dbContext, ILogger Handle(TRequest request, RequestHandlerDelegate next, CancellationToken - cancellationToken) + public async Task Handle( + TRequest request, + RequestHandlerDelegate next, + CancellationToken cancellationToken + ) { - if (request is not ITxRequest) return await next(); + if (request is not ITxRequest) + return await next(); - _logger.LogInformation("{Prefix} Handled command {MediatRRequest}", nameof(TxBehavior), - typeof(TRequest).FullName); - _logger.LogDebug("{Prefix} Handled command {MediatRRequest} with content {RequestContent}", - nameof(TxBehavior), typeof(TRequest).FullName, JsonSerializer.Serialize(request)); - _logger.LogInformation("{Prefix} Open the transaction for {MediatRRequest}", - nameof(TxBehavior), typeof(TRequest).FullName); + _logger.LogInformation( + "{Prefix} Handled command {MediatRRequest}", + nameof(TxBehavior), + typeof(TRequest).FullName + ); + _logger.LogDebug( + "{Prefix} Handled command {MediatRRequest} with content {RequestContent}", + nameof(TxBehavior), + typeof(TRequest).FullName, + JsonSerializer.Serialize(request) + ); + _logger.LogInformation( + "{Prefix} Open the transaction for {MediatRRequest}", + nameof(TxBehavior), + typeof(TRequest).FullName + ); try { @@ -41,8 +55,11 @@ public async Task Handle(TRequest request, RequestHandlerDelegate), typeof(TRequest).FullName); + _logger.LogInformation( + "{Prefix} Executed the {MediatRRequest} request", + nameof(TxBehavior), + typeof(TRequest).FullName + ); await _dbContext.CommitTransactionAsync(); @@ -54,4 +71,4 @@ public async Task Handle(TRequest request, RequestHandlerDelegate : IDisposable where TEntity : class, IAggregate +public interface IRepository : IDisposable + where TEntity : class, IAggregate { Task GetAsync(Guid id); Task GetAsync(Expression> predicate); Task> FindAsync(Expression> predicate); IAsyncEnumerable GetAllAsync(Expression> predicate = null); - public Task> BrowseAsync(Expression> predicate, - TQuery query) where TQuery : IPageList; + public Task> BrowseAsync(Expression> predicate, TQuery query) + where TQuery : IPageList; Task AddAsync(TEntity entity); Task UpdateAsync(TEntity entity); @@ -22,4 +23,4 @@ public Task> BrowseAsync(Expression> predicate); Task ExistsAsync(Expression> predicate); -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Persistence/IUnitOfWork.cs b/src/BuildingBlocks/BulidingBlocks/Persistence/IUnitOfWork.cs index 30e0035..1056063 100644 --- a/src/BuildingBlocks/BulidingBlocks/Persistence/IUnitOfWork.cs +++ b/src/BuildingBlocks/BulidingBlocks/Persistence/IUnitOfWork.cs @@ -6,4 +6,4 @@ namespace BuildingBlocks.Persistence; public interface IUnitOfWork : IDisposable { Task CommitAsync(); -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/ICircuitBreakerPolicyConfig.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/ICircuitBreakerPolicyConfig.cs index e7d583c..7cf6e1e 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/ICircuitBreakerPolicyConfig.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/ICircuitBreakerPolicyConfig.cs @@ -4,4 +4,4 @@ public interface ICircuitBreakerPolicyConfig { int RetryCount { get; set; } int BreakDuration { get; set; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/IRetryPolicyConfig.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/IRetryPolicyConfig.cs index b4a53e8..4ceeb2c 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/IRetryPolicyConfig.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/IRetryPolicyConfig.cs @@ -3,4 +3,4 @@ namespace BuildingBlocks.Resiliency.Configs; public interface IRetryPolicyConfig { int RetryCount { get; set; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/ITimeoutPolicy.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/ITimeoutPolicy.cs index 7bf1e1e..2ded260 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/ITimeoutPolicy.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/ITimeoutPolicy.cs @@ -3,4 +3,4 @@ namespace BuildingBlocks.Resiliency.Configs; public interface ITimeoutPolicy { public int TimeOutDuration { get; set; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/PolicyConfig.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/PolicyConfig.cs index 6527cf1..375b61e 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/PolicyConfig.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Configs/PolicyConfig.cs @@ -5,4 +5,4 @@ public class PolicyConfig : ICircuitBreakerPolicyConfig, IRetryPolicyConfig, ITi public int RetryCount { get; set; } public int BreakDuration { get; set; } public int TimeOutDuration { get; set; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Extensions.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Extensions.cs index b8a883e..fde3473 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Extensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Extensions.cs @@ -9,33 +9,39 @@ namespace BuildingBlocks.Resiliency; public static class Extensions { - public static IServiceCollection AddMediaterRetryPolicy(IServiceCollection services, - IReadOnlyList assemblies) + public static IServiceCollection AddMediaterRetryPolicy( + IServiceCollection services, + IReadOnlyList assemblies + ) { services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RetryBehavior<,>)); - services.Scan(scan => scan - .FromAssemblies(assemblies) - .AddClasses(classes => classes.AssignableTo(typeof(IRetryableRequest<,>))) - .UsingRegistrationStrategy(RegistrationStrategy.Skip) - .AsImplementedInterfaces() - .WithTransientLifetime()); + services.Scan(scan => + scan.FromAssemblies(assemblies) + .AddClasses(classes => classes.AssignableTo(typeof(IRetryableRequest<,>))) + .UsingRegistrationStrategy(RegistrationStrategy.Skip) + .AsImplementedInterfaces() + .WithTransientLifetime() + ); return services; } - public static IServiceCollection AddMediaterFallbackPolicy(IServiceCollection services, - IReadOnlyList assemblies) + public static IServiceCollection AddMediaterFallbackPolicy( + IServiceCollection services, + IReadOnlyList assemblies + ) { services.AddTransient(typeof(IPipelineBehavior<,>), typeof(FallbackBehavior<,>)); - services.Scan(scan => scan - .FromAssemblies(assemblies) - .AddClasses(classes => classes.AssignableTo(typeof(IFallbackHandler<,>))) - .UsingRegistrationStrategy(RegistrationStrategy.Skip) - .AsImplementedInterfaces() - .WithTransientLifetime()); + services.Scan(scan => + scan.FromAssemblies(assemblies) + .AddClasses(classes => classes.AssignableTo(typeof(IFallbackHandler<,>))) + .UsingRegistrationStrategy(RegistrationStrategy.Skip) + .AsImplementedInterfaces() + .WithTransientLifetime() + ); return services; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Fallback/FallbackBehavior.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Fallback/FallbackBehavior.cs index 00b25ef..8775865 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Fallback/FallbackBehavior.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Fallback/FallbackBehavior.cs @@ -19,15 +19,20 @@ public class FallbackBehavior : IPipelineBehavior> _fallbackHandlers; private readonly ILogger> _logger; - public FallbackBehavior(IEnumerable> fallbackHandlers, - ILogger> logger) + public FallbackBehavior( + IEnumerable> fallbackHandlers, + ILogger> logger + ) { _fallbackHandlers = fallbackHandlers; _logger = logger; } - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken - cancellationToken) + public async Task Handle( + TRequest request, + RequestHandlerDelegate next, + CancellationToken cancellationToken + ) { var fallbackHandler = _fallbackHandlers.FirstOrDefault(); if (fallbackHandler == null) @@ -38,14 +43,15 @@ public async Task Handle(TRequest request, RequestHandlerDelegate() .FallbackAsync(async cancellationToken => { - _logger.LogDebug("Initial handler failed. Falling back to `{FullName}@HandleFallback`", - fallbackHandler.GetType().FullName); - return await fallbackHandler.HandleFallbackAsync(request, cancellationToken) - .ConfigureAwait(false); + _logger.LogDebug( + "Initial handler failed. Falling back to `{FullName}@HandleFallback`", + fallbackHandler.GetType().FullName + ); + return await fallbackHandler.HandleFallbackAsync(request, cancellationToken).ConfigureAwait(false); }); var response = await fallbackPolicy.ExecuteAsync(async () => await next()); return response; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Fallback/IFallbackHandler.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Fallback/IFallbackHandler.cs index c6c37b2..608feca 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Fallback/IFallbackHandler.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Fallback/IFallbackHandler.cs @@ -4,7 +4,8 @@ namespace BuildingBlocks.Resiliency.Fallback; -public interface IFallbackHandler where TRequest : IRequest +public interface IFallbackHandler + where TRequest : IRequest { Task HandleFallbackAsync(TRequest request, CancellationToken cancellationToken); -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpCircuitBreakerPolicies.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpCircuitBreakerPolicies.cs index e592965..fc8190e 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpCircuitBreakerPolicies.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpCircuitBreakerPolicies.cs @@ -9,24 +9,39 @@ namespace BuildingBlocks.Resiliency; public static class HttpCircuitBreakerPolicies { - public static AsyncCircuitBreakerPolicy GetHttpCircuitBreakerPolicy(ILogger logger, - ICircuitBreakerPolicyConfig circuitBreakerPolicyConfig) + public static AsyncCircuitBreakerPolicy GetHttpCircuitBreakerPolicy( + ILogger logger, + ICircuitBreakerPolicyConfig circuitBreakerPolicyConfig + ) { - return HttpPolicyBuilders.GetBaseBuilder() - .CircuitBreakerAsync(circuitBreakerPolicyConfig.RetryCount + 1, + return HttpPolicyBuilders + .GetBaseBuilder() + .CircuitBreakerAsync( + circuitBreakerPolicyConfig.RetryCount + 1, TimeSpan.FromSeconds(circuitBreakerPolicyConfig.BreakDuration), (result, breakDuration) => { OnHttpBreak(result, breakDuration, circuitBreakerPolicyConfig.RetryCount, logger); }, - () => { OnHttpReset(logger); }); + () => + { + OnHttpReset(logger); + } + ); } - public static void OnHttpBreak(DelegateResult result, TimeSpan breakDuration, - int retryCount, ILogger logger) + public static void OnHttpBreak( + DelegateResult result, + TimeSpan breakDuration, + int retryCount, + ILogger logger + ) { - logger.LogWarning("Service shutdown during {breakDuration} after {DefaultRetryCount} failed retries.", - breakDuration, retryCount); + logger.LogWarning( + "Service shutdown during {breakDuration} after {DefaultRetryCount} failed retries.", + breakDuration, + retryCount + ); throw new BrokenCircuitException("Service inoperative. Please try again later"); } @@ -34,4 +49,4 @@ public static void OnHttpReset(ILogger logger) { logger.LogInformation("Service restarted."); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpClientBuilderExtensions.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpClientBuilderExtensions.cs index bcfc7fe..5d0345b 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpClientBuilderExtensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpClientBuilderExtensions.cs @@ -7,42 +7,56 @@ namespace BuildingBlocks.Resiliency; public static class HttpClientBuilderExtensions { - public static IHttpClientBuilder AddCustomPolicyHandlers(this IHttpClientBuilder httpClientBuilder, - IConfiguration configuration, string policySectionName) + public static IHttpClientBuilder AddCustomPolicyHandlers( + this IHttpClientBuilder httpClientBuilder, + IConfiguration configuration, + string policySectionName + ) { var policyConfig = new PolicyConfig(); configuration.Bind(policySectionName, policyConfig); - var circuitBreakerPolicyConfig = (ICircuitBreakerPolicyConfig) policyConfig; - var retryPolicyConfig = (IRetryPolicyConfig) policyConfig; + var circuitBreakerPolicyConfig = (ICircuitBreakerPolicyConfig)policyConfig; + var retryPolicyConfig = (IRetryPolicyConfig)policyConfig; - return httpClientBuilder.AddRetryPolicyHandler(retryPolicyConfig) + return httpClientBuilder + .AddRetryPolicyHandler(retryPolicyConfig) .AddCircuitBreakerHandler(circuitBreakerPolicyConfig); } - public static IHttpClientBuilder AddRetryPolicyHandler(this IHttpClientBuilder httpClientBuilder, - IRetryPolicyConfig retryPolicyConfig) + public static IHttpClientBuilder AddRetryPolicyHandler( + this IHttpClientBuilder httpClientBuilder, + IRetryPolicyConfig retryPolicyConfig + ) { //https://stackoverflow.com/questions/53604295/logging-polly-wait-and-retry-policy-asp-net-core-2-1 - return httpClientBuilder.AddPolicyHandler((sp, _) => - { - var loggerFactory = sp.GetRequiredService(); - var retryLogger = loggerFactory.CreateLogger("PollyHttpRetryPoliciesLogger"); - - return HttpRetryPolicies.GetHttpRetryPolicy(retryLogger, retryPolicyConfig); - }); + return httpClientBuilder.AddPolicyHandler( + (sp, _) => + { + var loggerFactory = sp.GetRequiredService(); + var retryLogger = loggerFactory.CreateLogger("PollyHttpRetryPoliciesLogger"); + + return HttpRetryPolicies.GetHttpRetryPolicy(retryLogger, retryPolicyConfig); + } + ); } - public static IHttpClientBuilder AddCircuitBreakerHandler(this IHttpClientBuilder httpClientBuilder, - ICircuitBreakerPolicyConfig circuitBreakerPolicyConfig) + public static IHttpClientBuilder AddCircuitBreakerHandler( + this IHttpClientBuilder httpClientBuilder, + ICircuitBreakerPolicyConfig circuitBreakerPolicyConfig + ) { - return httpClientBuilder.AddPolicyHandler((sp, _) => - { - var loggerFactory = sp.GetRequiredService(); - var circuitBreakerLogger = loggerFactory.CreateLogger("PollyHttpCircuitBreakerPoliciesLogger"); - - return HttpCircuitBreakerPolicies.GetHttpCircuitBreakerPolicy(circuitBreakerLogger, - circuitBreakerPolicyConfig); - }); + return httpClientBuilder.AddPolicyHandler( + (sp, _) => + { + var loggerFactory = sp.GetRequiredService(); + var circuitBreakerLogger = loggerFactory.CreateLogger("PollyHttpCircuitBreakerPoliciesLogger"); + + return HttpCircuitBreakerPolicies.GetHttpCircuitBreakerPolicy( + circuitBreakerLogger, + circuitBreakerPolicyConfig + ); + } + ); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpPolicyBuilders.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpPolicyBuilders.cs index cc64bd5..319cb4b 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpPolicyBuilders.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpPolicyBuilders.cs @@ -10,4 +10,4 @@ public static PolicyBuilder GetBaseBuilder() { return HttpPolicyExtensions.HandleTransientHttpError(); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpRetryPolicies.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpRetryPolicies.cs index 8a93059..127db6d 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpRetryPolicies.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/HttpRetryPolicies.cs @@ -9,33 +9,48 @@ namespace BuildingBlocks.Resiliency; public static class HttpRetryPolicies { - public static AsyncRetryPolicy GetHttpRetryPolicy(ILogger logger, - IRetryPolicyConfig retryPolicyConfig) + public static AsyncRetryPolicy GetHttpRetryPolicy( + ILogger logger, + IRetryPolicyConfig retryPolicyConfig + ) { - return HttpPolicyBuilders.GetBaseBuilder() - .WaitAndRetryAsync(retryPolicyConfig.RetryCount, + return HttpPolicyBuilders + .GetBaseBuilder() + .WaitAndRetryAsync( + retryPolicyConfig.RetryCount, ComputeDuration, (result, timeSpan, retryCount, context) => { OnHttpRetry(result, timeSpan, retryCount, context, logger); - }); + } + ); } - private static void OnHttpRetry(DelegateResult result, TimeSpan timeSpan, int - retryCount, Context context, ILogger logger) + private static void OnHttpRetry( + DelegateResult result, + TimeSpan timeSpan, + int retryCount, + Context context, + ILogger logger + ) { if (result.Result != null) logger.LogWarning( "Request failed with {StatusCode}. Waiting {timeSpan} before next retry. Retry attempt {retryCount}", - result.Result.StatusCode, timeSpan, retryCount); + result.Result.StatusCode, + timeSpan, + retryCount + ); else logger.LogWarning( "Request failed because network failure. Waiting {timeSpan} before next retry. Retry attempt {retryCount}", - timeSpan, retryCount); + timeSpan, + retryCount + ); } private static TimeSpan ComputeDuration(int input) { return TimeSpan.FromSeconds(Math.Pow(2, input)) + TimeSpan.FromMilliseconds(new Random().Next(0, 100)); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/IRetryableRequest.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/IRetryableRequest.cs index 92e6d3d..7235962 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/IRetryableRequest.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/IRetryableRequest.cs @@ -2,10 +2,11 @@ namespace BuildingBlocks.Resiliency; -public interface IRetryableRequest where TRequest : IRequest +public interface IRetryableRequest + where TRequest : IRequest { int RetryAttempts => 1; int RetryDelay => 250; bool RetryWithExponentialBackoff => false; int ExceptionsAllowedBeforeCircuitTrip => 1; -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/RetryBehavior.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/RetryBehavior.cs index 3d0e5a7..1481936 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/RetryBehavior.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/RetryBehavior.cs @@ -15,15 +15,20 @@ public class RetryBehavior : IPipelineBehavior> _logger; private readonly IEnumerable> _retryHandlers; - public RetryBehavior(IEnumerable> retryHandlers, - ILogger> logger) + public RetryBehavior( + IEnumerable> retryHandlers, + ILogger> logger + ) { _retryHandlers = retryHandlers; _logger = logger; } - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken - cancellationToken) + public async Task Handle( + TRequest request, + RequestHandlerDelegate next, + CancellationToken cancellationToken + ) { var retryHandler = _retryHandlers.FirstOrDefault(); //var retryAttr = typeof(TRequest).GetCustomAttribute(); @@ -34,25 +39,34 @@ public async Task Handle(TRequest request, RequestHandlerDelegate .Handle() - .CircuitBreakerAsync(retryHandler.ExceptionsAllowedBeforeCircuitTrip, TimeSpan.FromMilliseconds(5000), - (exception, things) => { _logger.LogDebug("Circuit Tripped!"); }, - () => { }); + .CircuitBreakerAsync( + retryHandler.ExceptionsAllowedBeforeCircuitTrip, + TimeSpan.FromMilliseconds(5000), + (exception, things) => + { + _logger.LogDebug("Circuit Tripped!"); + }, + () => { } + ); var retryPolicy = Policy .Handle() - .WaitAndRetryAsync(retryHandler.RetryAttempts, retryAttempt => - { - var retryDelay = retryHandler.RetryWithExponentialBackoff - ? TimeSpan.FromMilliseconds(Math.Pow(2, retryAttempt) * retryHandler.RetryDelay) - : TimeSpan.FromMilliseconds(retryHandler.RetryDelay); + .WaitAndRetryAsync( + retryHandler.RetryAttempts, + retryAttempt => + { + var retryDelay = retryHandler.RetryWithExponentialBackoff + ? TimeSpan.FromMilliseconds(Math.Pow(2, retryAttempt) * retryHandler.RetryDelay) + : TimeSpan.FromMilliseconds(retryHandler.RetryDelay); - _logger.LogDebug("Retrying, waiting {RetryDelay}...", retryDelay); + _logger.LogDebug("Retrying, waiting {RetryDelay}...", retryDelay); - return retryDelay; - }); + return retryDelay; + } + ); var response = await retryPolicy.ExecuteAsync(async () => await next()); return response; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/RetryPolicyAttribute.cs b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/RetryPolicyAttribute.cs index 987b9de..c0fd808 100644 --- a/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/RetryPolicyAttribute.cs +++ b/src/BuildingBlocks/BulidingBlocks/Resiliency/Retry/RetryPolicyAttribute.cs @@ -24,7 +24,8 @@ public int RetryCount get => _retryCount; set { - if (value < 1) throw new ArgumentException("Retry count must be higher than 1.", nameof(value)); + if (value < 1) + throw new ArgumentException("Retry count must be higher than 1.", nameof(value)); _retryCount = value; } @@ -40,9 +41,10 @@ public int SleepDuration get => _sleepDuration; set { - if (value < 1) throw new ArgumentException("Sleep duration must be higher than 1ms.", nameof(value)); + if (value < 1) + throw new ArgumentException("Sleep duration must be higher than 1ms.", nameof(value)); _sleepDuration = value; } } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKey.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKey.cs index 4fa1045..e43fcf3 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKey.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKey.cs @@ -19,4 +19,4 @@ public ApiKey(int id, string owner, string key, DateTime created, IReadOnlyColle public string Key { get; } public DateTime Created { get; } public IReadOnlyCollection Roles { get; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyAuthenticationHandler.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyAuthenticationHandler.cs index 6209f18..f4947ca 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyAuthenticationHandler.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyAuthenticationHandler.cs @@ -25,7 +25,9 @@ public ApiKeyAuthenticationHandler( ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, - IGetApiKeyQuery getApiKeyQuery) : base(options, logger, encoder, clock) + IGetApiKeyQuery getApiKeyQuery + ) + : base(options, logger, encoder, clock) { _getApiKeyQuery = getApiKeyQuery ?? throw new ArgumentNullException(nameof(getApiKeyQuery)); } @@ -35,29 +37,29 @@ protected override async Task HandleAuthenticateAsync() StringValues apiKeyQueryValues = ""; StringValues apiKeyHeaderValues = ""; - if (Request.Headers.TryGetValue(ApiKeyConstants.HeaderName, out apiKeyHeaderValues) == false && - Request.Query.TryGetValue(ApiKeyConstants.HeaderName, out apiKeyQueryValues) == false) + if ( + Request.Headers.TryGetValue(ApiKeyConstants.HeaderName, out apiKeyHeaderValues) == false + && Request.Query.TryGetValue(ApiKeyConstants.HeaderName, out apiKeyQueryValues) == false + ) return AuthenticateResult.NoResult(); var providedApiKey = apiKeyHeaderValues.FirstOrDefault() ?? apiKeyQueryValues.FirstOrDefault(); - if ((apiKeyHeaderValues.Count == 0 && apiKeyQueryValues.Count == 0) || string.IsNullOrWhiteSpace - (providedApiKey)) + if ( + (apiKeyHeaderValues.Count == 0 && apiKeyQueryValues.Count == 0) || string.IsNullOrWhiteSpace(providedApiKey) + ) return AuthenticateResult.NoResult(); var existingApiKey = await _getApiKeyQuery.ExecuteAsync(providedApiKey); if (existingApiKey != null) { - var claims = new List - { - new(ClaimTypes.Name, existingApiKey.Owner) - }; + var claims = new List { new(ClaimTypes.Name, existingApiKey.Owner) }; claims.AddRange(existingApiKey.Roles.Select(role => new Claim(ClaimTypes.Role, role))); var identity = new ClaimsIdentity(claims, Options.AuthenticationType); - var identities = new List {identity}; + var identities = new List { identity }; var principal = new ClaimsPrincipal(identities); var ticket = new AuthenticationTicket(principal, Options.Scheme); @@ -87,10 +89,11 @@ protected override async Task HandleForbiddenAsync(AuthenticationProperties prop public static class DefaultJsonSerializerOptions { - public static JsonSerializerOptions Options => new() - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - }; + public static JsonSerializerOptions Options => + new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyAuthenticationOptions.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyAuthenticationOptions.cs index 1bc3eea..84f3c24 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyAuthenticationOptions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyAuthenticationOptions.cs @@ -7,4 +7,4 @@ public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions public const string DefaultScheme = "ApiKey"; public string AuthenticationType = DefaultScheme; public string Scheme => DefaultScheme; -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyConstants.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyConstants.cs index 8fcb829..df4b908 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyConstants.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/ApiKeyConstants.cs @@ -3,4 +3,4 @@ namespace BuildingBlocks.Security.ApiKey; public class ApiKeyConstants { public const string HeaderName = "X-Api-Key"; -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/AuthenticationBuilderExtensions.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/AuthenticationBuilderExtensions.cs index 06ea6cf..ddbb7de 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/AuthenticationBuilderExtensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/AuthenticationBuilderExtensions.cs @@ -5,10 +5,14 @@ namespace BuildingBlocks.Security.ApiKey; public static class AuthenticationBuilderExtensions { - public static AuthenticationBuilder AddApiKeySupport(this AuthenticationBuilder authenticationBuilder, - Action options) + public static AuthenticationBuilder AddApiKeySupport( + this AuthenticationBuilder authenticationBuilder, + Action options + ) { return authenticationBuilder.AddScheme( - ApiKeyAuthenticationOptions.DefaultScheme, options); + ApiKeyAuthenticationOptions.DefaultScheme, + options + ); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyAdminsAuthorizationHandler.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyAdminsAuthorizationHandler.cs index 23cc72a..97e3576 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyAdminsAuthorizationHandler.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyAdminsAuthorizationHandler.cs @@ -5,11 +5,14 @@ namespace BuildingBlocks.Security.ApiKey.Authorization; public class OnlyAdminsAuthorizationHandler : AuthorizationHandler { - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, - OnlyAdminsRequirement requirement) + protected override Task HandleRequirementAsync( + AuthorizationHandlerContext context, + OnlyAdminsRequirement requirement + ) { - if (context.User.IsInRole(Roles.Admin)) context.Succeed(requirement); + if (context.User.IsInRole(Roles.Admin)) + context.Succeed(requirement); return Task.CompletedTask; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyAdminsRequirement.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyAdminsRequirement.cs index 19eda86..34d9aae 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyAdminsRequirement.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyAdminsRequirement.cs @@ -2,6 +2,4 @@ namespace BuildingBlocks.Security.ApiKey.Authorization; -public class OnlyAdminsRequirement : IAuthorizationRequirement -{ -} \ No newline at end of file +public class OnlyAdminsRequirement : IAuthorizationRequirement { } diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyCustomersAuthorizationHandler.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyCustomersAuthorizationHandler.cs index f5d6d30..17a0939 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyCustomersAuthorizationHandler.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyCustomersAuthorizationHandler.cs @@ -5,11 +5,14 @@ namespace BuildingBlocks.Security.ApiKey.Authorization; public class OnlyCustomersAuthorizationHandler : AuthorizationHandler { - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, - OnlyCustomersRequirement requirement) + protected override Task HandleRequirementAsync( + AuthorizationHandlerContext context, + OnlyCustomersRequirement requirement + ) { - if (context.User.IsInRole(Roles.Customer)) context.Succeed(requirement); + if (context.User.IsInRole(Roles.Customer)) + context.Succeed(requirement); return Task.CompletedTask; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyCustomersRequirement.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyCustomersRequirement.cs index e1b9e5e..1bc0a0e 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyCustomersRequirement.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyCustomersRequirement.cs @@ -2,6 +2,4 @@ namespace BuildingBlocks.Security.ApiKey.Authorization; -public class OnlyCustomersRequirement : IAuthorizationRequirement -{ -} \ No newline at end of file +public class OnlyCustomersRequirement : IAuthorizationRequirement { } diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyThirdPartiesAuthorizationHandler.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyThirdPartiesAuthorizationHandler.cs index 7e03442..8436aba 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyThirdPartiesAuthorizationHandler.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyThirdPartiesAuthorizationHandler.cs @@ -5,11 +5,14 @@ namespace BuildingBlocks.Security.ApiKey.Authorization; public class OnlyThirdPartiesAuthorizationHandler : AuthorizationHandler { - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, - OnlyThirdPartiesRequirement requirement) + protected override Task HandleRequirementAsync( + AuthorizationHandlerContext context, + OnlyThirdPartiesRequirement requirement + ) { - if (context.User.IsInRole(Roles.ThirdParty)) context.Succeed(requirement); + if (context.User.IsInRole(Roles.ThirdParty)) + context.Succeed(requirement); return Task.CompletedTask; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyThirdPartiesRequirement.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyThirdPartiesRequirement.cs index 0eacb95..a3d6865 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyThirdPartiesRequirement.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/OnlyThirdPartiesRequirement.cs @@ -2,6 +2,4 @@ namespace BuildingBlocks.Security.ApiKey.Authorization; -public class OnlyThirdPartiesRequirement : IAuthorizationRequirement -{ -} \ No newline at end of file +public class OnlyThirdPartiesRequirement : IAuthorizationRequirement { } diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/Policies.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/Policies.cs index 0c2bea9..0937111 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/Policies.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/Policies.cs @@ -5,4 +5,4 @@ public static class Policies public const string OnlyCustomers = nameof(OnlyCustomers); public const string OnlyAdmins = nameof(OnlyAdmins); public const string OnlyThirdParties = nameof(OnlyThirdParties); -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/Roles.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/Roles.cs index d20a724..86b63bf 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/Roles.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/Authorization/Roles.cs @@ -5,4 +5,4 @@ public static class Roles public const string Customer = "Customer"; public const string Admin = "Admin"; public const string ThirdParty = "Third Party"; -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/IGetApiKeyQuery.cs b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/IGetApiKeyQuery.cs index a4c3e30..1cb1f67 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/IGetApiKeyQuery.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ApiKey/IGetApiKeyQuery.cs @@ -5,4 +5,4 @@ namespace BuildingBlocks.Security.ApiKey; public interface IGetApiKeyQuery { Task ExecuteAsync(string providedApiKey); -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/ForbiddenProblemDetails.cs b/src/BuildingBlocks/BulidingBlocks/Security/ForbiddenProblemDetails.cs index 9d13413..957b31b 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/ForbiddenProblemDetails.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/ForbiddenProblemDetails.cs @@ -11,4 +11,4 @@ public ForbiddenProblemDetails(string details = null) Status = 403; Type = "https://httpstatuses.com/403"; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Security/UnauthorizedProblemDetails.cs b/src/BuildingBlocks/BulidingBlocks/Security/UnauthorizedProblemDetails.cs index a1605da..9ce64ef 100644 --- a/src/BuildingBlocks/BulidingBlocks/Security/UnauthorizedProblemDetails.cs +++ b/src/BuildingBlocks/BulidingBlocks/Security/UnauthorizedProblemDetails.cs @@ -11,4 +11,4 @@ public UnauthorizedProblemDetails(string details = null) Status = 401; Type = "https://httpstatuses.com/401"; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Swagger/ConfigureSwaggerOptions.cs b/src/BuildingBlocks/BulidingBlocks/Swagger/ConfigureSwaggerOptions.cs index 92a478c..257d2da 100644 --- a/src/BuildingBlocks/BulidingBlocks/Swagger/ConfigureSwaggerOptions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Swagger/ConfigureSwaggerOptions.cs @@ -9,7 +9,6 @@ namespace BuildingBlocks.Swagger; - public class ConfigureSwaggerOptions : IConfigureOptions { private readonly IApiVersionDescriptionProvider provider; @@ -44,8 +43,8 @@ private OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description) Version = description.ApiVersion.ToString(), Title = _options?.Title ?? "APIs", Description = "An application with Swagger, Swashbuckle, and API versioning.", - Contact = new OpenApiContact {Name = "", Email = ""}, - License = new OpenApiLicense {Name = "MIT", Url = new Uri("https://opensource.org/licenses/MIT")} + Contact = new OpenApiContact { Name = "", Email = "" }, + License = new OpenApiLicense { Name = "MIT", Url = new Uri("https://opensource.org/licenses/MIT") } }; if (description.IsDeprecated) @@ -57,9 +56,7 @@ private OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description) { if (policy.Date is DateTimeOffset when) { - text.Append(" The API will be sunset on ") - .Append(when.Date.ToShortDateString()) - .Append('.'); + text.Append(" The API will be sunset on ").Append(when.Date.ToShortDateString()).Append('.'); } if (policy.HasLinks) diff --git a/src/BuildingBlocks/BulidingBlocks/Swagger/ServiceCollectionExtensions.cs b/src/BuildingBlocks/BulidingBlocks/Swagger/ServiceCollectionExtensions.cs index 91c8d76..6e4acd5 100644 --- a/src/BuildingBlocks/BulidingBlocks/Swagger/ServiceCollectionExtensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Swagger/ServiceCollectionExtensions.cs @@ -17,64 +17,64 @@ public static class ServiceCollectionExtensions public static IServiceCollection AddCustomSwagger( this IServiceCollection services, IConfiguration configuration, - Assembly assembly) + Assembly assembly + ) { // https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/openapi services.AddEndpointsApiExplorer(); services.AddTransient, ConfigureSwaggerOptions>(); - services.AddOptions().Bind(configuration.GetSection(nameof(SwaggerOptions))) + services + .AddOptions() + .Bind(configuration.GetSection(nameof(SwaggerOptions))) .ValidateDataAnnotations(); - services.AddSwaggerGen( - options => - { - options.OperationFilter(); - //options.OperationFilter(); + services.AddSwaggerGen(options => + { + options.OperationFilter(); + //options.OperationFilter(); - var xmlFile = XmlCommentsFilePath(assembly); - if (File.Exists(xmlFile)) options.IncludeXmlComments(xmlFile); + var xmlFile = XmlCommentsFilePath(assembly); + if (File.Exists(xmlFile)) + options.IncludeXmlComments(xmlFile); - // https://github.com/domaindrivendev/Swashbuckle.AspNetCore#add-security-definitions-and-requirements - // https://swagger.io/docs/specification/authentication/ - // https://medium.com/@niteshsinghal85/assign-specific-authorization-scheme-to-endpoint-in-swagger-ui-in-net-core-cd84d2a2ebd7 - var bearerScheme = new OpenApiSecurityScheme() - { - Type = SecuritySchemeType.Http, - Name = JwtBearerDefaults.AuthenticationScheme, - Scheme = JwtBearerDefaults.AuthenticationScheme, - Reference = new() - { - Type = ReferenceType.SecurityScheme, Id = JwtBearerDefaults.AuthenticationScheme - } - }; - - var apiKeyScheme = new OpenApiSecurityScheme - { - Description = "Api key needed to access the endpoints. X-Api-Key: My_API_Key", - In = ParameterLocation.Header, - Name = "X-Api-Key", - Scheme = "ApiKey", - Type = SecuritySchemeType.ApiKey, - Reference = new() - { - Type = ReferenceType.SecurityScheme, Id = "X-Api-Key" - } - }; - - options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, bearerScheme); - options.AddSecurityDefinition("X-Api-Key", apiKeyScheme); - - options.AddSecurityRequirement(new OpenApiSecurityRequirement + // https://github.com/domaindrivendev/Swashbuckle.AspNetCore#add-security-definitions-and-requirements + // https://swagger.io/docs/specification/authentication/ + // https://medium.com/@niteshsinghal85/assign-specific-authorization-scheme-to-endpoint-in-swagger-ui-in-net-core-cd84d2a2ebd7 + var bearerScheme = new OpenApiSecurityScheme() + { + Type = SecuritySchemeType.Http, + Name = JwtBearerDefaults.AuthenticationScheme, + Scheme = JwtBearerDefaults.AuthenticationScheme, + Reference = new() { Type = ReferenceType.SecurityScheme, Id = JwtBearerDefaults.AuthenticationScheme } + }; + + var apiKeyScheme = new OpenApiSecurityScheme + { + Description = "Api key needed to access the endpoints. X-Api-Key: My_API_Key", + In = ParameterLocation.Header, + Name = "X-Api-Key", + Scheme = "ApiKey", + Type = SecuritySchemeType.ApiKey, + Reference = new() { Type = ReferenceType.SecurityScheme, Id = "X-Api-Key" } + }; + + options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, bearerScheme); + options.AddSecurityDefinition("X-Api-Key", apiKeyScheme); + + options.AddSecurityRequirement( + new OpenApiSecurityRequirement { - {bearerScheme, Array.Empty()}, {apiKeyScheme, Array.Empty()} - }); + { bearerScheme, Array.Empty() }, + { apiKeyScheme, Array.Empty() } + } + ); - options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); + options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); - // Enables Swagger annotations (SwaggerOperationAttribute, SwaggerParameterAttribute etc.) - options.EnableAnnotations(); - }); + // Enables Swagger annotations (SwaggerOperationAttribute, SwaggerParameterAttribute etc.) + options.EnableAnnotations(); + }); static string XmlCommentsFilePath(Assembly assembly) { @@ -89,20 +89,19 @@ static string XmlCommentsFilePath(Assembly assembly) public static WebApplication UseCustomSwagger(this WebApplication app) { app.UseSwagger(); - app.UseSwaggerUI( - options => - { - var descriptions = app.DescribeApiVersions(); + app.UseSwaggerUI(options => + { + var descriptions = app.DescribeApiVersions(); - // build a swagger endpoint for each discovered API version - foreach (var description in descriptions) - { - var url = $"/swagger/{description.GroupName}/swagger.json"; - var name = description.GroupName.ToUpperInvariant(); - options.SwaggerEndpoint(url, name); - } - }); + // build a swagger endpoint for each discovered API version + foreach (var description in descriptions) + { + var url = $"/swagger/{description.GroupName}/swagger.json"; + var name = description.GroupName.ToUpperInvariant(); + options.SwaggerEndpoint(url, name); + } + }); return app; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Swagger/SwaggerDefaultValues.cs b/src/BuildingBlocks/BulidingBlocks/Swagger/SwaggerDefaultValues.cs index 53bf26d..d66e004 100644 --- a/src/BuildingBlocks/BulidingBlocks/Swagger/SwaggerDefaultValues.cs +++ b/src/BuildingBlocks/BulidingBlocks/Swagger/SwaggerDefaultValues.cs @@ -49,10 +49,12 @@ public void Apply(OpenApiOperation operation, OperationFilterContext context) parameter.Description = description.ModelMetadata?.Description; } - if (parameter.Schema.Default == null && - description.DefaultValue != null && - description.DefaultValue is not DBNull && - description.ModelMetadata is ModelMetadata modelMetadata) + if ( + parameter.Schema.Default == null + && description.DefaultValue != null + && description.DefaultValue is not DBNull + && description.ModelMetadata is ModelMetadata modelMetadata + ) { // REF: https://github.com/Microsoft/aspnet-api-versioning/issues/429#issuecomment-605402330 var json = JsonSerializer.Serialize(description.DefaultValue, modelMetadata.ModelType); diff --git a/src/BuildingBlocks/BulidingBlocks/Swagger/SwaggerOptions.cs b/src/BuildingBlocks/BulidingBlocks/Swagger/SwaggerOptions.cs index cdfa95d..e434d0a 100644 --- a/src/BuildingBlocks/BulidingBlocks/Swagger/SwaggerOptions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Swagger/SwaggerOptions.cs @@ -5,4 +5,4 @@ public class SwaggerOptions public string Title { get; set; } public string Name { get; set; } public string Version { get; set; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Utils/EnumExtensions.cs b/src/BuildingBlocks/BulidingBlocks/Utils/EnumExtensions.cs index 0150aa3..1bb18ef 100644 --- a/src/BuildingBlocks/BulidingBlocks/Utils/EnumExtensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Utils/EnumExtensions.cs @@ -8,14 +8,13 @@ public static class EnumExtensions { // This extension method is broken out so you can use a similar pattern with // other MetaData elements in the future. This is your base method for each. - public static T GetAttribute(this Enum value) where T : Attribute + public static T GetAttribute(this Enum value) + where T : Attribute { var type = value.GetType(); var memberInfo = type.GetMember(value.ToString()); var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false); - return attributes.Length > 0 - ? (T) attributes[0] - : null; + return attributes.Length > 0 ? (T)attributes[0] : null; } // This method creates a specific call to the above method, requesting the @@ -25,4 +24,4 @@ public static string ToName(this Enum value) var attribute = value.GetAttribute(); return attribute == null ? value.ToString() : attribute.Description; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Utils/EnumerableExtensions.cs b/src/BuildingBlocks/BulidingBlocks/Utils/EnumerableExtensions.cs index 42fe1a8..fac1f4e 100644 --- a/src/BuildingBlocks/BulidingBlocks/Utils/EnumerableExtensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Utils/EnumerableExtensions.cs @@ -9,4 +9,4 @@ public static class EnumerableExtensions { return source.Select((item, index) => (item, index)); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Utils/ObjectExtensions.cs b/src/BuildingBlocks/BulidingBlocks/Utils/ObjectExtensions.cs index 88a98c7..9bd84df 100644 --- a/src/BuildingBlocks/BulidingBlocks/Utils/ObjectExtensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Utils/ObjectExtensions.cs @@ -7,10 +7,11 @@ public static class ObjectExtensions { public static string GetQueryString(this object obj) { - var properties = from p in obj.GetType().GetProperties() + var properties = + from p in obj.GetType().GetProperties() where p.GetValue(obj, null) != null select p.Name + "=" + HttpUtility.UrlEncode(p.GetValue(obj, null).ToString()); return string.Join("&", properties.ToArray()); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Utils/ReflectionHelpers.cs b/src/BuildingBlocks/BulidingBlocks/Utils/ReflectionHelpers.cs index 0d1e6e2..6c3be8b 100644 --- a/src/BuildingBlocks/BulidingBlocks/Utils/ReflectionHelpers.cs +++ b/src/BuildingBlocks/BulidingBlocks/Utils/ReflectionHelpers.cs @@ -29,19 +29,22 @@ public static string PrettyPrint(this Type type) { return t.Name; } - }); + } + ); } private static string PrettyPrintRecursive(Type type, int depth) { - if (depth > 3) return type.Name; + if (depth > 3) + return type.Name; var nameParts = type.Name.Split('`'); - if (nameParts.Length == 1) return nameParts[0]; + if (nameParts.Length == 1) + return nameParts[0]; var genericArguments = type.GetTypeInfo().GetGenericArguments(); return !type.IsConstructedGenericType ? $"{nameParts[0]}<{new string(',', genericArguments.Length - 1)}>" : $"{nameParts[0]}<{string.Join(",", genericArguments.Select(t => PrettyPrintRecursive(t, depth + 1)))}>"; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Validation/Extensions.cs b/src/BuildingBlocks/BulidingBlocks/Validation/Extensions.cs index 67883ea..35f5371 100644 --- a/src/BuildingBlocks/BulidingBlocks/Validation/Extensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Validation/Extensions.cs @@ -19,7 +19,8 @@ private static ValidationResultModel ToValidationResultModel(this ValidationResu public static async Task HandleValidationAsync(this IValidator validator, TRequest request) { var validationResult = await validator.ValidateAsync(request); - if (!validationResult.IsValid) throw new ValidationException(validationResult.ToValidationResultModel()); + if (!validationResult.IsValid) + throw new ValidationException(validationResult.ToValidationResultModel()); } public static IServiceCollection AddCustomValidators(this IServiceCollection services, Assembly assembly) @@ -27,4 +28,4 @@ public static IServiceCollection AddCustomValidators(this IServiceCollection ser //https://codewithmukesh.com/blog/mediatr-pipeline-behaviour/ return services.AddValidatorsFromAssembly(assembly); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Validation/RequestValidationBehavior.cs b/src/BuildingBlocks/BulidingBlocks/Validation/RequestValidationBehavior.cs index 5ee24d4..02acc50 100644 --- a/src/BuildingBlocks/BulidingBlocks/Validation/RequestValidationBehavior.cs +++ b/src/BuildingBlocks/BulidingBlocks/Validation/RequestValidationBehavior.cs @@ -17,16 +17,21 @@ public class RequestValidationBehavior : IPipelineBehavior< private readonly IServiceProvider _serviceProvider; private IValidator _validator; - public RequestValidationBehavior(IServiceProvider serviceProvider, - ILogger> logger) + public RequestValidationBehavior( + IServiceProvider serviceProvider, + ILogger> logger + ) { _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); ; _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken - cancellationToken) + public async Task Handle( + TRequest request, + RequestHandlerDelegate next, + CancellationToken cancellationToken + ) { _validator = _serviceProvider.GetService>(); if (_validator is null) @@ -34,11 +39,16 @@ public async Task Handle(TRequest request, RequestHandlerDelegate), typeof(TRequest).Name, - typeof(TResponse).Name); + nameof(RequestValidationBehavior), + typeof(TRequest).Name, + typeof(TResponse).Name + ); - _logger.LogDebug("Handling {FullName} with content {Serialize}", typeof(TRequest).FullName, - JsonSerializer.Serialize(request)); + _logger.LogDebug( + "Handling {FullName} with content {Serialize}", + typeof(TRequest).FullName, + JsonSerializer.Serialize(request) + ); await _validator.HandleValidationAsync(request); @@ -47,4 +57,4 @@ public async Task Handle(TRequest request, RequestHandlerDelegate new ValidationError(error.PropertyName, error.ErrorMessage)) + Errors = validationResult + .Errors.Select(error => new ValidationError(error.PropertyName, error.ErrorMessage)) .ToList(); } - public int StatusCode { get; set; } = (int) HttpStatusCode.BadRequest; + public int StatusCode { get; set; } = (int)HttpStatusCode.BadRequest; public string Message { get; set; } = "Validation Failed."; public List Errors { get; } @@ -24,4 +24,4 @@ public override string ToString() { return JsonSerializer.Serialize(this); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Web/ApplicationBuilderExtensions.cs b/src/BuildingBlocks/BulidingBlocks/Web/ApplicationBuilderExtensions.cs index a4eabe8..13392b5 100644 --- a/src/BuildingBlocks/BulidingBlocks/Web/ApplicationBuilderExtensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Web/ApplicationBuilderExtensions.cs @@ -16,29 +16,38 @@ public static class ApplicationBuilderExtensions { public static IApplicationBuilder UseCustomHealthCheck(this IApplicationBuilder app) { - app.UseHealthChecks("/healthz", new HealthCheckOptions - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse, - ResultStatusCodes = + app.UseHealthChecks( + "/healthz", + new HealthCheckOptions { - [HealthStatus.Healthy] = StatusCodes.Status200OK, - [HealthStatus.Degraded] = StatusCodes.Status500InternalServerError, - [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse, + ResultStatusCodes = + { + [HealthStatus.Healthy] = StatusCodes.Status200OK, + [HealthStatus.Degraded] = StatusCodes.Status500InternalServerError, + [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable + } } - }) - .UseHealthChecks("/health", new HealthCheckOptions - { - Predicate = check => !check.Tags.Contains("services"), - AllowCachingResponses = false, - ResponseWriter = WriteResponseAsync - }) - .UseHealthChecks("/health/ready", new HealthCheckOptions - { - Predicate = _ => true, - AllowCachingResponses = false, - ResponseWriter = WriteResponseAsync - }) + ) + .UseHealthChecks( + "/health", + new HealthCheckOptions + { + Predicate = check => !check.Tags.Contains("services"), + AllowCachingResponses = false, + ResponseWriter = WriteResponseAsync + } + ) + .UseHealthChecks( + "/health/ready", + new HealthCheckOptions + { + Predicate = _ => true, + AllowCachingResponses = false, + ResponseWriter = WriteResponseAsync + } + ) .UseHealthChecksUI(setup => { setup.ApiPath = "/healthcheck"; @@ -52,10 +61,7 @@ private static Task WriteResponseAsync(HttpContext context, HealthReport result) { context.Response.ContentType = "application/json; charset=utf-8"; - var options = new JsonWriterOptions - { - Indented = true - }; + var options = new JsonWriterOptions { Indented = true }; using var stream = new MemoryStream(); using (var writer = new Utf8JsonWriter(stream, options)) @@ -78,4 +84,4 @@ private static Task WriteResponseAsync(HttpContext context, HealthReport result) return context.Response.WriteAsync(json); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Web/BaseController.cs b/src/BuildingBlocks/BulidingBlocks/Web/BaseController.cs index a21f788..d5c500e 100644 --- a/src/BuildingBlocks/BulidingBlocks/Web/BaseController.cs +++ b/src/BuildingBlocks/BulidingBlocks/Web/BaseController.cs @@ -13,8 +13,7 @@ public abstract class BaseController : Controller private IMediator _mediator; - protected IMediator Mediator => - _mediator ??= HttpContext.RequestServices.GetService(); + protected IMediator Mediator => _mediator ??= HttpContext.RequestServices.GetService(); protected IMapper Mapper => _mapper ??= HttpContext.RequestServices.GetService(); -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Web/IPageRequest.cs b/src/BuildingBlocks/BulidingBlocks/Web/IPageRequest.cs index 296e793..937c684 100644 --- a/src/BuildingBlocks/BulidingBlocks/Web/IPageRequest.cs +++ b/src/BuildingBlocks/BulidingBlocks/Web/IPageRequest.cs @@ -10,4 +10,4 @@ public interface IPageRequest public List Sorts { get; set; } public int Page { get; set; } public int PageSize { get; set; } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Web/ServiceCollectionExtensions.cs b/src/BuildingBlocks/BulidingBlocks/Web/ServiceCollectionExtensions.cs index b444b0e..67dc173 100644 --- a/src/BuildingBlocks/BulidingBlocks/Web/ServiceCollectionExtensions.cs +++ b/src/BuildingBlocks/BulidingBlocks/Web/ServiceCollectionExtensions.cs @@ -8,8 +8,10 @@ namespace BuildingBlocks.Web; public static class ServiceCollectionExtensions { - public static void AddCustomVersioning(this IServiceCollection services, - Action configurator = null) + public static void AddCustomVersioning( + this IServiceCollection services, + Action configurator = null + ) { // https://www.meziantou.net/versioning-an-asp-net-core-api.htm // https://dotnetthoughts.net/aspnetcore-api-versioning-with-net-6-minimal-apis/ @@ -18,7 +20,8 @@ public static void AddCustomVersioning(this IServiceCollection services, // https://www.nuget.org/packages/Asp.Versioning.Http // Support versioning in minimal apis with (Asp.Versioning.Http) dll - services.AddApiVersioning(options => + services + .AddApiVersioning(options => { // Add the headers "api-supported-versions" and "api-deprecated-versions" // This is better for discoverability @@ -35,30 +38,31 @@ public static void AddCustomVersioning(this IServiceCollection services, options.ApiVersionReader = ApiVersionReader.Combine( new HeaderApiVersionReader("api-version"), new QueryStringApiVersionReader(), - new UrlSegmentApiVersionReader()); + new UrlSegmentApiVersionReader() + ); configurator?.Invoke(options); }) - .AddApiExplorer( - options => - { - // add the versioned api explorer, which also adds IApiVersionDescriptionProvider service - // note: the specified format code will format the version as "'v'major[.minor][-status]" - options.GroupNameFormat = "'v'VVV"; - - // note1: this option is only necessary when versioning by url segment. - // note2:if we set it to true version will infer automatically in swagger based on mapped versions to api (swagger infer api versions in different tab in header Swagger UI), - // but if we set it to false we should put version for api endpoint manually. - // https://github.com/dotnet/aspnet-api-versioning/issues/909 - options.SubstituteApiVersionInUrl = true; - }) - + .AddApiExplorer(options => + { + // add the versioned api explorer, which also adds IApiVersionDescriptionProvider service + // note: the specified format code will format the version as "'v'major[.minor][-status]" + options.GroupNameFormat = "'v'VVV"; + + // note1: this option is only necessary when versioning by url segment. + // note2:if we set it to true version will infer automatically in swagger based on mapped versions to api (swagger infer api versions in different tab in header Swagger UI), + // but if we set it to false we should put version for api endpoint manually. + // https://github.com/dotnet/aspnet-api-versioning/issues/909 + options.SubstituteApiVersionInUrl = true; + }) // Support versioning in mvc with with (Asp.Versioning.Mvc.ApiExplorer) dll .AddMvc(); // https://www.nuget.org/packages/Asp.Versioning.Mvc.ApiExplorer } - public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, - Action configurator = null) + public static IServiceCollection AddCustomHealthCheck( + this IServiceCollection services, + Action configurator = null + ) { var healCheckBuilder = services.AddHealthChecks(); configurator?.Invoke(healCheckBuilder); @@ -73,15 +77,13 @@ public static IServiceCollection AddCustomHealthCheck(this IServiceCollection se return services; } - public static void Unregister(this IServiceCollection services) { var descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(TService)); services.Remove(descriptor); } - public static void Replace(this IServiceCollection services, - ServiceLifetime lifetime) + public static void Replace(this IServiceCollection services, ServiceLifetime lifetime) { services.Unregister(); services.Add(new ServiceDescriptor(typeof(TService), typeof(TImplementation), lifetime)); @@ -95,10 +97,14 @@ public static void Replace(this IServiceCollection se /// The service collection /// Service type /// Implementation type - private static void TryAddTransientExact(this IServiceCollection services, Type serviceType, - Type implementationType) + private static void TryAddTransientExact( + this IServiceCollection services, + Type serviceType, + Type implementationType + ) { - if (services.Any(reg => reg.ServiceType == serviceType && reg.ImplementationType == implementationType)) return; + if (services.Any(reg => reg.ServiceType == serviceType && reg.ImplementationType == implementationType)) + return; services.AddTransient(serviceType, implementationType); } @@ -111,10 +117,10 @@ private static void TryAddTransientExact(this IServiceCollection services, Type /// The service collection /// Service type /// Implementation type - private static void TryAddScopeExact(this IServiceCollection services, Type serviceType, - Type implementationType) + private static void TryAddScopeExact(this IServiceCollection services, Type serviceType, Type implementationType) { - if (services.Any(reg => reg.ServiceType == serviceType && reg.ImplementationType == implementationType)) return; + if (services.Any(reg => reg.ServiceType == serviceType && reg.ImplementationType == implementationType)) + return; services.AddScoped(serviceType, implementationType); } @@ -127,10 +133,14 @@ private static void TryAddScopeExact(this IServiceCollection services, Type serv /// The service collection /// Service type /// Implementation type - private static void TryAddSingletonExact(this IServiceCollection services, Type serviceType, - Type implementationType) + private static void TryAddSingletonExact( + this IServiceCollection services, + Type serviceType, + Type implementationType + ) { - if (services.Any(reg => reg.ServiceType == serviceType && reg.ImplementationType == implementationType)) return; + if (services.Any(reg => reg.ServiceType == serviceType && reg.ImplementationType == implementationType)) + return; services.AddSingleton(serviceType, implementationType); } @@ -143,8 +153,10 @@ public static void ReplaceScoped(this IServiceCollect services.AddScoped(); } - public static void ReplaceScoped(this IServiceCollection services, - Func implementationFactory) + public static void ReplaceScoped( + this IServiceCollection services, + Func implementationFactory + ) where TService : class { services.Unregister(); @@ -159,8 +171,10 @@ public static void ReplaceTransient(this IServiceColl services.AddTransient(); } - public static void ReplaceTransient(this IServiceCollection services, - Func implementationFactory) + public static void ReplaceTransient( + this IServiceCollection services, + Func implementationFactory + ) where TService : class { services.Unregister(); @@ -175,8 +189,10 @@ public static void ReplaceSingleton(this IServiceColl services.AddSingleton(); } - public static void ReplaceSingleton(this IServiceCollection services, - Func implementationFactory) + public static void ReplaceSingleton( + this IServiceCollection services, + Func implementationFactory + ) where TService : class { services.Unregister(); @@ -192,12 +208,16 @@ public static void RegisterOptions(this IServiceCollection services, I services.AddSingleton(options); } - public static void RegisterOptions(this IServiceCollection services, IConfiguration configuration, - string name) where TOptions : class, new() + public static void RegisterOptions( + this IServiceCollection services, + IConfiguration configuration, + string name + ) + where TOptions : class, new() { var options = new TOptions(); configuration.Bind(name, options); services.AddSingleton(options); } -} \ No newline at end of file +} diff --git a/src/BuildingBlocks/BulidingBlocks/Web/SlugifyParameterTransformer.cs b/src/BuildingBlocks/BulidingBlocks/Web/SlugifyParameterTransformer.cs index c73eb92..9aecf77 100644 --- a/src/BuildingBlocks/BulidingBlocks/Web/SlugifyParameterTransformer.cs +++ b/src/BuildingBlocks/BulidingBlocks/Web/SlugifyParameterTransformer.cs @@ -12,4 +12,4 @@ public string TransformOutbound(object value) ? null : Regex.Replace(value.ToString() ?? string.Empty, "([a-z])([A-Z])", "$1-$2").ToLower(); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Movies/Models/GetMovieCreditsRequest.cs b/src/MovieSearch.Api/Movies/Models/GetMovieCreditsRequest.cs index 639754c..863ef41 100644 --- a/src/MovieSearch.Api/Movies/Models/GetMovieCreditsRequest.cs +++ b/src/MovieSearch.Api/Movies/Models/GetMovieCreditsRequest.cs @@ -3,4 +3,4 @@ namespace Thesaurus.Api.Words.ViewModels; public class GetMovieCreditsRequest { public int MovieId { get; set; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Movies/Models/GetPopularMoviesRequest.cs b/src/MovieSearch.Api/Movies/Models/GetPopularMoviesRequest.cs index 1f3891d..133ee11 100644 --- a/src/MovieSearch.Api/Movies/Models/GetPopularMoviesRequest.cs +++ b/src/MovieSearch.Api/Movies/Models/GetPopularMoviesRequest.cs @@ -3,4 +3,4 @@ namespace Thesaurus.Api.Words.ViewModels; public class GetPopularMoviesRequest { public int Page { get; set; } = 1; -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Movies/Models/GetUpcomingMoviesRequest.cs b/src/MovieSearch.Api/Movies/Models/GetUpcomingMoviesRequest.cs index 0b05196..2113a69 100644 --- a/src/MovieSearch.Api/Movies/Models/GetUpcomingMoviesRequest.cs +++ b/src/MovieSearch.Api/Movies/Models/GetUpcomingMoviesRequest.cs @@ -3,4 +3,4 @@ namespace Thesaurus.Api.Words.ViewModels; public class GetUpcomingMoviesRequest { public int Page { get; set; } = 1; -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Movies/Models/SearchMoviesByTitleRequest.cs b/src/MovieSearch.Api/Movies/Models/SearchMoviesByTitleRequest.cs index 090950d..e391a4f 100644 --- a/src/MovieSearch.Api/Movies/Models/SearchMoviesByTitleRequest.cs +++ b/src/MovieSearch.Api/Movies/Models/SearchMoviesByTitleRequest.cs @@ -4,4 +4,4 @@ public class SearchMoviesByTitleRequest { public string SearchKeywords { get; set; } public int Page { get; set; } = 1; -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Movies/Models/SearchMoviesRequest.cs b/src/MovieSearch.Api/Movies/Models/SearchMoviesRequest.cs index 8f926eb..4e63771 100644 --- a/src/MovieSearch.Api/Movies/Models/SearchMoviesRequest.cs +++ b/src/MovieSearch.Api/Movies/Models/SearchMoviesRequest.cs @@ -7,4 +7,4 @@ public class SearchMoviesRequest public bool IncludeAdult { get; set; } public string SearchKeywords { get; set; } public int Page { get; set; } = 1; -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Movies/MoviesController.cs b/src/MovieSearch.Api/Movies/MoviesController.cs index 139f2c5..c800da6 100644 --- a/src/MovieSearch.Api/Movies/MoviesController.cs +++ b/src/MovieSearch.Api/Movies/MoviesController.cs @@ -38,7 +38,7 @@ public class MoviesController : BaseController [SwaggerOperation(Summary = "Get specific movie by id", Description = "Get a single movie by Id")] public async Task GetByIdAsync([FromRoute] int id, CancellationToken cancellationToken) { - var query = new FindMovieByIdQuery {Id = id}; + var query = new FindMovieByIdQuery { Id = id }; var result = await Mediator.Send(query, cancellationToken); return Ok(result); @@ -58,7 +58,7 @@ public async Task GetByIdAsync([FromRoute] int id, CancellationTok [SwaggerOperation(Summary = "Get specific order by id", Description = "Get a single Order by Id")] public async Task GetByImdbIdAsync([FromRoute] string imdbId, CancellationToken cancellationToken) { - var query = new FindMovieByImdbIdQuery {ImdbId = imdbId}; + var query = new FindMovieByImdbIdQuery { ImdbId = imdbId }; var result = await Mediator.Send(query, cancellationToken); return Ok(result); @@ -76,10 +76,15 @@ public async Task GetByImdbIdAsync([FromRoute] string imdbId, Canc [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [SwaggerOperation(Summary = "Get specific movie by id with its trailers", - Description = "Get specific movie by id with its trailers")] - public async Task GetWithTrailersById([FromRoute] int id, [FromQuery] int trailersCount = 20, - CancellationToken cancellationToken = default) + [SwaggerOperation( + Summary = "Get specific movie by id with its trailers", + Description = "Get specific movie by id with its trailers" + )] + public async Task GetWithTrailersById( + [FromRoute] int id, + [FromQuery] int trailersCount = 20, + CancellationToken cancellationToken = default + ) { var query = new FindMovieWithTrailersByIdQuery(id, trailersCount); var result = await Mediator.Send(query, cancellationToken); @@ -99,10 +104,15 @@ public async Task GetWithTrailersById([FromRoute] int id, [FromQue [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [SwaggerOperation(Summary = "Get specific movie by imdbId with its trailers.", - Description = "Get specific movie by imdbId with its trailers.")] - public async Task GetWithTrailersByImdbId([FromRoute] string imdbId, - [FromQuery] int trailersCount = 20, CancellationToken cancellationToken = default) + [SwaggerOperation( + Summary = "Get specific movie by imdbId with its trailers.", + Description = "Get specific movie by imdbId with its trailers." + )] + public async Task GetWithTrailersByImdbId( + [FromRoute] string imdbId, + [FromQuery] int trailersCount = 20, + CancellationToken cancellationToken = default + ) { var query = new FindMovieWithTrailersByImdbIdQuery(imdbId, trailersCount); var result = await Mediator.Send(query, cancellationToken); @@ -121,13 +131,12 @@ public async Task GetWithTrailersByImdbId([FromRoute] string imdbI [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [SwaggerOperation(Summary = "Search movies by title", Description = "Search movies by title")] - public async Task SearchByTitleAsync([FromQuery] SearchMoviesByTitleRequest request, - CancellationToken cancellationToken) + public async Task SearchByTitleAsync( + [FromQuery] SearchMoviesByTitleRequest request, + CancellationToken cancellationToken + ) { - var query = new SearchMovieByTitleQuery - { - Page = request.Page, SearchKeywords = request.SearchKeywords - }; + var query = new SearchMovieByTitleQuery { Page = request.Page, SearchKeywords = request.SearchKeywords }; var result = await Mediator.Send(query, cancellationToken); return Ok(result); @@ -143,13 +152,22 @@ public async Task SearchByTitleAsync([FromQuery] SearchMoviesByTit [ApiVersion("1.0")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - [SwaggerOperation(Summary = "Search movies by different parameters", - Description = "Search movies by different parameters")] - public async Task SearchAsync([FromQuery] SearchMoviesRequest request, - CancellationToken cancellationToken) + [SwaggerOperation( + Summary = "Search movies by different parameters", + Description = "Search movies by different parameters" + )] + public async Task SearchAsync( + [FromQuery] SearchMoviesRequest request, + CancellationToken cancellationToken + ) { - var query = new SearchMovieQuery(request.SearchKeywords, request.Page, request.Year, request - .PrimaryReleaseYear, request.IncludeAdult); + var query = new SearchMovieQuery( + request.SearchKeywords, + request.Page, + request.Year, + request.PrimaryReleaseYear, + request.IncludeAdult + ); var result = await Mediator.Send(query, cancellationToken); return Ok(result); @@ -165,12 +183,16 @@ public async Task SearchAsync([FromQuery] SearchMoviesRequest requ [ApiVersion("1.0")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - [SwaggerOperation(Summary = "Get a list of upcoming movies in theatres", - Description = "Get a list of upcoming movies in theatres")] - public async Task GetUpcomingMoviesAsync([FromQuery] GetUpcomingMoviesRequest request, - CancellationToken cancellationToken) + [SwaggerOperation( + Summary = "Get a list of upcoming movies in theatres", + Description = "Get a list of upcoming movies in theatres" + )] + public async Task GetUpcomingMoviesAsync( + [FromQuery] GetUpcomingMoviesRequest request, + CancellationToken cancellationToken + ) { - var query = new FindUpcomingMoviesQuery {Page = request.Page}; + var query = new FindUpcomingMoviesQuery { Page = request.Page }; var result = await Mediator.Send(query, cancellationToken); return Ok(result); @@ -186,12 +208,16 @@ public async Task GetUpcomingMoviesAsync([FromQuery] GetUpcomingMo [ApiVersion("1.0")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - [SwaggerOperation(Summary = "Get a list of the current popular movies on TMDB. This list updates daily.", - Description = "Get a list of the current popular movies on TMDB. This list updates daily.")] - public async Task GetPopularMoviesAsync([FromQuery] GetPopularMoviesRequest request, - CancellationToken cancellationToken) + [SwaggerOperation( + Summary = "Get a list of the current popular movies on TMDB. This list updates daily.", + Description = "Get a list of the current popular movies on TMDB. This list updates daily." + )] + public async Task GetPopularMoviesAsync( + [FromQuery] GetPopularMoviesRequest request, + CancellationToken cancellationToken + ) { - var query = new FindPopularMoviesQuery {Page = request.Page}; + var query = new FindPopularMoviesQuery { Page = request.Page }; var result = await Mediator.Send(query, cancellationToken); return Ok(result); @@ -208,14 +234,18 @@ public async Task GetPopularMoviesAsync([FromQuery] GetPopularMovi [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [SwaggerOperation(Summary = "Get the cast and crew for a movie.", - Description = "Get the cast and crew for a movie.")] - public async Task GetMovieCreditsAsync([FromQuery] GetMovieCreditsRequest request, - CancellationToken cancellationToken) + [SwaggerOperation( + Summary = "Get the cast and crew for a movie.", + Description = "Get the cast and crew for a movie." + )] + public async Task GetMovieCreditsAsync( + [FromQuery] GetMovieCreditsRequest request, + CancellationToken cancellationToken + ) { var query = new FindMovieCreditsQuery(request.MovieId); var result = await Mediator.Send(query, cancellationToken); return Ok(result); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Multi/Models/SearchMultipleModelRequest.cs b/src/MovieSearch.Api/Multi/Models/SearchMultipleModelRequest.cs index d492ae0..d5bc21a 100644 --- a/src/MovieSearch.Api/Multi/Models/SearchMultipleModelRequest.cs +++ b/src/MovieSearch.Api/Multi/Models/SearchMultipleModelRequest.cs @@ -6,4 +6,4 @@ public class SearchMultipleModelRequest public bool IncludeAdult { get; set; } public int Page { get; set; } = 1; public int Year { get; set; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Multi/MultiController.cs b/src/MovieSearch.Api/Multi/MultiController.cs index 074faca..f11a687 100644 --- a/src/MovieSearch.Api/Multi/MultiController.cs +++ b/src/MovieSearch.Api/Multi/MultiController.cs @@ -27,12 +27,13 @@ public class MultiController : BaseController [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [SwaggerOperation( - Summary = - "Search multiple models in a single request. Multi search currently supports searching for movies, tv shows and people in a single request.", - Description = - "Search multiple models in a single request. Multi search currently supports searching for movies, tv shows and people in a single request.")] - public async Task SearchAsync([FromQuery] SearchMultipleModelRequest request, - CancellationToken cancellationToken) + Summary = "Search multiple models in a single request. Multi search currently supports searching for movies, tv shows and people in a single request.", + Description = "Search multiple models in a single request. Multi search currently supports searching for movies, tv shows and people in a single request." + )] + public async Task SearchAsync( + [FromQuery] SearchMultipleModelRequest request, + CancellationToken cancellationToken + ) { var query = new SearchMultipleModelQuery { @@ -45,4 +46,4 @@ public async Task SearchAsync([FromQuery] SearchMultipleModelReque return Ok(result); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/People/PeopleController.cs b/src/MovieSearch.Api/People/PeopleController.cs index b825da1..0da08f2 100644 --- a/src/MovieSearch.Api/People/PeopleController.cs +++ b/src/MovieSearch.Api/People/PeopleController.cs @@ -27,8 +27,10 @@ public class PeopleController : BaseController [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [SwaggerOperation(Summary = "Get the primary person details by id.", - Description = "Get the primary person details by id.")] + [SwaggerOperation( + Summary = "Get the primary person details by id.", + Description = "Get the primary person details by id." + )] public async Task GetByIdAsync([FromRoute] int personId, CancellationToken cancellationToken) { var query = new FindPersonByIdQuery(personId); @@ -47,10 +49,11 @@ public async Task GetByIdAsync([FromRoute] int personId, Cancellat [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [SwaggerOperation(Summary = "Get the movie credits for a person.", - Description = "Get the movie credits for a person.")] - public async Task GetPersonMovieCreditsAsync([FromRoute] int id, - CancellationToken cancellationToken) + [SwaggerOperation( + Summary = "Get the movie credits for a person.", + Description = "Get the movie credits for a person." + )] + public async Task GetPersonMovieCreditsAsync([FromRoute] int id, CancellationToken cancellationToken) { var query = new FindPersonMovieCreditsQuery(id); var result = await Mediator.Send(query, cancellationToken); @@ -68,14 +71,15 @@ public async Task GetPersonMovieCreditsAsync([FromRoute] int id, [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [SwaggerOperation(Summary = "Get the tv-show credits for a person.", - Description = "Get the tv-show credits for a person.")] - public async Task GetPersonTvShowCreditsAsync([FromRoute] int id, - CancellationToken cancellationToken) + [SwaggerOperation( + Summary = "Get the tv-show credits for a person.", + Description = "Get the tv-show credits for a person." + )] + public async Task GetPersonTvShowCreditsAsync([FromRoute] int id, CancellationToken cancellationToken) { var query = new FindPersonTVShowCreditsQuery(id); var result = await Mediator.Send(query, cancellationToken); return Ok(result); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Program.cs b/src/MovieSearch.Api/Program.cs index 42ef226..8676727 100644 --- a/src/MovieSearch.Api/Program.cs +++ b/src/MovieSearch.Api/Program.cs @@ -16,30 +16,41 @@ using MovieSearch.Infrastructure; using Serilog; - // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis // https://benfoster.io/blog/mvc-to-minimal-apis-aspnet-6/ var builder = WebApplication.CreateBuilder(args); -builder.Host.UseDefaultServiceProvider((env, c) => -{ - // Handling Captive Dependency Problem - // https://ankitvijay.net/2020/03/17/net-core-and-di-beware-of-captive-dependency/ - // https://levelup.gitconnected.com/top-misconceptions-about-dependency-injection-in-asp-net-core-c6a7afd14eb4 - // https://blog.ploeh.dk/2014/06/02/captive-dependency/ - if (env.HostingEnvironment.IsDevelopment() || env.HostingEnvironment.IsEnvironment("tests") || - env.HostingEnvironment.IsStaging()) - c.ValidateScopes = true; -}); +builder.Host.UseDefaultServiceProvider( + (env, c) => + { + // Handling Captive Dependency Problem + // https://ankitvijay.net/2020/03/17/net-core-and-di-beware-of-captive-dependency/ + // https://levelup.gitconnected.com/top-misconceptions-about-dependency-injection-in-asp-net-core-c6a7afd14eb4 + // https://blog.ploeh.dk/2014/06/02/captive-dependency/ + if ( + env.HostingEnvironment.IsDevelopment() + || env.HostingEnvironment.IsEnvironment("tests") + || env.HostingEnvironment.IsStaging() + ) + c.ValidateScopes = true; + } +); builder.AddCustomSerilog(); builder.Services.AddControllers(options => - options.Conventions.Add(new RouteTokenTransformerConvention(new SlugifyParameterTransformer()))); + options.Conventions.Add(new RouteTokenTransformerConvention(new SlugifyParameterTransformer())) +); builder.Services.AddCors(options => { - options.AddPolicy("api", policy => { policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); }); + options.AddPolicy( + "api", + policy => + { + policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); + } + ); }); builder.Services.AddApplication(); @@ -65,6 +76,4 @@ await app.RunAsync(); -public partial class Program -{ -} \ No newline at end of file +public partial class Program { } diff --git a/src/MovieSearch.Api/TvShows/Model/SearchTVShowsByTitleRequest.cs b/src/MovieSearch.Api/TvShows/Model/SearchTVShowsByTitleRequest.cs index 7b3828b..ff217a7 100644 --- a/src/MovieSearch.Api/TvShows/Model/SearchTVShowsByTitleRequest.cs +++ b/src/MovieSearch.Api/TvShows/Model/SearchTVShowsByTitleRequest.cs @@ -4,4 +4,4 @@ public class SearchTVShowsByTitleRequest { public int Page { get; set; } = 1; public string SearchKeywords { get; set; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/TvShows/Model/SearchTVShowsRequest.cs b/src/MovieSearch.Api/TvShows/Model/SearchTVShowsRequest.cs index ac397bd..8d7518a 100644 --- a/src/MovieSearch.Api/TvShows/Model/SearchTVShowsRequest.cs +++ b/src/MovieSearch.Api/TvShows/Model/SearchTVShowsRequest.cs @@ -6,4 +6,4 @@ public class SearchTVShowsRequest public bool IncludeAdult { get; set; } public string SearchKeywords { get; set; } public int Page { get; set; } = 1; -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/TvShows/TVShowsController.cs b/src/MovieSearch.Api/TvShows/TVShowsController.cs index 5d39d9d..1bc92bc 100644 --- a/src/MovieSearch.Api/TvShows/TVShowsController.cs +++ b/src/MovieSearch.Api/TvShows/TVShowsController.cs @@ -49,10 +49,15 @@ public async Task GetByIdAsync([FromRoute] int id, CancellationTok [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [SwaggerOperation(Summary = "Get specific tv-show by id with its trailers", - Description = "Get specific tv-show by id with its trailers")] - public async Task GetWithTrailersByIdAsync([FromRoute] int id, [FromQuery] int trailersCount = 20, - CancellationToken cancellationToken = default) + [SwaggerOperation( + Summary = "Get specific tv-show by id with its trailers", + Description = "Get specific tv-show by id with its trailers" + )] + public async Task GetWithTrailersByIdAsync( + [FromRoute] int id, + [FromQuery] int trailersCount = 20, + CancellationToken cancellationToken = default + ) { var query = new FindTVShowWithTrailersByIdQuery(id, trailersCount); var result = await Mediator.Send(query, cancellationToken); @@ -70,8 +75,10 @@ public async Task GetWithTrailersByIdAsync([FromRoute] int id, [Fr [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [SwaggerOperation(Summary = "Search tv-shows by title", Description = "Search tv-shows by title")] - public async Task SearchByTitleAsync([FromQuery] SearchTVShowsByTitleRequest request, - CancellationToken cancellationToken) + public async Task SearchByTitleAsync( + [FromQuery] SearchTVShowsByTitleRequest request, + CancellationToken cancellationToken + ) { var query = new SearchTVShowByTitleQuery(request.SearchKeywords, request.Page); var result = await Mediator.Send(query, cancellationToken); @@ -88,15 +95,23 @@ public async Task SearchByTitleAsync([FromQuery] SearchTVShowsByTi [HttpGet("search")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - [SwaggerOperation(Summary = "Search tv-shows by different parameters", - Description = "Search tv-shows by different parameters")] - public async Task SearchAsync([FromQuery] SearchTVShowsRequest request, - CancellationToken cancellationToken) + [SwaggerOperation( + Summary = "Search tv-shows by different parameters", + Description = "Search tv-shows by different parameters" + )] + public async Task SearchAsync( + [FromQuery] SearchTVShowsRequest request, + CancellationToken cancellationToken + ) { - var query = new SearchTVShowQuery(request.SearchKeywords, request.Page, request.FirstAirDateYear, - request.IncludeAdult); + var query = new SearchTVShowQuery( + request.SearchKeywords, + request.Page, + request.FirstAirDateYear, + request.IncludeAdult + ); var result = await Mediator.Send(query, cancellationToken); return Ok(result); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Videos/Models/GetMovieTrailersRequest.cs b/src/MovieSearch.Api/Videos/Models/GetMovieTrailersRequest.cs index 6c6d4ea..43f2300 100644 --- a/src/MovieSearch.Api/Videos/Models/GetMovieTrailersRequest.cs +++ b/src/MovieSearch.Api/Videos/Models/GetMovieTrailersRequest.cs @@ -5,4 +5,4 @@ public class GetMovieTrailersRequest public string PageToken { get; set; } = ""; public int PageSize { get; set; } = 20; public int MovieId { get; set; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Videos/Models/GetTVShowTrailersRequest.cs b/src/MovieSearch.Api/Videos/Models/GetTVShowTrailersRequest.cs index bf4e1d8..bfb3120 100644 --- a/src/MovieSearch.Api/Videos/Models/GetTVShowTrailersRequest.cs +++ b/src/MovieSearch.Api/Videos/Models/GetTVShowTrailersRequest.cs @@ -5,4 +5,4 @@ public class GetTVShowTrailersRequest public string PageToken { get; set; } = ""; public int PageSize { get; set; } = 20; public int TVShowId { get; set; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Videos/Models/GetTrailersRequest.cs b/src/MovieSearch.Api/Videos/Models/GetTrailersRequest.cs index 264e406..b1831f6 100644 --- a/src/MovieSearch.Api/Videos/Models/GetTrailersRequest.cs +++ b/src/MovieSearch.Api/Videos/Models/GetTrailersRequest.cs @@ -9,4 +9,4 @@ public class GetTrailersRequest public string MovieName { get; set; } public DateTime? PublishedBefore { get; set; } public DateTime? PublishedAfter { get; set; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Api/Videos/VideosController.cs b/src/MovieSearch.Api/Videos/VideosController.cs index 18ba243..8f00d6b 100644 --- a/src/MovieSearch.Api/Videos/VideosController.cs +++ b/src/MovieSearch.Api/Videos/VideosController.cs @@ -25,16 +25,16 @@ public class VideosController : BaseController [HttpGet("search-trailers")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - [SwaggerOperation(Summary = "Get the trailers by movie or tv-show name", - Description = "Get the trailers by movie or tv-show name")] - public async Task GetTrailersAsync([FromQuery] GetTrailersRequest request, - CancellationToken cancellationToken) + [SwaggerOperation( + Summary = "Get the trailers by movie or tv-show name", + Description = "Get the trailers by movie or tv-show name" + )] + public async Task GetTrailersAsync( + [FromQuery] GetTrailersRequest request, + CancellationToken cancellationToken + ) { - var query = new FindTrailersQuery - { - MovieName = request.MovieName, - PageToken = request.PageToken - }; + var query = new FindTrailersQuery { MovieName = request.MovieName, PageToken = request.PageToken }; var result = await Mediator.Send(query, cancellationToken); return Ok(result); @@ -50,10 +50,14 @@ public async Task GetTrailersAsync([FromQuery] GetTrailersRequest [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [SwaggerOperation(Summary = "Get the trailers for a specific movie", - Description = "Get the trailers for a specific movie")] - public async Task GetMovieTrailersAsync([FromQuery] GetMovieTrailersRequest request, - CancellationToken cancellationToken) + [SwaggerOperation( + Summary = "Get the trailers for a specific movie", + Description = "Get the trailers for a specific movie" + )] + public async Task GetMovieTrailersAsync( + [FromQuery] GetMovieTrailersRequest request, + CancellationToken cancellationToken + ) { var query = new FindMovieTrailersQuery { @@ -76,10 +80,14 @@ public async Task GetMovieTrailersAsync([FromQuery] GetMovieTraile [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [SwaggerOperation(Summary = "Get the trailers for a specific tv-show", - Description = "Get the trailers for a specific tv-show")] - public async Task GetTVShowTrailersAsync([FromQuery] GetTVShowTrailersRequest request, - CancellationToken cancellationToken) + [SwaggerOperation( + Summary = "Get the trailers for a specific tv-show", + Description = "Get the trailers for a specific tv-show" + )] + public async Task GetTVShowTrailersAsync( + [FromQuery] GetTVShowTrailersRequest request, + CancellationToken cancellationToken + ) { var query = new FindTVShowTrailersQuery { @@ -91,4 +99,4 @@ public async Task GetTVShowTrailersAsync([FromQuery] GetTVShowTrai return Ok(result); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/ApplicationRoot.cs b/src/MovieSearch.Application/ApplicationRoot.cs index cf8d53e..ffdcb3e 100644 --- a/src/MovieSearch.Application/ApplicationRoot.cs +++ b/src/MovieSearch.Application/ApplicationRoot.cs @@ -1,5 +1,3 @@ namespace MovieSearch.Application; -public class ApplicationRoot -{ -} \ No newline at end of file +public class ApplicationRoot { } diff --git a/src/MovieSearch.Application/Companies/CompanyMappings.cs b/src/MovieSearch.Application/Companies/CompanyMappings.cs index 693fe4b..1b22c2e 100644 --- a/src/MovieSearch.Application/Companies/CompanyMappings.cs +++ b/src/MovieSearch.Application/Companies/CompanyMappings.cs @@ -10,4 +10,4 @@ public CompanyMappings() { CreateMap(); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Companies/Dtos/ProductCompanyDto.cs b/src/MovieSearch.Application/Companies/Dtos/ProductCompanyDto.cs index a7ca68a..1042e19 100644 --- a/src/MovieSearch.Application/Companies/Dtos/ProductCompanyDto.cs +++ b/src/MovieSearch.Application/Companies/Dtos/ProductCompanyDto.cs @@ -6,4 +6,4 @@ public class ProductionCompanyDto public string Name { get; init; } public string LogoPath { get; init; } public string OriginCountry { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Extensions.cs b/src/MovieSearch.Application/Extensions.cs index cfffa39..aea650a 100644 --- a/src/MovieSearch.Application/Extensions.cs +++ b/src/MovieSearch.Application/Extensions.cs @@ -10,4 +10,4 @@ public static IServiceCollection AddApplication(this IServiceCollection services { return services; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Generals/Dtos/CountryDto.cs b/src/MovieSearch.Application/Generals/Dtos/CountryDto.cs index 2656796..e555f8d 100644 --- a/src/MovieSearch.Application/Generals/Dtos/CountryDto.cs +++ b/src/MovieSearch.Application/Generals/Dtos/CountryDto.cs @@ -4,4 +4,4 @@ public class CountryDto { public string Iso3166Code { get; init; } public string Name { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Generals/Dtos/LanguageDto.cs b/src/MovieSearch.Application/Generals/Dtos/LanguageDto.cs index 5b6abb1..f562a81 100644 --- a/src/MovieSearch.Application/Generals/Dtos/LanguageDto.cs +++ b/src/MovieSearch.Application/Generals/Dtos/LanguageDto.cs @@ -5,4 +5,4 @@ public class LanguageDto public string Iso639Code { get; init; } public string Name { get; init; } public string EnglishName { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Generals/Dtos/MultiInfoDto.cs b/src/MovieSearch.Application/Generals/Dtos/MultiInfoDto.cs index fc3ae75..b9d9828 100644 --- a/src/MovieSearch.Application/Generals/Dtos/MultiInfoDto.cs +++ b/src/MovieSearch.Application/Generals/Dtos/MultiInfoDto.cs @@ -7,4 +7,4 @@ public class MultiInfoDto public int Id { get; init; } public virtual MediaType MediaType { get; init; } public double Popularity { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Generals/GeneralMappings.cs b/src/MovieSearch.Application/Generals/GeneralMappings.cs index 7f0204b..41845fd 100644 --- a/src/MovieSearch.Application/Generals/GeneralMappings.cs +++ b/src/MovieSearch.Application/Generals/GeneralMappings.cs @@ -12,4 +12,4 @@ public GeneralMappings() CreateMap(); CreateMap(); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMovieQueryValidator.cs b/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMovieQueryValidator.cs index da59b1a..820e843 100644 --- a/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMovieQueryValidator.cs +++ b/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMovieQueryValidator.cs @@ -7,11 +7,17 @@ public class SearchMultipleModelQueryValidator : AbstractValidator query.Page).GreaterThan(0).WithMessage("page number should be greater than zero."); - RuleFor(query => query.Year).Must(x => x >= 1700).When(c => c.Year > 0) + RuleFor(query => query.Year) + .Must(x => x >= 1700) + .When(c => c.Year > 0) .WithMessage("year should be greater than 1700."); //if it's not a default value - RuleFor(query => query.Year).Must(x => x >= 1700).When(c => c.Year > 0) + RuleFor(query => query.Year) + .Must(x => x >= 1700) + .When(c => c.Year > 0) .WithMessage("primary release year should be greater than 1700."); - RuleFor(query => query.SearchKeywords).NotEmpty().NotNull() + RuleFor(query => query.SearchKeywords) + .NotEmpty() + .NotNull() .WithMessage("search value should not be null or empty."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQuery.cs b/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQuery.cs index 4eb1d48..20891c6 100644 --- a/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQuery.cs +++ b/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQuery.cs @@ -8,4 +8,4 @@ public class SearchMultipleModelQuery : IQuery public bool IncludeAdult { get; init; } public int Page { get; init; } = 1; public int Year { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQueryHandler.cs b/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQueryHandler.cs index f0672ef..fd47aeb 100644 --- a/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQueryHandler.cs +++ b/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQueryHandler.cs @@ -7,8 +7,7 @@ namespace MovieSearch.Application.Generals.Multi.Features.SearchMultipleModel; -public class - SearchMultipleModelQueryHandler : IRequestHandler +public class SearchMultipleModelQueryHandler : IRequestHandler { private readonly IMapper _mapper; private readonly IMovieDbServiceClient _movieDbServiceClient; @@ -19,14 +18,21 @@ public SearchMultipleModelQueryHandler(IMovieDbServiceClient movieDbServiceClien _mapper = mapper; } - public async Task Handle(SearchMultipleModelQuery query, - CancellationToken cancellationToken) + public async Task Handle( + SearchMultipleModelQuery query, + CancellationToken cancellationToken + ) { Guard.Against.Null(query, nameof(SearchMultipleModelQuery)); - var searchData = await _movieDbServiceClient.SearchMultiAsync(query.SearchKeywords, query.Page, query - .IncludeAdult, query.Year, cancellationToken); + var searchData = await _movieDbServiceClient.SearchMultiAsync( + query.SearchKeywords, + query.Page, + query.IncludeAdult, + query.Year, + cancellationToken + ); - return new SearchMultipleModelQueryResult {List = searchData}; + return new SearchMultipleModelQueryResult { List = searchData }; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQueryResult.cs b/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQueryResult.cs index 3c60622..6afa8da 100644 --- a/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQueryResult.cs +++ b/src/MovieSearch.Application/Generals/Multi/Features/SearchMultipleModel/SearchMultipleModelQueryResult.cs @@ -5,4 +5,4 @@ namespace MovieSearch.Application.Generals.Multi.Features.SearchMultipleModel; public class SearchMultipleModelQueryResult { public ListResultModel List { get; set; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Genres/Dtos/GenreDto.cs b/src/MovieSearch.Application/Genres/Dtos/GenreDto.cs index c33ccb2..a4629c3 100644 --- a/src/MovieSearch.Application/Genres/Dtos/GenreDto.cs +++ b/src/MovieSearch.Application/Genres/Dtos/GenreDto.cs @@ -4,4 +4,4 @@ public class GenreDto { public int Id { get; init; } public string Name { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Genres/GenreMappings.cs b/src/MovieSearch.Application/Genres/GenreMappings.cs index 8b2e7ca..7e5580d 100644 --- a/src/MovieSearch.Application/Genres/GenreMappings.cs +++ b/src/MovieSearch.Application/Genres/GenreMappings.cs @@ -10,4 +10,4 @@ public GenreMappings() { CreateMap(); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Dtos/MovieCreditDto.cs b/src/MovieSearch.Application/Movies/Dtos/MovieCreditDto.cs index 87d6906..d4ebc38 100644 --- a/src/MovieSearch.Application/Movies/Dtos/MovieCreditDto.cs +++ b/src/MovieSearch.Application/Movies/Dtos/MovieCreditDto.cs @@ -39,4 +39,4 @@ public class MovieCrewMemberDto public string KnownForDepartment { get; init; } public string OriginalName { get; init; } public float Popularity { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Dtos/MovieDto.cs b/src/MovieSearch.Application/Movies/Dtos/MovieDto.cs index 31110cf..fe3792a 100644 --- a/src/MovieSearch.Application/Movies/Dtos/MovieDto.cs +++ b/src/MovieSearch.Application/Movies/Dtos/MovieDto.cs @@ -34,4 +34,4 @@ public class MovieDto public bool IsVideo { get; init; } public double VoteAverage { get; init; } public int VoteCount { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Dtos/MovieInfoDto.cs b/src/MovieSearch.Application/Movies/Dtos/MovieInfoDto.cs index 220f086..b55d9c0 100644 --- a/src/MovieSearch.Application/Movies/Dtos/MovieInfoDto.cs +++ b/src/MovieSearch.Application/Movies/Dtos/MovieInfoDto.cs @@ -20,4 +20,4 @@ public class MovieInfoDto : MultiInfoDto public bool Video { get; init; } public double VoteAverage { get; init; } public int VoteCount { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Dtos/MovieWithTrailersDto.cs b/src/MovieSearch.Application/Movies/Dtos/MovieWithTrailersDto.cs index e359f47..a72835a 100644 --- a/src/MovieSearch.Application/Movies/Dtos/MovieWithTrailersDto.cs +++ b/src/MovieSearch.Application/Movies/Dtos/MovieWithTrailersDto.cs @@ -7,4 +7,4 @@ public class MovieWithTrailersDto { public MovieDto Movie { get; init; } public IEnumerable Trailers { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Exceptions/MovieCreditsNotFoundException.cs b/src/MovieSearch.Application/Movies/Exceptions/MovieCreditsNotFoundException.cs index 871cd87..4e47b6f 100644 --- a/src/MovieSearch.Application/Movies/Exceptions/MovieCreditsNotFoundException.cs +++ b/src/MovieSearch.Application/Movies/Exceptions/MovieCreditsNotFoundException.cs @@ -4,8 +4,6 @@ namespace MovieSearch.Application.Movies.Exceptions; public class MovieCreditsNotFoundException : NotFoundException { - public MovieCreditsNotFoundException(int id) : base( - $"can't find a movie_credits for a movie with movieId '{id}' in the database.") - { - } -} \ No newline at end of file + public MovieCreditsNotFoundException(int id) + : base($"can't find a movie_credits for a movie with movieId '{id}' in the database.") { } +} diff --git a/src/MovieSearch.Application/Movies/Exceptions/MovieNotFoundException.cs b/src/MovieSearch.Application/Movies/Exceptions/MovieNotFoundException.cs index 45f2dbc..1d3e03f 100644 --- a/src/MovieSearch.Application/Movies/Exceptions/MovieNotFoundException.cs +++ b/src/MovieSearch.Application/Movies/Exceptions/MovieNotFoundException.cs @@ -4,11 +4,9 @@ namespace MovieSearch.Application.Movies.Exceptions; public class MovieNotFoundException : NotFoundException { - public MovieNotFoundException(int id) : base($"can't find movie with id '{id}' in the database.") - { - } + public MovieNotFoundException(int id) + : base($"can't find movie with id '{id}' in the database.") { } - public MovieNotFoundException(string imdbId) : base($"can't find movie with imdbid '{imdbId}' in the database.") - { - } -} \ No newline at end of file + public MovieNotFoundException(string imdbId) + : base($"can't find movie with imdbid '{imdbId}' in the database.") { } +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQuery.cs b/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQuery.cs index 33ff124..a22359f 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQuery.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQuery.cs @@ -17,4 +17,4 @@ public string GetCacheKey(FindMovieByIdQuery query) return CacheKey.With(query.GetType(), query.Id.ToString()); } } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryHandler.cs b/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryHandler.cs index d9655cf..4b3e43a 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryHandler.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryHandler.cs @@ -31,6 +31,6 @@ public async Task Handle(FindMovieByIdQuery query, Can var result = _mapper.Map(movie); - return new FindMovieByIdQueryResult {Movie = result}; + return new FindMovieByIdQueryResult { Movie = result }; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryResult.cs b/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryResult.cs index 2099650..38ced13 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryResult.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryResult.cs @@ -5,4 +5,4 @@ namespace MovieSearch.Application.Movies.Features.FindById; public class FindMovieByIdQueryResult { public MovieDto Movie { get; set; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryValidator.cs b/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryValidator.cs index 2044590..45e0301 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryValidator.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieById/FindMovieByIdQueryValidator.cs @@ -9,4 +9,4 @@ public FindMovieByIdQueryValidator() { RuleFor(query => query.Id).GreaterThan(0).WithMessage("id should be greater than zero."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindByImdbIdQueryResult.cs b/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindByImdbIdQueryResult.cs index f786f7a..26f3022 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindByImdbIdQueryResult.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindByImdbIdQueryResult.cs @@ -5,4 +5,4 @@ namespace MovieSearch.Application.Movies.Features.FindMovieByImdbId; public class FindByImdbIdQueryResult { public MovieDto Movie { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQuery.cs b/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQuery.cs index 21d6f24..6bb517d 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQuery.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQuery.cs @@ -17,4 +17,4 @@ public string GetCacheKey(FindMovieByImdbIdQuery query) return CacheKey.With(query.GetType(), query.ImdbId); } } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQueryHandler.cs b/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQueryHandler.cs index 9620089..f8160b5 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQueryHandler.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQueryHandler.cs @@ -20,8 +20,7 @@ public FindMovieByImdbIdQueryHandler(IMovieDbServiceClient movieDbServiceClient, _mapper = mapper; } - public async Task Handle(FindMovieByImdbIdQuery query, - CancellationToken cancellationToken) + public async Task Handle(FindMovieByImdbIdQuery query, CancellationToken cancellationToken) { Guard.Against.Null(query, nameof(FindMovieByImdbIdQuery)); @@ -32,6 +31,6 @@ public async Task Handle(FindMovieByImdbIdQuery query, var result = _mapper.Map(movie); - return new FindByImdbIdQueryResult {Movie = result}; + return new FindByImdbIdQueryResult { Movie = result }; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQueryValidator.cs b/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQueryValidator.cs index 954d10f..2e28924 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQueryValidator.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieByImdbId/FindMovieByImdbIdQueryValidator.cs @@ -9,4 +9,4 @@ public FindMovieByImdbIdQueryValidator() { RuleFor(query => query.ImdbId).NotNull().NotEmpty().WithMessage("ImdbId should not be null or empty."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQuery.cs b/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQuery.cs index 084370e..24b22fc 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQuery.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQuery.cs @@ -10,4 +10,4 @@ public FindMovieCreditsQuery(int movieId) } public int MovieId { get; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryHandler.cs b/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryHandler.cs index f5d9ddd..be4f650 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryHandler.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryHandler.cs @@ -20,8 +20,10 @@ public FindMovieCreditsQueryHandler(IMovieDbServiceClient movieDbServiceClient, _mapper = mapper; } - public async Task Handle(FindMovieCreditsQuery query, - CancellationToken cancellationToken) + public async Task Handle( + FindMovieCreditsQuery query, + CancellationToken cancellationToken + ) { Guard.Against.Null(query, nameof(FindMovieCreditsQuery)); @@ -32,6 +34,6 @@ public async Task Handle(FindMovieCreditsQuery quer var result = _mapper.Map(movieCredit); - return new FindMovieCreditsQueryResult {MovieCredit = result}; + return new FindMovieCreditsQueryResult { MovieCredit = result }; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryResult.cs b/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryResult.cs index 1eda606..08cab18 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryResult.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryResult.cs @@ -5,4 +5,4 @@ namespace MovieSearch.Application.Movies.Features.FindMovieCredits; public class FindMovieCreditsQueryResult { public MovieCreditDto MovieCredit { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryValidator.cs b/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryValidator.cs index fd68fc1..edfa356 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryValidator.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieCredits/FindMovieCreditsQueryValidator.cs @@ -9,4 +9,4 @@ public FindMovieCreditsQueryValidator() { RuleFor(query => query.MovieId).GreaterThan(0).WithMessage("movieId should be greater than zero."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQuery.cs b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQuery.cs index 7736fbb..c729e22 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQuery.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQuery.cs @@ -21,8 +21,10 @@ public class CachePolicy : ICachePolicy +public class FindMovieWithTrailersByIdQueryHandler + : IRequestHandler { private readonly IMapper _mapper; private readonly IMovieDbServiceClient _movieDbServiceClient; private readonly IVideoServiceClient _videoServiceClient; - public FindMovieWithTrailersByIdQueryHandler(IMovieDbServiceClient movieDbServiceClient, IVideoServiceClient - videoServiceClient, IMapper mapper) + public FindMovieWithTrailersByIdQueryHandler( + IMovieDbServiceClient movieDbServiceClient, + IVideoServiceClient videoServiceClient, + IMapper mapper + ) { _movieDbServiceClient = movieDbServiceClient; _videoServiceClient = videoServiceClient; _mapper = mapper; } - public async Task Handle(FindMovieWithTrailersByIdQuery query, - CancellationToken cancellationToken) + public async Task Handle( + FindMovieWithTrailersByIdQuery query, + CancellationToken cancellationToken + ) { Guard.Against.Null(query, nameof(FindMovieWithTrailersByIdQuery)); @@ -43,10 +47,8 @@ public async Task Handle(FindMovieWithTrai var trailers = (await _videoServiceClient.GetTrailers(movieDto.Title, query.TrailersCount)).Items; var trailersDto = _mapper.Map>(trailers); - return new FindMovieWithTrailersByIdQueryResult(new MovieWithTrailersDto - { - Movie = movieDto, - Trailers = trailersDto - }); + return new FindMovieWithTrailersByIdQueryResult( + new MovieWithTrailersDto { Movie = movieDto, Trailers = trailersDto } + ); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQueryResult.cs b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQueryResult.cs index 829c691..f47b7a3 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQueryResult.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQueryResult.cs @@ -10,4 +10,4 @@ public FindMovieWithTrailersByIdQueryResult(MovieWithTrailersDto movieWithTraile } public MovieWithTrailersDto MovieWithTrailers { get; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQueryValidator.cs b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQueryValidator.cs index 2e3fd23..8818161 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQueryValidator.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersById/FindMovieWithTrailersByIdQueryValidator.cs @@ -9,4 +9,4 @@ public FindMovieWithTrailersByIdQueryValidator() RuleFor(query => query.MovieId).GreaterThan(0).WithMessage("id should be greater than zero."); RuleFor(query => query.TrailersCount).GreaterThan(0).WithMessage("trailers-count should be greater than zero."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQuery.cs b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQuery.cs index 5b15c15..01adf36 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQuery.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQuery.cs @@ -15,15 +15,17 @@ public FindMovieWithTrailersByImdbIdQuery(string imdbId, int trailersCount = 20) public string ImdbId { get; } public int TrailersCount { get; } - public class - CachePolicy : ICachePolicy + public class CachePolicy + : ICachePolicy { public DateTime? AbsoluteExpirationRelativeToNow => DateTime.Now.AddMinutes(15); public string GetCacheKey(FindMovieWithTrailersByImdbIdQuery query) { - return CacheKey.With(query.GetType(), - $"{nameof(ImdbId)}_{query.ImdbId}_{nameof(TrailersCount)}_{query.TrailersCount}"); + return CacheKey.With( + query.GetType(), + $"{nameof(ImdbId)}_{query.ImdbId}_{nameof(TrailersCount)}_{query.TrailersCount}" + ); } } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryHandler.cs b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryHandler.cs index 22661fc..cb74da4 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryHandler.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryHandler.cs @@ -12,23 +12,28 @@ namespace MovieSearch.Application.Movies.Features.FindMovieWithTrailersByImdbId; //https://docs.microsoft.com/en-us/azure/architecture/patterns/gateway-aggregation -public class FindMovieWithTrailersByImdbIdQueryHandler : IRequestHandler +public class FindMovieWithTrailersByImdbIdQueryHandler + : IRequestHandler { private readonly IMapper _mapper; private readonly IMovieDbServiceClient _movieDbServiceClient; private readonly IVideoServiceClient _videoServiceClient; - public FindMovieWithTrailersByImdbIdQueryHandler(IMovieDbServiceClient movieDbServiceClient, - IVideoServiceClient videoServiceClient, IMapper mapper) + public FindMovieWithTrailersByImdbIdQueryHandler( + IMovieDbServiceClient movieDbServiceClient, + IVideoServiceClient videoServiceClient, + IMapper mapper + ) { _movieDbServiceClient = movieDbServiceClient; _videoServiceClient = videoServiceClient; _mapper = mapper; } - public async Task Handle(FindMovieWithTrailersByImdbIdQuery query, - CancellationToken cancellationToken) + public async Task Handle( + FindMovieWithTrailersByImdbIdQuery query, + CancellationToken cancellationToken + ) { Guard.Against.Null(query, nameof(FindMovieWithTrailersByImdbIdQuery)); @@ -44,11 +49,7 @@ public async Task Handle(FindMovieWith return new FindMovieWithTrailersByImdbIdQueryResult { - MovieWithTrailers = new MovieWithTrailersDto - { - Movie = movieDto, - Trailers = trailersDto - } + MovieWithTrailers = new MovieWithTrailersDto { Movie = movieDto, Trailers = trailersDto } }; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryResult.cs b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryResult.cs index a1738a1..f2c7daa 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryResult.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryResult.cs @@ -5,4 +5,4 @@ namespace MovieSearch.Application.Movies.Features.FindMovieWithTrailersByImdbId; public class FindMovieWithTrailersByImdbIdQueryResult { public MovieWithTrailersDto MovieWithTrailers { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryValidator.cs b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryValidator.cs index b7fcae6..e9bf62c 100644 --- a/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryValidator.cs +++ b/src/MovieSearch.Application/Movies/Features/FindMovieWithTrailersByImdbId/FindMovieWithTrailersByImdbIdQueryValidator.cs @@ -8,7 +8,9 @@ public class FindMovieWithTrailersByImdbIdQueryValidator : AbstractValidator query.ImdbId).NotNull().NotEmpty().WithMessage("ImdbId should not be null or empty."); - RuleFor(query => query.TrailersCount).NotNull().NotEmpty() + RuleFor(query => query.TrailersCount) + .NotNull() + .NotEmpty() .WithMessage("trailers-count should not be null or empty."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQuery.cs b/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQuery.cs index cae9b44..2fa09b6 100644 --- a/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQuery.cs +++ b/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQuery.cs @@ -5,4 +5,4 @@ namespace MovieSearch.Application.Movies.Features.FindPopularMovies; public class FindPopularMoviesQuery : IQuery { public int Page { get; init; } = 1; -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryHandler.cs b/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryHandler.cs index d859282..4c6bc8d 100644 --- a/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryHandler.cs +++ b/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryHandler.cs @@ -19,8 +19,10 @@ public FindPopularMoviesQueryHandler(IMovieDbServiceClient movieDbServiceClient, _mapper = mapper; } - public async Task Handle(FindPopularMoviesQuery query, - CancellationToken cancellationToken) + public async Task Handle( + FindPopularMoviesQuery query, + CancellationToken cancellationToken + ) { Guard.Against.Null(query, nameof(FindPopularMoviesQuery)); @@ -28,6 +30,6 @@ public async Task Handle(FindPopularMoviesQuery qu var result = movies.Map(x => _mapper.Map(x)); - return new FindPopularMoviesQueryResult {MovieList = result}; + return new FindPopularMoviesQueryResult { MovieList = result }; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryResult.cs b/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryResult.cs index 9aee05d..79e74cb 100644 --- a/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryResult.cs +++ b/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryResult.cs @@ -6,4 +6,4 @@ namespace MovieSearch.Application.Movies.Features.FindPopularMovies; public class FindPopularMoviesQueryResult { public ListResultModel MovieList { get; set; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryValidator.cs b/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryValidator.cs index fc4ac0f..db6c8cd 100644 --- a/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryValidator.cs +++ b/src/MovieSearch.Application/Movies/Features/FindPopularMovies/FindPopularMoviesQueryValidator.cs @@ -9,4 +9,4 @@ public FindPopularMoviesQueryValidator() { RuleFor(query => query.Page).GreaterThan(0).WithMessage("page number should be greater than zero."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQuery.cs b/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQuery.cs index 2d26e6f..062495f 100644 --- a/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQuery.cs +++ b/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQuery.cs @@ -5,4 +5,4 @@ namespace MovieSearch.Application.Movies.Features.FindUpcomingMovies; public class FindUpcomingMoviesQuery : IQuery { public int Page { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQueryHandler.cs b/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQueryHandler.cs index be5e2ec..5e953f4 100644 --- a/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQueryHandler.cs +++ b/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQueryHandler.cs @@ -8,8 +8,7 @@ namespace MovieSearch.Application.Movies.Features.FindUpcomingMovies; -public class - FindUpcomingMoviesQueryHandler : IRequestHandler +public class FindUpcomingMoviesQueryHandler : IRequestHandler { private readonly IMapper _mapper; private readonly IMovieDbServiceClient _movieDbServiceClient; @@ -20,8 +19,10 @@ public FindUpcomingMoviesQueryHandler(IMovieDbServiceClient movieDbServiceClient _mapper = mapper; } - public async Task Handle(FindUpcomingMoviesQuery query, - CancellationToken cancellationToken) + public async Task Handle( + FindUpcomingMoviesQuery query, + CancellationToken cancellationToken + ) { Guard.Against.Null(query, nameof(FindUpcomingMoviesQuery)); @@ -29,6 +30,6 @@ public async Task Handle(FindUpcomingMoviesQuery var result = movies.Map(x => _mapper.Map(x)); - return new FindUpcomingMoviesQueryResult {MovieList = result}; + return new FindUpcomingMoviesQueryResult { MovieList = result }; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQueryResult.cs b/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQueryResult.cs index be1b594..5274684 100644 --- a/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQueryResult.cs +++ b/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/FindUpcomingMoviesQueryResult.cs @@ -6,4 +6,4 @@ namespace MovieSearch.Application.Movies.Features.FindUpcomingMovies; public class FindUpcomingMoviesQueryResult { public ListResultModel MovieList { get; set; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/SearchMovieQueryValidator.cs b/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/SearchMovieQueryValidator.cs index d6d149c..7f7deee 100644 --- a/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/SearchMovieQueryValidator.cs +++ b/src/MovieSearch.Application/Movies/Features/FindUpcomingMovies/SearchMovieQueryValidator.cs @@ -9,4 +9,4 @@ public FindUpcomingMoviesQueryQueryValidator() { RuleFor(query => query.Page).GreaterThan(0).WithMessage("page number should be greater than zero."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQuery.cs b/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQuery.cs index b019dc7..ac2344e 100644 --- a/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQuery.cs +++ b/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQuery.cs @@ -6,8 +6,13 @@ namespace MovieSearch.Application.Movies.Features.SearchMovie; public class SearchMovieQuery : IQuery { - public SearchMovieQuery(string searchKeywords, int page = 1, int year = 0, int primaryReleaseYear = 0, - bool includeAdult = false) + public SearchMovieQuery( + string searchKeywords, + int page = 1, + int year = 0, + int primaryReleaseYear = 0, + bool includeAdult = false + ) { SearchKeywords = searchKeywords; Page = page; @@ -22,15 +27,16 @@ public SearchMovieQuery(string searchKeywords, int page = 1, int year = 0, int p public string SearchKeywords { get; } public int Page { get; } - public class CachePolicy : ICachePolicy { public DateTime? AbsoluteExpirationRelativeToNow => DateTime.Now.AddMinutes(15); public string GetCacheKey(SearchMovieQuery query) { - return CacheKey.With(query.GetType(), - $"SearchKeywords_{query.SearchKeywords?.ToLower().Trim()}_Page_{query.Page}_IncludeAdult_{query.IncludeAdult.ToString()}_PrimaryReleaseYear_{query.PrimaryReleaseYear}_Year_{query.Year}"); + return CacheKey.With( + query.GetType(), + $"SearchKeywords_{query.SearchKeywords?.ToLower().Trim()}_Page_{query.Page}_IncludeAdult_{query.IncludeAdult.ToString()}_PrimaryReleaseYear_{query.PrimaryReleaseYear}_Year_{query.Year}" + ); } } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryHandler.cs b/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryHandler.cs index 1126f32..39065ce 100644 --- a/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryHandler.cs +++ b/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryHandler.cs @@ -23,12 +23,17 @@ public async Task Handle(SearchMovieQuery query, Cancell { Guard.Against.Null(query, nameof(SearchMovieQuery)); - var movies = await _movieDbServiceClient.SearchMovieAsync(query.SearchKeywords, - query.Page, query.IncludeAdult, query.Year, query - .PrimaryReleaseYear, cancellationToken); + var movies = await _movieDbServiceClient.SearchMovieAsync( + query.SearchKeywords, + query.Page, + query.IncludeAdult, + query.Year, + query.PrimaryReleaseYear, + cancellationToken + ); var result = movies.Map(x => _mapper.Map(x)); - return new SearchMovieQueryResult {MovieList = result}; + return new SearchMovieQueryResult { MovieList = result }; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryResult.cs b/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryResult.cs index 113e4c6..e798cd3 100644 --- a/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryResult.cs +++ b/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryResult.cs @@ -6,4 +6,4 @@ namespace MovieSearch.Application.Movies.Features.SearchMovie; public class SearchMovieQueryResult { public ListResultModel MovieList { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryValidator.cs b/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryValidator.cs index 74a5bd9..2e94d65 100644 --- a/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryValidator.cs +++ b/src/MovieSearch.Application/Movies/Features/SearchMovie/SearchMovieQueryValidator.cs @@ -7,11 +7,17 @@ public class SearchMovieQueryValidator : AbstractValidator public SearchMovieQueryValidator() { RuleFor(query => query.Page).GreaterThan(0).WithMessage("page number should be greater than zero."); - RuleFor(query => query.Year).Must(x => x >= 1700).When(c => c.Year > 0) + RuleFor(query => query.Year) + .Must(x => x >= 1700) + .When(c => c.Year > 0) .WithMessage("year should be greater than 1700."); //if it's not a default value - RuleFor(query => query.PrimaryReleaseYear).Must(x => x >= 1700).When(c => c.PrimaryReleaseYear > 0) + RuleFor(query => query.PrimaryReleaseYear) + .Must(x => x >= 1700) + .When(c => c.PrimaryReleaseYear > 0) .WithMessage("primary release year should be greater than 1700."); - RuleFor(query => query.SearchKeywords).NotEmpty().NotNull() + RuleFor(query => query.SearchKeywords) + .NotEmpty() + .NotNull() .WithMessage("search value should not be null or empty."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQuery.cs b/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQuery.cs index 1034c54..a3baeea 100644 --- a/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQuery.cs +++ b/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQuery.cs @@ -15,8 +15,10 @@ public class CachePolicy : ICachePolicy +public class SearchMovieByTitleQueryHandler : IRequestHandler { private readonly IMapper _mapper; private readonly IMovieDbServiceClient _movieDbServiceClient; @@ -20,16 +19,21 @@ public SearchMovieByTitleQueryHandler(IMovieDbServiceClient movieDbServiceClient _mapper = mapper; } - public async Task Handle(SearchMovieByTitleQuery query, - CancellationToken cancellationToken) + public async Task Handle( + SearchMovieByTitleQuery query, + CancellationToken cancellationToken + ) { Guard.Against.Null(query, nameof(SearchMovieByTitleQuery)); - var movies = await _movieDbServiceClient.SearchMovieAsync(query.SearchKeywords, query - .Page, cancellationToken: cancellationToken); + var movies = await _movieDbServiceClient.SearchMovieAsync( + query.SearchKeywords, + query.Page, + cancellationToken: cancellationToken + ); var result = movies.Map(x => _mapper.Map(x)); - return new SearchMovieByTitleQueryResult {MovieList = result}; + return new SearchMovieByTitleQueryResult { MovieList = result }; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQueryResult.cs b/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQueryResult.cs index 8bd4d22..3b7a60d 100644 --- a/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQueryResult.cs +++ b/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQueryResult.cs @@ -6,4 +6,4 @@ namespace MovieSearch.Application.Movies.Features.SearchMovieByTitle; public class SearchMovieByTitleQueryResult { public ListResultModel MovieList { get; set; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQueryValidator.cs b/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQueryValidator.cs index 05ee06c..9aca86d 100644 --- a/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQueryValidator.cs +++ b/src/MovieSearch.Application/Movies/Features/SearchMovieByTitle/SearchMovieByTitleQueryValidator.cs @@ -8,7 +8,9 @@ public class SearchMovieByTitleQueryValidator : AbstractValidator query.Page).GreaterThan(0).WithMessage("page number should be greater than zero."); - RuleFor(query => query.SearchKeywords).NotEmpty().NotNull() + RuleFor(query => query.SearchKeywords) + .NotEmpty() + .NotNull() .WithMessage("search value should not be null or empty."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Movies/MovieMappings.cs b/src/MovieSearch.Application/Movies/MovieMappings.cs index cc08303..98f40f7 100644 --- a/src/MovieSearch.Application/Movies/MovieMappings.cs +++ b/src/MovieSearch.Application/Movies/MovieMappings.cs @@ -14,4 +14,4 @@ public MovieMappings() CreateMap(); CreateMap(); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Dtos/PersonDto.cs b/src/MovieSearch.Application/People/Dtos/PersonDto.cs index 42cf7b3..4fe71d8 100644 --- a/src/MovieSearch.Application/People/Dtos/PersonDto.cs +++ b/src/MovieSearch.Application/People/Dtos/PersonDto.cs @@ -20,4 +20,4 @@ public class PersonDto public string PlaceOfBirth { get; init; } public double Popularity { get; init; } public string ProfilePath { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Dtos/PersonMovieCreditDto.cs b/src/MovieSearch.Application/People/Dtos/PersonMovieCreditDto.cs index 586d67c..3942ca4 100644 --- a/src/MovieSearch.Application/People/Dtos/PersonMovieCreditDto.cs +++ b/src/MovieSearch.Application/People/Dtos/PersonMovieCreditDto.cs @@ -33,4 +33,4 @@ public class PersonMovieCrewMemberDto public string PosterPath { get; init; } public DateTime? ReleaseDate { get; init; } public string Title { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Dtos/PersonTVShowCreditDto.cs b/src/MovieSearch.Application/People/Dtos/PersonTVShowCreditDto.cs index 60225e8..4f67563 100644 --- a/src/MovieSearch.Application/People/Dtos/PersonTVShowCreditDto.cs +++ b/src/MovieSearch.Application/People/Dtos/PersonTVShowCreditDto.cs @@ -33,4 +33,4 @@ public class PersonTVShowCrewMemberDto public string Name { get; init; } public string OriginalName { get; init; } public string PosterPath { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Exceptions/PersonMovieCreditsNotFoundException.cs b/src/MovieSearch.Application/People/Exceptions/PersonMovieCreditsNotFoundException.cs index 0487ae0..33fd497 100644 --- a/src/MovieSearch.Application/People/Exceptions/PersonMovieCreditsNotFoundException.cs +++ b/src/MovieSearch.Application/People/Exceptions/PersonMovieCreditsNotFoundException.cs @@ -4,8 +4,6 @@ namespace MovieSearch.Application.People.Exceptions; public class PersonMovieCreditsNotFoundException : NotFoundException { - public PersonMovieCreditsNotFoundException(int personId) : base( - $"can't find a person_movie_credits for a person with personId '{personId}' in the database.") - { - } -} \ No newline at end of file + public PersonMovieCreditsNotFoundException(int personId) + : base($"can't find a person_movie_credits for a person with personId '{personId}' in the database.") { } +} diff --git a/src/MovieSearch.Application/People/Exceptions/PersonNotFoundException.cs b/src/MovieSearch.Application/People/Exceptions/PersonNotFoundException.cs index 096f951..5987c98 100644 --- a/src/MovieSearch.Application/People/Exceptions/PersonNotFoundException.cs +++ b/src/MovieSearch.Application/People/Exceptions/PersonNotFoundException.cs @@ -4,7 +4,6 @@ namespace MovieSearch.Application.People.Exceptions; public class PersonNotFoundException : NotFoundException { - public PersonNotFoundException(int id) : base($"can't find a person with id '{id}' in the database.") - { - } -} \ No newline at end of file + public PersonNotFoundException(int id) + : base($"can't find a person with id '{id}' in the database.") { } +} diff --git a/src/MovieSearch.Application/People/Exceptions/PersonTVShowCreditsNotFoundException.cs b/src/MovieSearch.Application/People/Exceptions/PersonTVShowCreditsNotFoundException.cs index 37bcb7a..eda087a 100644 --- a/src/MovieSearch.Application/People/Exceptions/PersonTVShowCreditsNotFoundException.cs +++ b/src/MovieSearch.Application/People/Exceptions/PersonTVShowCreditsNotFoundException.cs @@ -4,8 +4,6 @@ namespace MovieSearch.Application.People.Exceptions; public class PersonTVShowCreditsNotFoundException : NotFoundException { - public PersonTVShowCreditsNotFoundException(int personId) : base( - $"can't find a person_tvshow_credits for a person with personId '{personId}' in the database.") - { - } -} \ No newline at end of file + public PersonTVShowCreditsNotFoundException(int personId) + : base($"can't find a person_tvshow_credits for a person with personId '{personId}' in the database.") { } +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonById/FindByIdQueryHandler.cs b/src/MovieSearch.Application/People/Features/FindPersonById/FindByIdQueryHandler.cs index 13d28d1..7aa6b5d 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonById/FindByIdQueryHandler.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonById/FindByIdQueryHandler.cs @@ -20,8 +20,7 @@ public FindPersonByIdQueryHandler(IMovieDbServiceClient movieDbServiceClient, IM _mapper = mapper; } - public async Task Handle(FindPersonByIdQuery query, - CancellationToken cancellationToken) + public async Task Handle(FindPersonByIdQuery query, CancellationToken cancellationToken) { Guard.Against.Null(query, nameof(FindPersonByIdQuery)); @@ -32,6 +31,6 @@ public async Task Handle(FindPersonByIdQuery query, var result = _mapper.Map(person); - return new FindPersonByIdQueryResult {Person = result}; + return new FindPersonByIdQueryResult { Person = result }; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonById/FindMovieByIdQueryValidator.cs b/src/MovieSearch.Application/People/Features/FindPersonById/FindMovieByIdQueryValidator.cs index 2e9a9fa..bd5a7d5 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonById/FindMovieByIdQueryValidator.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonById/FindMovieByIdQueryValidator.cs @@ -9,4 +9,4 @@ public FindPersonByIdQueryValidator() { RuleFor(query => query.PersonId).GreaterThan(0).WithMessage("personId should be greater than zero."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonById/FindPersonByIdQuery.cs b/src/MovieSearch.Application/People/Features/FindPersonById/FindPersonByIdQuery.cs index 57c08d4..ebfaac5 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonById/FindPersonByIdQuery.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonById/FindPersonByIdQuery.cs @@ -22,4 +22,4 @@ public string GetCacheKey(FindPersonByIdQuery query) return CacheKey.With(query.GetType(), query.PersonId.ToString()); } } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonById/FindPersonByIdQueryResult.cs b/src/MovieSearch.Application/People/Features/FindPersonById/FindPersonByIdQueryResult.cs index a101908..6c2fdb9 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonById/FindPersonByIdQueryResult.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonById/FindPersonByIdQueryResult.cs @@ -5,4 +5,4 @@ namespace MovieSearch.Application.People.Features.FindPersonById; public class FindPersonByIdQueryResult { public PersonDto Person { get; init; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQuery.cs b/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQuery.cs index 5d2cb1f..095e220 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQuery.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQuery.cs @@ -10,4 +10,4 @@ public FindPersonMovieCreditsQuery(int personId) } public int PersonId { get; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryHandler.cs b/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryHandler.cs index 9f7fd75..9697a47 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryHandler.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryHandler.cs @@ -9,9 +9,8 @@ namespace MovieSearch.Application.People.Features.FindPersonMovieCredits; -public class - FindPersonMovieCreditsQueryHandler : IRequestHandler +public class FindPersonMovieCreditsQueryHandler + : IRequestHandler { private readonly IMapper _mapper; private readonly IMovieDbServiceClient _movieDbServiceClient; @@ -22,13 +21,17 @@ public FindPersonMovieCreditsQueryHandler(IMovieDbServiceClient movieDbServiceCl _mapper = mapper; } - public async Task Handle(FindPersonMovieCreditsQuery query, - CancellationToken cancellationToken) + public async Task Handle( + FindPersonMovieCreditsQuery query, + CancellationToken cancellationToken + ) { Guard.Against.Null(query, nameof(FindPersonMovieCreditsQuery)); - var personMovieCredit = - await _movieDbServiceClient.GetPersonMovieCreditsAsync(query.PersonId, cancellationToken); + var personMovieCredit = await _movieDbServiceClient.GetPersonMovieCreditsAsync( + query.PersonId, + cancellationToken + ); if (personMovieCredit is null) throw new PersonMovieCreditsNotFoundException(query.PersonId); @@ -37,4 +40,4 @@ public async Task Handle(FindPersonMovieCredi return new FindPersonMovieCreditsQueryResult(result); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryResult.cs b/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryResult.cs index 34fa446..fee715b 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryResult.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryResult.cs @@ -10,4 +10,4 @@ public FindPersonMovieCreditsQueryResult(PersonMovieCreditDto personMovieCredit) } public PersonMovieCreditDto PersonMovieCredit { get; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryValidator.cs b/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryValidator.cs index b9ed8a1..062aa42 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryValidator.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonMovieCredits/FindPersonMovieCreditsQueryValidator.cs @@ -9,4 +9,4 @@ public FindPersonMovieCreditsQueryValidator() { RuleFor(query => query.PersonId).GreaterThan(0).WithMessage("personId should be greater than zero."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQuery.cs b/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQuery.cs index 169c9ce..a60dca9 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQuery.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQuery.cs @@ -10,4 +10,4 @@ public FindPersonTVShowCreditsQuery(int personId) } public int PersonId { get; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryHandler.cs b/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryHandler.cs index 82915eb..3e0b67e 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryHandler.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryHandler.cs @@ -9,9 +9,8 @@ namespace MovieSearch.Application.People.Features.FindPersonTVShowCredits; -public class - FindPersonTVShowCreditsQueryHandler : IRequestHandler +public class FindPersonTVShowCreditsQueryHandler + : IRequestHandler { private readonly IMapper _mapper; private readonly IMovieDbServiceClient _movieDbServiceClient; @@ -22,13 +21,17 @@ public FindPersonTVShowCreditsQueryHandler(IMovieDbServiceClient movieDbServiceC _mapper = mapper; } - public async Task Handle(FindPersonTVShowCreditsQuery query, - CancellationToken cancellationToken) + public async Task Handle( + FindPersonTVShowCreditsQuery query, + CancellationToken cancellationToken + ) { Guard.Against.Null(query, nameof(FindPersonTVShowCreditsQuery)); - var personTVShowCredit = await _movieDbServiceClient.GetPersonTvShowCreditsAsync(query.PersonId, - cancellationToken); + var personTVShowCredit = await _movieDbServiceClient.GetPersonTvShowCreditsAsync( + query.PersonId, + cancellationToken + ); if (personTVShowCredit is null) throw new PersonTVShowCreditsNotFoundException(query.PersonId); @@ -37,4 +40,4 @@ public async Task Handle(FindPersonTVShowCre return new FindPersonTVShowCreditsQueryResult(result); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryResult.cs b/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryResult.cs index c1d0a8b..2dcae79 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryResult.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryResult.cs @@ -10,4 +10,4 @@ public FindPersonTVShowCreditsQueryResult(PersonTVShowCreditDto personTvShowCred } public PersonTVShowCreditDto PersonTVShowCredit { get; } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryValidator.cs b/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryValidator.cs index 2b38bf5..ba95e85 100644 --- a/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryValidator.cs +++ b/src/MovieSearch.Application/People/Features/FindPersonTVShowCredits/FindPersonTVShowCreditsQueryValidator.cs @@ -9,4 +9,4 @@ public FindPersonTVShowCreditsQueryValidator() { RuleFor(query => query.PersonId).GreaterThan(0).WithMessage("personId should be greater than zero."); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/People/PeopleMappings.cs b/src/MovieSearch.Application/People/PeopleMappings.cs index 8eeaa5e..fd315e3 100644 --- a/src/MovieSearch.Application/People/PeopleMappings.cs +++ b/src/MovieSearch.Application/People/PeopleMappings.cs @@ -17,4 +17,4 @@ public PeopleMappings() CreateMap(); CreateMap(); } -} \ No newline at end of file +} diff --git a/src/MovieSearch.Application/Services/Clients/IMovieDbServiceClient.cs b/src/MovieSearch.Application/Services/Clients/IMovieDbServiceClient.cs index 4e1d654..d14ccbd 100644 --- a/src/MovieSearch.Application/Services/Clients/IMovieDbServiceClient.cs +++ b/src/MovieSearch.Application/Services/Clients/IMovieDbServiceClient.cs @@ -10,6 +10,7 @@ using MovieSearch.Core.TV; namespace MovieSearch.Application.Services.Clients; + //https://deviq.com/domain-driven-design/anti-corruption-layer //https://docs.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer //https://www.markhneedham.com/blog/2009/07/07/domain-driven-design-anti-corruption-layer/ @@ -29,8 +30,7 @@ public interface IMovieDbServiceClient /// /// /// - Task> GetNowPlayingAsync(int page, - CancellationToken cancellationToken = default); + Task> GetNowPlayingAsync(int page, CancellationToken cancellationToken = default); /// /// Search for movies. @@ -43,12 +43,14 @@ Task> GetNowPlayingAsync(int page, /// /// /// - Task> SearchMovieAsync(string keyword, + Task> SearchMovieAsync( + string keyword, int page = 1, bool includeAdult = false, int year = 0, int primaryReleaseYear = 0, - CancellationToken cancellationToken = default); + CancellationToken cancellationToken = default + ); /// /// Get a list of the current popular movies on TMDB. This list updates daily. @@ -57,8 +59,7 @@ Task> SearchMovieAsync(string keyword, /// /// /// - Task> GetPopularMoviesAsync(int page, - CancellationToken cancellationToken = default); + Task> GetPopularMoviesAsync(int page, CancellationToken cancellationToken = default); /// /// Get the most newly created movie. This is a live response and will continuously change. @@ -76,8 +77,7 @@ Task> GetPopularMoviesAsync(int page, /// /// /// - Task> GetUpComingMoviesAsync(int page, - CancellationToken cancellationToken = default); + Task> GetUpComingMoviesAsync(int page, CancellationToken cancellationToken = default); /// /// Get the top rated movies on TMDB. @@ -86,8 +86,7 @@ Task> GetUpComingMoviesAsync(int page, /// /// /// - Task> GetTopRatedMoviesAsync(int page, - CancellationToken cancellationToken = default); + Task> GetTopRatedMoviesAsync(int page, CancellationToken cancellationToken = default); /// /// Get the list of official genres for movies. @@ -97,11 +96,17 @@ Task> GetTopRatedMoviesAsync(int page, /// Task> GetMovieGenresAsync(CancellationToken cancellationToken = default); - Task> FindMoviesByGenreAsync(IReadOnlyList genreIds, - int page = 1, CancellationToken cancellationToken = default); + Task> FindMoviesByGenreAsync( + IReadOnlyList genreIds, + int page = 1, + CancellationToken cancellationToken = default + ); - Task> FindTvShowsByGenreAsync(IReadOnlyList genreIds, - int page = 1, CancellationToken cancellationToken = default); + Task> FindTvShowsByGenreAsync( + IReadOnlyList genreIds, + int page = 1, + CancellationToken cancellationToken = default + ); /// /// Get the list of official genres for TV shows. @@ -146,8 +151,11 @@ Task> FindTvShowsByGenreAsync(IReadOnlyList gen /// /// /// - Task> GetMovieReviewsAsync(int movieId, int page = 1, - CancellationToken cancellationToken = default); + Task> GetMovieReviewsAsync( + int movieId, + int page = 1, + CancellationToken cancellationToken = default + ); /// /// Get the reviews for a TV show. @@ -157,8 +165,11 @@ Task> GetMovieReviewsAsync(int movieId, int page = 1 /// /// /// - Task> GetTvShowReviewsAsync(int tvShowId, int page = 1, - CancellationToken cancellationToken = default); + Task> GetTvShowReviewsAsync( + int tvShowId, + int page = 1, + CancellationToken cancellationToken = default + ); /// /// Retrieve the details of a movie or TV show review. @@ -185,8 +196,7 @@ Task> GetTvShowReviewsAsync(int tvShowId, int page = /// /// /// - Task GetPersonMovieCreditsAsync(int personId, - CancellationToken cancellationToken = default); + Task GetPersonMovieCreditsAsync(int personId, CancellationToken cancellationToken = default); /// /// Get the TV show credits for a person. @@ -195,8 +205,7 @@ Task GetPersonMovieCreditsAsync(int personId, /// /// /// - Task GetPersonTvShowCreditsAsync(int personId, - CancellationToken cancellationToken = default); + Task GetPersonTvShowCreditsAsync(int personId, CancellationToken cancellationToken = default); /// /// Get the credits (cast and crew) that have been added to a TV show. @@ -205,8 +214,7 @@ Task GetPersonTvShowCreditsAsync(int personId, /// /// /// - Task GetTvShowCreditsAsync(int tvShowId, - CancellationToken cancellationToken = default); + Task GetTvShowCreditsAsync(int tvShowId, CancellationToken cancellationToken = default); /// /// Get the images that belong to a movie. @@ -233,8 +241,10 @@ Task GetTvShowCreditsAsync(int tvShowId, /// /// /// - Task<(List