├── .github
└── workflows
│ └── ci.yaml
├── .gitignore
├── LICENSE
├── README.md
├── WebInfrastructure.sln
├── WebInfrastructure.sln.DotSettings
├── appveyor.yml
├── build
├── NuGet.config
├── build.cake
├── build.ps1
└── build.sh
├── common.props
├── src
├── Infrastructure
│ ├── CQRS.Abstractions
│ │ ├── CQRS.Abstractions.csproj
│ │ ├── Commands
│ │ │ ├── IAsyncCommand.cs
│ │ │ ├── ICommand.cs
│ │ │ ├── ICommandContext.cs
│ │ │ └── ICommandsDispatcher.cs
│ │ └── Queries
│ │ │ ├── IAsyncCriterion.cs
│ │ │ ├── IAsyncQuery.cs
│ │ │ ├── ICriterion.cs
│ │ │ ├── IQueriesDispatcher.cs
│ │ │ ├── IQuery.cs
│ │ │ └── QueriesDispatcherExtensions.cs
│ ├── CQRS.Implementations
│ │ ├── CQRS.Implementations.csproj
│ │ ├── Commands
│ │ │ ├── CommandsDispatcher.cs
│ │ │ └── CommandsFactory
│ │ │ │ ├── GenericCommandsFactory.cs
│ │ │ │ └── ICommandsFactory.cs
│ │ └── Queries
│ │ │ ├── QueriesDispatcher.cs
│ │ │ └── QueriesFactory
│ │ │ ├── GenericQueriesFactory.cs
│ │ │ └── IQueriesFactory.cs
│ ├── Common
│ │ ├── Common.csproj
│ │ └── Extensions
│ │ │ ├── DictionaryExtensions.cs
│ │ │ ├── DoubleExtensions.cs
│ │ │ ├── EnumExtensions.cs
│ │ │ ├── EnumerableExtensions.cs
│ │ │ └── ParallelExtensions.cs
│ ├── Dapper
│ │ ├── ConnectionsFactory
│ │ │ ├── IConnectionsFactory.cs
│ │ │ ├── SqlConnectionsFactory.cs
│ │ │ └── SqlConnectionsFactoryOptions.cs
│ │ ├── Dapper.csproj
│ │ ├── Extensions
│ │ │ ├── CollectonReader.cs
│ │ │ ├── DbConnectionExtensions.cs
│ │ │ ├── IColumnsMappingConfigurator.cs
│ │ │ ├── IMappingInfoProvider.cs
│ │ │ ├── PropertyInfoProviders
│ │ │ │ ├── ExpandoObjectMappingInfoProvider.cs
│ │ │ │ ├── ManualConfiguredStrictTypeMappingInfoProvider.cs
│ │ │ │ └── StrictTypeMappingInfoProvider.cs
│ │ │ └── SqlConnectionExtensions.cs
│ │ ├── QueryObject.cs
│ │ ├── SessionsFactory
│ │ │ ├── ISession.cs
│ │ │ ├── ISessionsFactory.cs
│ │ │ ├── Session.cs
│ │ │ ├── SessionExtensions.cs
│ │ │ └── SessionsFactory.cs
│ │ ├── Tvp
│ │ │ ├── IMetaDataOptionsBuilder.cs
│ │ │ ├── Int32ValuesList.cs
│ │ │ ├── Int64ValuesList.cs
│ │ │ ├── MetaDataCreationOptions.cs
│ │ │ ├── MetaDataOptionsBuilder.cs
│ │ │ ├── PrimitiveValuesList.cs
│ │ │ ├── SqlTypesMapper.cs
│ │ │ └── TvpParameter.cs
│ │ └── TypesHandlers
│ │ │ └── CollectionsHandler.cs
│ ├── Directory.Build.props
│ ├── Queues.Abstractions
│ │ ├── Configuration
│ │ │ └── ServiceCollectionExtensions.cs
│ │ ├── IMessageHandler.cs
│ │ ├── MessagesProcessingService.cs
│ │ ├── MessagesProcessingServiceOptions.cs
│ │ ├── Queues.Abstractions.csproj
│ │ └── QueuesFactory
│ │ │ ├── Configuration
│ │ │ ├── QueueCreationOptions.cs
│ │ │ └── QueueCreationOptionsExtensions.cs
│ │ │ ├── ExceptionsHandling
│ │ │ ├── ErrorInformation.cs
│ │ │ ├── ExceptionHandlersFactory.cs
│ │ │ ├── ExceptionHandlingPolicy.cs
│ │ │ ├── Handlers
│ │ │ │ ├── EmptyExceptionHandler.cs
│ │ │ │ ├── ErrorsQueuingExceptionHandler.cs
│ │ │ │ ├── ExceptionHandlerBase.cs
│ │ │ │ └── RequeuingExceptionHandler.cs
│ │ │ └── IExceptionHandlersFactory.cs
│ │ │ ├── GenericQueuesFactory.cs
│ │ │ ├── IGenericQueuesFactory.cs
│ │ │ ├── ITypedQueue.cs
│ │ │ ├── ITypedQueuesFactory.cs
│ │ │ ├── IUntypedQueuesFactory.cs
│ │ │ ├── QueueBase.cs
│ │ │ └── QueueMessageDescriptionBase.cs
│ ├── Queues.RabbitMq
│ │ ├── Queues.RabbitMq.csproj
│ │ └── QueuesFactory
│ │ │ ├── Configuration
│ │ │ ├── RabbitCredentianls.cs
│ │ │ ├── RabbitQueueCreationOptions.cs
│ │ │ ├── ServiceCollectionExtensions.cs
│ │ │ └── TypedRabbitQueuesFactoryOptions.cs
│ │ │ ├── ExceptionsHandling
│ │ │ └── Handlers
│ │ │ │ └── RequeuingWithDelayExceptionHandler.cs
│ │ │ ├── RabbitMessageDescription.cs
│ │ │ ├── RabbitQueue.cs
│ │ │ ├── RabbitQueuesFactory.cs
│ │ │ └── TypedRabbitQueue.cs
│ ├── Web.Authentication
│ │ ├── JwtBearer
│ │ │ ├── ApplicationBuilderExtensions.cs
│ │ │ ├── Configuration
│ │ │ │ ├── Issuing
│ │ │ │ │ ├── IJwtBearerTokensIssuerBuilder.cs
│ │ │ │ │ ├── JwtBearerTokensIssuerBuilder.cs
│ │ │ │ │ ├── JwtBearerTokensIssuerBuilderExtensions.cs
│ │ │ │ │ ├── ServiceCollectionExtensions.cs
│ │ │ │ │ ├── TokenIssueEventHandlerSetup.cs
│ │ │ │ │ └── TokensIssuingOptionsExtensions.cs
│ │ │ │ └── Validation
│ │ │ │ │ ├── JwtBearerOptionsExtensions.cs
│ │ │ │ │ └── TokenValidationParametersExtensions.cs
│ │ │ ├── ITokenIssueEventHandler.cs
│ │ │ ├── Models
│ │ │ │ ├── TokenErrorResponseModel.cs
│ │ │ │ ├── TokenRequestModel.cs
│ │ │ │ └── TokenResponseModel.cs
│ │ │ ├── TokensIssuingMiddleware.cs
│ │ │ ├── TokensIssuingOptions.cs
│ │ │ └── UserClaimsProvider
│ │ │ │ ├── Exceptions
│ │ │ │ ├── IncorrectPasswordException.cs
│ │ │ │ └── LoginNotFoundException.cs
│ │ │ │ └── IUserClaimsProvider.cs
│ │ └── Web.Authentication.csproj
│ ├── Web.Conventions
│ │ ├── Responses
│ │ │ ├── ApiExceptionResponse.cs
│ │ │ ├── ApiResponse.cs
│ │ │ ├── ApiResponseError.cs
│ │ │ └── ExceptionDescription.cs
│ │ └── Web.Conventions.csproj
│ ├── Web.Hosting
│ │ ├── HostBuilderExtensions.cs
│ │ ├── Web.Hosting.csproj
│ │ └── WebApiBaseStartup.cs
│ ├── Web.Integration
│ │ ├── BaseApiClient
│ │ │ ├── BaseClient.cs
│ │ │ ├── Configuration
│ │ │ │ ├── BaseClientOptions.cs
│ │ │ │ ├── HttpClientBuilderExtensions.cs
│ │ │ │ ├── HttpClientHandlerExtensions.cs
│ │ │ │ ├── OptionsBuilderExtensions.cs
│ │ │ │ └── ServiceCollectionExtensions.cs
│ │ │ ├── Exceptions
│ │ │ │ ├── ApiException.cs
│ │ │ │ ├── BadRequestException.cs
│ │ │ │ ├── NotFoundException.cs
│ │ │ │ └── UnauthorizedException.cs
│ │ │ └── RequestHeadersExtensions.cs
│ │ ├── BaseApiFluentClient
│ │ │ ├── BaseFluentClient.cs
│ │ │ └── FluentChainedTask.cs
│ │ └── Web.Integration.csproj
│ ├── Web.Logging.Abstractions
│ │ ├── ContextsCapturing
│ │ │ ├── CapturedData
│ │ │ │ └── CapturedActionExecutingContext.cs
│ │ │ └── LoggerExtensions.cs
│ │ └── Web.Logging.Abstractions.csproj
│ ├── Web.Logging.NLog
│ │ ├── ConfigurationBuilderExtensions.cs
│ │ ├── LoggingBuilderExtensions.cs
│ │ └── Web.Logging.NLog.csproj
│ ├── Web.Logging.Serilog
│ │ ├── Configuration
│ │ │ └── LoggerConfigurationExtensions.cs
│ │ ├── Enrichers
│ │ │ ├── LogEventHashEnricher.cs
│ │ │ ├── LoggerEnrichmentConfigurationExtensions.cs
│ │ │ └── MessageTemplateHashEnricher.cs
│ │ ├── Formatting
│ │ │ └── RenderedJsonFormatter.cs
│ │ └── Web.Logging.Serilog.csproj
│ ├── Web.Serialization.Abstractions
│ │ ├── ISerializer.cs
│ │ └── Web.Serialization.Abstractions.csproj
│ ├── Web.Serialization.Jil
│ │ ├── Configuration
│ │ │ ├── MvcBuilderExtensions.cs
│ │ │ ├── MvcJilOptions.cs
│ │ │ ├── MvcOptionsSetup.cs
│ │ │ └── OptionsExtensions.cs
│ │ ├── Formatters
│ │ │ ├── JilInputFormatter.cs
│ │ │ ├── JilOutputFormatter.cs
│ │ │ └── MediaTypeHeaderValues.cs
│ │ ├── Serializer
│ │ │ └── JilSerializer.cs
│ │ └── Web.Serialization.Jil.csproj
│ ├── Web.Serialization.JsonNet
│ │ ├── Configuration
│ │ │ ├── JsonSerializerSettingsExtensions.cs
│ │ │ └── MvcBuilderExtensions.cs
│ │ ├── JsonConverters
│ │ │ └── DateTimeConverter.cs
│ │ ├── PropertyNamesResolvers
│ │ │ └── SnakeCasePropertyNamesContractResolver.cs
│ │ ├── Serializer
│ │ │ └── JsonNetSerializer.cs
│ │ └── Web.Serialization.JsonNet.csproj
│ ├── Web.Serialization.Protobuf
│ │ ├── Configuration
│ │ │ ├── MvcBuilderExtensions.cs
│ │ │ ├── MvcOptionsSetup.cs
│ │ │ ├── MvcProtobufOptions.cs
│ │ │ └── RuntimeTypeModelExtensions.cs
│ │ ├── Formatters
│ │ │ ├── MediaTypeHeaderValues.cs
│ │ │ ├── ProtobufInputFormatter.cs
│ │ │ ├── ProtobufOutputFormatter.cs
│ │ │ └── Surrogates
│ │ │ │ └── DateTimeOffsetSurrogate.cs
│ │ ├── Serializer
│ │ │ └── ProtobufSerializer.cs
│ │ └── Web.Serialization.Protobuf.csproj
│ ├── Web.Testing
│ │ ├── BaseApiClientTests.cs
│ │ ├── BaseApiTestsFixture.cs
│ │ ├── BaseServiceClientTests.cs
│ │ ├── CustomAutofacServiceProviderFactory.cs
│ │ ├── Extensions
│ │ │ ├── ConfigurationBuilderExtensions.cs
│ │ │ ├── MockLoggerExtensions.cs
│ │ │ └── WebHostBuilderExtensions.cs
│ │ └── Web.Testing.csproj
│ └── Web
│ │ ├── Configuration
│ │ └── ConfigurationBuilderExtensions.cs
│ │ ├── Documentation
│ │ └── AuthResponsesOperationFilter.cs
│ │ ├── ExceptionsHandling
│ │ ├── ApplicationBuilderExtensions.cs
│ │ ├── MvcOptionsExtensions.cs
│ │ ├── ServiceCollectionExtensions.cs
│ │ ├── UnhandledExceptionsFilterAttribute.cs
│ │ ├── UnhandledExceptionsLoggingMiddleware.cs
│ │ └── UnhandledExceptionsStartupFilter.cs
│ │ ├── Routing
│ │ ├── CentralPrefixConvention.cs
│ │ └── MvcOptionsExtensions.cs
│ │ ├── Validation
│ │ ├── ModelValidationFilterAttribute.cs
│ │ ├── MvcOptionsExtensions.cs
│ │ └── ParametersValidationFilterAttribute.cs
│ │ └── Web.csproj
├── Web.Application
│ ├── Controllers
│ │ ├── AccountController.cs
│ │ └── ValuesController.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Services
│ │ ├── TokenIssueEventHandler.cs
│ │ └── UserClaimsProvider.cs
│ └── Web.Application.csproj
├── Web.Client
│ ├── ApiClient.Account.cs
│ ├── ApiClient.Values.cs
│ ├── ApiClient.cs
│ ├── ApiClientOptions.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── ServicesClients
│ │ ├── AccountController
│ │ │ ├── AccountControllerClient.cs
│ │ │ ├── AccountControllerClientOptions.cs
│ │ │ └── ServiceCollectionExtensions.cs
│ │ └── ValuesService
│ │ │ ├── IValuesServiceClient.cs
│ │ │ ├── ServiceCollectionExtensions.cs
│ │ │ ├── ValuesServiceClient.cs
│ │ │ └── ValuesServiceClientOptions.cs
│ └── Web.Client.csproj
├── Web.DataAccess
│ ├── Commands
│ │ ├── DeleteValueAsyncCommand.cs
│ │ └── SetValueCommand.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Queries
│ │ ├── GetAllValuesQuery.cs
│ │ └── GetValueQuery.cs
│ ├── Repositories
│ │ ├── IValuesRepository.cs
│ │ └── Impl
│ │ │ └── InMemoryValuesRepository.cs
│ └── Web.DataAccess.csproj
├── Web.Domain
│ ├── CommandContexts
│ │ ├── DeleteValueAsyncCommandContext.cs
│ │ └── SetValueCommandContext.cs
│ ├── Criteria
│ │ ├── GetAllValuesQueryCriterion.cs
│ │ └── GetValueQueryCriterion.cs
│ ├── Dtos
│ │ └── DefaultConfigurationValues.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── Web.Domain.csproj
├── Web.Migrations
│ ├── Migration201703191215.cs
│ └── Web.Migrations.csproj
├── Web.Models
│ ├── Input
│ │ └── ValuesModificationRequest.cs
│ └── Web.Models.csproj
└── Web
│ ├── Installers
│ ├── CommandsInstaller.cs
│ ├── DataAccessInstaller.cs
│ ├── QueriesInstaller.cs
│ └── ServicesInstaller.cs
│ ├── Program.cs
│ ├── Properties
│ ├── PublishProfiles
│ │ ├── DevelopmentProfile.pubxml
│ │ └── StagingProfile.pubxml
│ └── launchSettings.json
│ ├── Startup.cs
│ ├── Web.Generic.config
│ ├── Web.csproj
│ ├── appsettings.Development.json
│ ├── appsettings.Staging.json
│ └── appsettings.json
└── test
├── Infrastructure
├── CQRS.Implementations.Tests
│ ├── CQRS.Implementations.Tests.csproj
│ └── QueriesDispatcherTests.cs
├── Common.Tests
│ ├── Common.Tests.csproj
│ └── Extensions
│ │ ├── DictionaryExtensionsTests.cs
│ │ ├── DoubleExtensionsTests.cs
│ │ ├── EnumExtensionsTests.cs
│ │ ├── EnumerableExtensionsTests.cs
│ │ └── ParallelExtensionsTests.cs
├── Dapper.Tests
│ ├── Dapper.Tests.csproj
│ ├── DbUsingTestBase.cs
│ ├── Extensions
│ │ └── SqlConnectionExtensionsTests.cs
│ ├── SessionsFactory
│ │ └── SessionsTests.cs
│ ├── Tvp
│ │ ├── PrimitiveValuesListTests.cs
│ │ └── TvpParameterTests.cs
│ └── TypesHandlers
│ │ └── CollectionsHandlerTests.cs
├── Queues.RabbitMq.Tests
│ ├── ExceptionHandlersFactoryTests.cs
│ ├── GenericQueuesFactoryTests.cs
│ ├── Handlers
│ │ ├── CatchingMessageHandler.cs
│ │ └── ThrowingExceptionMessageHandler.cs
│ ├── MessagesProcessingServiceTests.cs
│ ├── ProcessingService
│ │ ├── NotificationsProcessingService.cs
│ │ ├── NotificationsProcessingServiceOptions.cs
│ │ └── ServiceCollectionExtensions.cs
│ ├── QueueCreationOptionsExtensionsTests.cs
│ ├── Queues.RabbitMq.Tests.csproj
│ ├── RabbitQueueTests.cs
│ ├── ServiceCollectionExtensionsTests.cs
│ ├── appsettings.Development.Appveyor.Linux.json
│ ├── appsettings.Development.Appveyor.Windows.json
│ ├── appsettings.Development.Travis.json
│ ├── appsettings.Development.json
│ └── appsettings.json
└── Web.Tests
│ ├── Authentication
│ └── JwtBearer
│ │ ├── JwtBearerOptionsExtensionsTests.cs
│ │ ├── TokenValidationParametersExtensionsTests.cs
│ │ └── TokensIssuingOptionsExtensionsTests.cs
│ ├── Conventions
│ └── Responses
│ │ └── ExceptionDescriptionTests.cs
│ ├── ExceptionsHandling
│ └── UnhandledExceptionsLoggingMiddlewareTests.cs
│ ├── Integration
│ └── BaseApiClient
│ │ ├── HttpClientBuilderExtensionsTests.cs
│ │ ├── HttpClientHandlerExtensionsTests.cs
│ │ ├── HttpRequestHeadersExtensionsTests.cs
│ │ ├── OptionsBuilderExtensionsTests.cs
│ │ └── ServiceCollectionExtensionsTests.cs
│ ├── Serialization
│ ├── JsonNet
│ │ ├── DateTimeConverterTests.cs
│ │ └── SnakeCasePropertyNamesContractResolverTests.cs
│ └── Protobuf
│ │ ├── DateTimeOffsetSurrogateTests.cs
│ │ └── RuntimeTypeModelExtensionsTests.cs
│ └── Web.Tests.csproj
└── Web.Tests
├── AccountApiClientTests.cs
├── ApiTestsCollection.cs
├── ServicesClientsTests.cs
├── ValuesApiClientTests.cs
├── ValuesControllerTests.cs
├── Web.Tests.csproj
├── appsettings.Development.json
├── appsettings.Staging.Appveyor.Linux.json
├── appsettings.Staging.Appveyor.Windows.json
├── appsettings.Staging.Travis.json
├── appsettings.Staging.json
└── appsettings.json
/.gitignore:
--------------------------------------------------------------------------------
1 | _ReSharper.*/
2 | build/artifacts/
3 | build/tools/
4 | bin
5 | obj
6 | Backup
7 | *.user
8 | *.suo
9 | *.Cache
10 | publish
11 | *.deploy
12 | Debug
13 | Release
14 | UpgradeLog.*
15 | _UpgradeReport_Files/
16 | artifacts/
17 | _UpgradeReport*
18 | *.dbmdl
19 | *.ncrunchproject
20 | *.ncrunchsolution
21 | /.vs/
22 | project.lock.json
23 | logs
24 | web.config
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Dmitriy Litichevskiy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: '{build}'
2 | image: Visual Studio 2019
3 | configuration: Release
4 | environment:
5 | ASPNETCORE_ENVIRONMENT: Staging
6 | deploy: off
7 | branches:
8 | only:
9 | - develop
10 | - /release.*/
11 | - master
12 | skip_commits:
13 | files:
14 | - LICENSE
15 | - README.md
16 | - .travis.yml
17 | - WebInfrastructure.sln.DotSettings
18 | services: mssql2017
19 | install:
20 | - ps: choco install rabbitmq --version 3.7.7 -y
21 | build_script:
22 | - ps: >-
23 | cd build
24 |
25 | .\build.ps1 -target Test --settings_skipverification=true
26 |
--------------------------------------------------------------------------------
/build/NuGet.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/build/build.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | Param(
3 | [string]$Script = "build.cake",
4 | [string]$Target = "Default",
5 | [ValidateSet("Release", "Debug")]
6 | [string]$Configuration = "Release",
7 | [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
8 | [string]$Verbosity = "Verbose",
9 | [Alias("DryRun","Noop")]
10 | [switch]$WhatIf,
11 | [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
12 | [string[]]$ScriptArgs
13 | )
14 |
15 | Write-Host -f Yellow "Preparing to run build script..."
16 | if(!$PSScriptRoot){
17 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
18 | }
19 |
20 | $UseDryRun = "";
21 | if($WhatIf.IsPresent)
22 | {
23 | $UseDryRun = "--dryrun"
24 | }
25 |
26 | Write-Host -f Yellow "Looking for Cake.Tool..."
27 | if (-Not (& dotnet tool list -g | Select-String "cake.tool")) {
28 | & dotnet tool install --global --configfile ./NuGet.config Cake.Tool
29 | }
30 |
31 | Write-Host -f Yellow "Running build script..."
32 | & dotnet cake $Script --nuget_useinprocessclient=true --target=$Target --configuration=$Configuration --verbosity=$Verbosity $UseDryRun $ScriptArgs
33 | exit $LASTEXITCODE
34 |
--------------------------------------------------------------------------------
/build/build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | SCRIPT="build.cake"
4 | TARGET="Default"
5 | CONFIGURATION="Release"
6 | VERBOSITY="verbose"
7 | DRYRUN=
8 | SHOW_VERSION=false
9 | SCRIPT_ARGUMENTS=()
10 |
11 | while [[ $# -gt 0 ]]; do
12 | case $1 in
13 | -s|--script) SCRIPT="$2"; shift ;;
14 | -t|--target) TARGET="$2"; shift ;;
15 | -c|--configuration) CONFIGURATION="$2"; shift ;;
16 | -v|--verbosity) VERBOSITY="$2"; shift ;;
17 | -d|--dryrun) DRYRUN="-dryrun" ;;
18 | --version) SHOW_VERSION=true ;;
19 | --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;;
20 | *) SCRIPT_ARGUMENTS+=("$1") ;;
21 | esac
22 | shift
23 | done
24 |
25 | if [[ $(dotnet tool list -g) != *"cake.tool"* ]]; then
26 | dotnet tool install --global --configfile ./NuGet.config Cake.Tool
27 | fi
28 |
29 | if $SHOW_VERSION; then
30 | dotnet cake --version
31 | else
32 | dotnet cake $SCRIPT --nuget_useinprocessclient=true --settings_skipverification=true --verbosity=$VERBOSITY --configuration=$CONFIGURATION --target=$TARGET $DRYRUN "${SCRIPT_ARGUMENTS[@]}"
33 | fi
--------------------------------------------------------------------------------
/common.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 2.0.1
4 | $([System.DateTime]::op_Subtraction($([System.DateTime]::get_UtcNow().get_Date()),$([System.DateTime]::new(2018,1,1))).get_TotalDays())
5 | $(VersionPrefix).$(Build)
6 | $(VersionPrefix).$(Build)
7 |
8 |
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Abstractions/CQRS.Abstractions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with abstractions for CQRS pattern
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netstandard1.1
12 | Skeleton.CQRS.Abstractions
13 | Skeleton.CQRS.Abstractions
14 | Skeleton.CQRS.Abstractions
15 | CQRS
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Abstractions/Commands/IAsyncCommand.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Abstractions.Commands
2 | {
3 | using System.Threading.Tasks;
4 |
5 | ///
6 | /// Interface for asynchronous commands
7 | ///
8 | /// Command context type
9 | public interface IAsyncCommand where TCommandContext : ICommandContext
10 | {
11 | ///
12 | /// Method for command execution
13 | ///
14 | /// Information needed for command execution
15 | Task Execute(TCommandContext commandContext);
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Abstractions/Commands/ICommand.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Abstractions.Commands
2 | {
3 | ///
4 | /// Interface for synchronous commands
5 | ///
6 | /// Command context type
7 | public interface ICommand where TCommandContext : ICommandContext
8 | {
9 | ///
10 | /// Method for command execution
11 | ///
12 | /// Information needed for command execution
13 | void Execute(TCommandContext commandContext);
14 | }
15 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Abstractions/Commands/ICommandContext.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Abstractions.Commands
2 | {
3 | ///
4 | /// Interface for commands contexts marking
5 | ///
6 | public interface ICommandContext
7 | {
8 |
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Abstractions/Commands/ICommandsDispatcher.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Abstractions.Commands
2 | {
3 | using System.Threading.Tasks;
4 |
5 | ///
6 | /// Commands dispatcher interface
7 | ///
8 | public interface ICommandsDispatcher
9 | {
10 | ///
11 | /// Method for synchronous commands execution
12 | ///
13 | /// Command context type
14 | /// Information needed for commands execution
15 | void Execute(TCommandContext commandContext) where TCommandContext : ICommandContext;
16 |
17 | ///
18 | /// Method for asynchronous commands execution
19 | ///
20 | /// Command context type
21 | /// Information needed for commands execution
22 | Task ExecuteAsync(TCommandContext commandContext) where TCommandContext : ICommandContext;
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Abstractions/Queries/IAsyncCriterion.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Abstractions.Queries
2 | {
3 | using System.Threading.Tasks;
4 | public interface IAsyncCriterion : ICriterion>
5 | {
6 | }
7 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Abstractions/Queries/IAsyncQuery.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Abstractions.Queries
2 | {
3 | using System.Threading.Tasks;
4 |
5 | ///
6 | /// Interface for asynchronously processed queries
7 | ///
8 | /// Query criterion type
9 | /// Query result type
10 | public interface IAsyncQuery : IQuery> where TCriterion : IAsyncCriterion
11 | {
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Abstractions/Queries/ICriterion.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Abstractions.Queries
2 | {
3 | ///
4 | /// Interface for queries criterions marking
5 | ///
6 | public interface ICriterion
7 | {
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Abstractions/Queries/IQueriesDispatcher.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Abstractions.Queries
2 | {
3 | ///
4 | /// Queries dispatcher interface
5 | ///
6 | public interface IQueriesDispatcher
7 | {
8 | ///
9 | /// Method for queries execution
10 | ///
11 | /// Query result type
12 | /// Information needed for queries execution
13 | /// Query result
14 | TResult Execute(ICriterion criterion);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Abstractions/Queries/IQuery.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Abstractions.Queries
2 | {
3 | ///
4 | /// Interface for queries
5 | ///
6 | /// Query criterion type
7 | /// Query result type
8 | public interface IQuery where TCriterion : ICriterion
9 | {
10 | ///
11 | /// Method for criterion execution
12 | ///
13 | /// Information needed for criterion execution
14 | /// Query result
15 | TResult Ask(TCriterion criterion);
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Abstractions/Queries/QueriesDispatcherExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Abstractions.Queries
2 | {
3 | using System.Threading.Tasks;
4 |
5 | ///
6 | /// Extensions for queries dispatcher
7 | ///
8 | public static class QueriesDispatcherExtensions
9 | {
10 | ///
11 | /// Method for asynchronous queries execution
12 | ///
13 | /// Query result type
14 | /// Queries dispatcher
15 | /// Information needed for queries execution
16 | /// Task for asynchronous operation
17 | public static Task ExecuteAsync(this IQueriesDispatcher queriesDispatcher, IAsyncCriterion criterion)
18 | {
19 | return queriesDispatcher.Execute(criterion);
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Implementations/CQRS.Implementations.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with implementations of CQRS pattern
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netstandard1.1
12 | Skeleton.CQRS.Implementations
13 | Skeleton.CQRS.Implementations
14 | Skeleton.CQRS.Implementations
15 | CQRS
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Implementations/Commands/CommandsFactory/GenericCommandsFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Implementations.Commands.CommandsFactory
2 | {
3 | using System;
4 | using Abstractions.Commands;
5 |
6 | ///
7 | /// Commands factory implementation based on IServiceProvider
8 | ///
9 | public class GenericCommandsFactory : ICommandsFactory
10 | {
11 | private readonly IServiceProvider _serviceProvider;
12 |
13 | ///
14 | /// Constructor
15 | ///
16 | public GenericCommandsFactory(IServiceProvider serviceProvider)
17 | {
18 | if(serviceProvider == null)
19 | throw new ArgumentNullException(nameof(serviceProvider));
20 |
21 | _serviceProvider = serviceProvider;
22 | }
23 |
24 | ///
25 | public ICommand CreateCommand() where TCommandContext : ICommandContext
26 | {
27 | return (ICommand)_serviceProvider.GetService(typeof(ICommand));
28 | }
29 |
30 | ///
31 | public IAsyncCommand CreateAsyncCommand() where TCommandContext : ICommandContext
32 | {
33 | return (IAsyncCommand)_serviceProvider.GetService(typeof(IAsyncCommand));
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Implementations/Commands/CommandsFactory/ICommandsFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Implementations.Commands.CommandsFactory
2 | {
3 | using Abstractions.Commands;
4 |
5 | ///
6 | /// Commands factory interface
7 | ///
8 | public interface ICommandsFactory
9 | {
10 | ///
11 | /// Method for synchronous commands creation
12 | ///
13 | /// Command context type
14 | /// Command instance
15 | ICommand CreateCommand() where TCommandContext : ICommandContext;
16 |
17 | ///
18 | /// Method for asynchronous commands creation
19 | ///
20 | /// Command context type
21 | /// Command instance
22 | IAsyncCommand CreateAsyncCommand() where TCommandContext : ICommandContext;
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Implementations/Queries/QueriesFactory/GenericQueriesFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Implementations.Queries.QueriesFactory
2 | {
3 | using System;
4 | using Abstractions.Queries;
5 |
6 | ///
7 | /// Queries factory based on IServiceProvider
8 | ///
9 | public class GenericQueriesFactory : IQueriesFactory
10 | {
11 | private readonly IServiceProvider _serviceProvider;
12 |
13 | ///
14 | /// Constructor
15 | ///
16 | public GenericQueriesFactory(IServiceProvider serviceProvider)
17 | {
18 | if(serviceProvider == null)
19 | throw new ArgumentNullException(nameof(serviceProvider));
20 |
21 | _serviceProvider = serviceProvider;
22 | }
23 |
24 | ///
25 | public IQuery Create() where TCriterion : ICriterion
26 | {
27 | return (IQuery)_serviceProvider.GetService(typeof(IQuery));
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/Infrastructure/CQRS.Implementations/Queries/QueriesFactory/IQueriesFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.CQRS.Implementations.Queries.QueriesFactory
2 | {
3 | using Abstractions.Queries;
4 |
5 | ///
6 | /// Queries factory interface
7 | ///
8 | public interface IQueriesFactory
9 | {
10 | ///
11 | /// Method for qsueries creation
12 | ///
13 | /// Query criterion type
14 | /// Query result type
15 | /// Query instance
16 | IQuery Create() where TCriterion : ICriterion;
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Common/Common.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with common extensions and objects for applications development
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netstandard1.6
12 | Skeleton.Common
13 | Skeleton.Common
14 | Skeleton.Common
15 | Common extensions
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/Infrastructure/Common/Extensions/DictionaryExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Common.Extensions
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | public static class DictionaryExtensions
7 | {
8 | public static TValue GetOrDefault(this IReadOnlyDictionary dictionary, TKey key)
9 | {
10 | return dictionary.TryGetValue(key, out var value) ? value : default(TValue);
11 | }
12 |
13 | public static TValue GetOrEmpty(this IReadOnlyDictionary dictionary, TKey key) where TValue : new()
14 | {
15 | return dictionary.TryGetValue(key, out var value) ? value : new TValue();
16 | }
17 |
18 | public static TValue GetOrValue(this IReadOnlyDictionary dictionary, TKey key, TValue replacement)
19 | {
20 | return dictionary.TryGetValue(key, out var value) ? value : replacement;
21 | }
22 |
23 | public static TValue GetOrValue(
24 | this IReadOnlyDictionary dictionary,
25 | TKey key,
26 | Func valueFunc)
27 | {
28 | return dictionary.TryGetValue(key, out var value) ? value : valueFunc(key);
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Common/Extensions/DoubleExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Common.Extensions
2 | {
3 | using System;
4 |
5 | public static class DoubleExtensions
6 | {
7 | public const double DefaultAccuracy = 1e-7;
8 |
9 | private static double GetUsedAccuracy(double? accuracy) => accuracy ?? DefaultAccuracy;
10 |
11 | public static bool Equal(this double first, double second, double? accuracy = null)
12 | {
13 | var usedAccuracy = GetUsedAccuracy(accuracy);
14 | return first <= second + usedAccuracy
15 | && first + usedAccuracy >= second;
16 | }
17 |
18 | public static bool NotEqual(this double first, double second, double? accuracy = null)
19 | {
20 | var usedAccuracy = GetUsedAccuracy(accuracy);
21 | return first + usedAccuracy < second
22 | || first > second + usedAccuracy;
23 | }
24 |
25 | public static bool LessOrEqual(this double first, double second, double? accuracy = null)
26 | {
27 | return first <= second + GetUsedAccuracy(accuracy);
28 | }
29 |
30 | public static bool Less(this double first, double second, double? accuracy = null)
31 | {
32 | return first + GetUsedAccuracy(accuracy) < second;
33 | }
34 |
35 | public static bool GreaterOrEqual(this double first, double second, double? accuracy = null)
36 | {
37 | return first + GetUsedAccuracy(accuracy) >= second;
38 | }
39 |
40 | public static bool Greater(this double first, double second, double? accuracy = null)
41 | {
42 | return first > second + GetUsedAccuracy(accuracy);
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Common/Extensions/EnumExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Common.Extensions
2 | {
3 | using System;
4 | using System.ComponentModel;
5 | using System.Reflection;
6 |
7 | public static class EnumExtensions
8 | {
9 | public static string GetDescription(this Enum member)
10 | {
11 | var memberTypeInfo = member.GetType().GetTypeInfo();
12 |
13 | if (memberTypeInfo.IsEnum == false)
14 | throw new ArgumentOutOfRangeException(nameof(member), "member is not enum");
15 |
16 | var fieldInfo = memberTypeInfo.GetField(member.ToString());
17 | if (fieldInfo == null)
18 | return null;
19 |
20 | var attributes = fieldInfo.GetCustomAttributes(false).AsArray();
21 |
22 | if (attributes.Length > 0)
23 | return attributes[0].Description;
24 |
25 | return member.ToString();
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Common/Extensions/ParallelExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Common.Extensions
2 | {
3 | using System;
4 | using System.Collections.Concurrent;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 |
10 | public static class ParallelExtensions
11 | {
12 | public static IEnumerable> ForEachAsync(
13 | this IEnumerable source,
14 | Func body,
15 | int degreeOfParallelism)
16 | {
17 | if (source == null)
18 | throw new ArgumentNullException(nameof(source));
19 | if (body == null)
20 | throw new ArgumentNullException(nameof(body));
21 |
22 | var sourceArray = source.ToArray();
23 | var completedTask = -1;
24 |
25 | var taskCompletions = new TaskCompletionSource[sourceArray.Length];
26 | for (var i = 0; i < taskCompletions.Length; i++)
27 | taskCompletions[i] = new TaskCompletionSource();
28 |
29 | foreach (var partition in Partitioner.Create(sourceArray).GetPartitions(degreeOfParallelism))
30 | Task.Run(
31 | () =>
32 | {
33 | while (partition.MoveNext())
34 | {
35 | var result = body(partition.Current);
36 |
37 | var finishedTaskIndex = Interlocked.Increment(ref completedTask);
38 | taskCompletions[finishedTaskIndex].SetResult(result);
39 | }
40 | }
41 | );
42 |
43 | return taskCompletions.Select(tcs => tcs.Task);
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/ConnectionsFactory/IConnectionsFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.ConnectionsFactory
2 | {
3 | using System.Data;
4 |
5 | public interface IConnectionsFactory
6 | {
7 | IDbConnection Create();
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/ConnectionsFactory/SqlConnectionsFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.ConnectionsFactory
2 | {
3 | using System;
4 | using System.Data;
5 | using System.Data.SqlClient;
6 | using Microsoft.Extensions.Options;
7 |
8 | public class SqlConnectionsFactory : IConnectionsFactory
9 | {
10 | private readonly SqlConnectionsFactoryOptions _options;
11 |
12 | public SqlConnectionsFactory(IOptions options)
13 | {
14 | if (options == null)
15 | throw new ArgumentNullException(nameof(options));
16 | if (string.IsNullOrWhiteSpace(options.Value.SqlServer))
17 | throw new ArgumentNullException(nameof(SqlConnectionsFactoryOptions.SqlServer));
18 |
19 | _options = options.Value;
20 | }
21 |
22 | public IDbConnection Create()
23 | {
24 | var sqlConnection = new SqlConnection(_options.SqlServer);
25 | sqlConnection.Open();
26 | return sqlConnection;
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/ConnectionsFactory/SqlConnectionsFactoryOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.ConnectionsFactory
2 | {
3 | public class SqlConnectionsFactoryOptions
4 | {
5 | public string SqlServer { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/Dapper.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with common extensions and helpers for use Dapper in code
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netstandard2.0
12 | Skeleton.Dapper
13 | Skeleton.Dapper
14 | Skeleton.Dapper
15 | Helpers for Dapper;TVP;Bulk Copy
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/Extensions/IColumnsMappingConfigurator.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.Extensions
2 | {
3 | using System;
4 | using System.Linq.Expressions;
5 |
6 | public interface IColumnsMappingConfigurator where TEntity : class
7 | {
8 | IColumnsMappingConfigurator WithProperty(
9 | Expression> member,
10 | string tableColumnName = null);
11 |
12 | IColumnsMappingConfigurator WithFunction(
13 | Func valuesProvider,
14 | string tableColumnName);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/Extensions/IMappingInfoProvider.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.Extensions
2 | {
3 | using System.Data.SqlClient;
4 |
5 | public interface IMappingInfoProvider
6 | {
7 | object GetValue(int ordinal, object current);
8 | SqlBulkCopyColumnMappingCollection MappingsCollection { get; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/Extensions/PropertyInfoProviders/ExpandoObjectMappingInfoProvider.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.Extensions.PropertyInfoProviders
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Data.SqlClient;
6 |
7 | public class ExpandoObjectMappingInfoProvider : IMappingInfoProvider
8 | {
9 | private readonly Dictionary _propertiesKeyIndices;
10 |
11 | public ExpandoObjectMappingInfoProvider(
12 | IDictionary properties,
13 | SqlBulkCopyColumnMappingCollection mappingsCollection)
14 | {
15 | if (properties == null || properties.Count == 0)
16 | throw new InvalidOperationException("Cannot collect properties from object");
17 |
18 | MappingsCollection = mappingsCollection;
19 | _propertiesKeyIndices = new Dictionary();
20 |
21 | foreach (var property in properties)
22 | {
23 | var ordinal = _propertiesKeyIndices.Count;
24 |
25 | _propertiesKeyIndices.Add(ordinal, property.Key);
26 | MappingsCollection.Add(new SqlBulkCopyColumnMapping(ordinal, property.Key));
27 | }
28 | }
29 |
30 | public SqlBulkCopyColumnMappingCollection MappingsCollection { get; }
31 |
32 | public object GetValue(int ordinal, object collectionEnumeratorCurrent)
33 | {
34 | var propertyName = _propertiesKeyIndices[ordinal];
35 | return ((IDictionary)collectionEnumeratorCurrent)[propertyName];
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/Extensions/PropertyInfoProviders/StrictTypeMappingInfoProvider.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.Extensions.PropertyInfoProviders
2 | {
3 | using System;
4 | using System.Data.SqlClient;
5 | using System.Linq;
6 | using System.Reflection;
7 |
8 | public class StrictTypeMappingInfoProvider : IMappingInfoProvider
9 | {
10 | private readonly PropertyInfo[] _itemProperties;
11 | public StrictTypeMappingInfoProvider(Type type, SqlBulkCopyColumnMappingCollection mappingsCollection)
12 | {
13 | _itemProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
14 | if (_itemProperties == null || _itemProperties.Any() == false)
15 | throw new InvalidOperationException("Cannot collect properties from object");
16 |
17 | MappingsCollection = mappingsCollection;
18 | for (var i = 0; i < _itemProperties.Length; i++)
19 | MappingsCollection.Add(new SqlBulkCopyColumnMapping(i, _itemProperties[i].Name));
20 | }
21 |
22 | public SqlBulkCopyColumnMappingCollection MappingsCollection { get; }
23 |
24 | public object GetValue(int ordinal, object current)
25 | {
26 | return _itemProperties[ordinal].GetValue(current);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/QueryObject.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper
2 | {
3 | using System;
4 |
5 | ///
6 | /// Incapsulate SQL and Parameters for Dapper methods
7 | ///
8 | ///
9 | /// http://www.martinfowler.com/eaaCatalog/queryObject.html
10 | ///
11 | public class QueryObject
12 | {
13 | ///
14 | /// SQL string
15 | ///
16 | public string Sql { get; private set; }
17 |
18 | ///
19 | /// Parameter list
20 | ///
21 | public object QueryParams { get; private set; }
22 |
23 | ///
24 | /// Create QueryObject for parameterized
25 | ///
26 | /// SQL string
27 | /// Parameter list
28 | public QueryObject(string sql, object queryParams = null)
29 | {
30 | if (string.IsNullOrEmpty(sql))
31 | throw new ArgumentNullException(nameof(sql));
32 |
33 | Sql = sql;
34 | QueryParams = queryParams;
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/SessionsFactory/ISession.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.SessionsFactory
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Data;
6 | using System.Threading.Tasks;
7 | using Extensions;
8 |
9 | public interface ISession : IDisposable
10 | {
11 | IEnumerable Query(string sql, object param = null, bool buffered = true, TimeSpan? commandTimeout = null,
12 | CommandType? commandType = null);
13 |
14 | Task> QueryAsync(string sql, object param = null, TimeSpan? commandTimeout = null,
15 | CommandType? commandType = null);
16 |
17 | int Execute(string sql, object param = null, TimeSpan? commandTimeout = null, CommandType? commandType = null);
18 | Task ExecuteAsync(string sql, object param = null, TimeSpan? commandTimeout = null, CommandType? commandType = null);
19 |
20 | void BulkInsert(string tableName, IReadOnlyCollection source,
21 | Func, IColumnsMappingConfigurator> columnsMappingSetup = null,
22 | int? batchSize = null, TimeSpan? timeout = null) where TSource : class;
23 |
24 | void Commit();
25 | }
26 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/SessionsFactory/ISessionsFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.SessionsFactory
2 | {
3 | using System.Data;
4 |
5 | public interface ISessionsFactory
6 | {
7 | ISession Create(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted);
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/SessionsFactory/SessionsFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.SessionsFactory
2 | {
3 | using System;
4 | using System.Data;
5 | using ConnectionsFactory;
6 |
7 | public class SessionsFactory : ISessionsFactory
8 | {
9 | private readonly IConnectionsFactory _connectionsFactory;
10 |
11 | public SessionsFactory(IConnectionsFactory connectionsFactory)
12 | {
13 | if (connectionsFactory == null)
14 | throw new ArgumentNullException(nameof(connectionsFactory));
15 |
16 | _connectionsFactory = connectionsFactory;
17 | }
18 |
19 | public ISession Create(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
20 | {
21 | var connection = _connectionsFactory.Create();
22 | var transaction = connection.BeginTransaction(isolationLevel);
23 |
24 | return new Session(connection, transaction);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/Tvp/IMetaDataOptionsBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.Tvp
2 | {
3 | using System;
4 | using System.Linq.Expressions;
5 |
6 | public interface IMetaDataOptionsBuilder where TSource : class
7 | {
8 | IMetaDataOptionsBuilder SetAccuracy(Expression> member, byte precision, byte scale);
9 |
10 | IMetaDataOptionsBuilder SetAccuracy(Expression> member, byte precision, byte scale);
11 |
12 | IMetaDataOptionsBuilder SetMaxLength(Expression> member, long maxLength);
13 |
14 | IMetaDataOptionsBuilder SetMaxLength(Expression> member, long maxLength);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/Tvp/Int32ValuesList.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.Tvp
2 | {
3 | using System.Collections.Generic;
4 |
5 | public class Int32ValuesList : PrimitiveValuesList
6 | {
7 | public Int32ValuesList(string typeName, IEnumerable source) : base(typeName, source)
8 | {
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/Tvp/Int64ValuesList.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.Tvp
2 | {
3 | using System.Collections.Generic;
4 |
5 | public class Int64ValuesList : PrimitiveValuesList
6 | {
7 | public Int64ValuesList(string typeName, IEnumerable source) : base(typeName, source)
8 | {
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Dapper/Tvp/MetaDataCreationOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Dapper.Tvp
2 | {
3 | public class MetaDataCreationOptions
4 | {
5 | public long? MaxLength { get; set; }
6 |
7 | public byte? Precision { get; set; }
8 |
9 | public byte? Scale { get; set; }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | portable
7 | dmitriy.litichevskiy
8 | https://github.com/litichevskiydv/WebInfrastructure
9 | MIT
10 | git
11 | https://github.com/litichevskiydv/WebInfrastructure
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/Configuration/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.Configuration
2 | {
3 | using System;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using Microsoft.Extensions.Options;
7 |
8 | public static class ServiceCollectionExtensions
9 | {
10 | public static IServiceCollection ConfigureMessagesProcessingService(
11 | this IServiceCollection services,
12 | IConfiguration configuration,
13 | Action> optionsConfigurator)
14 | where TServiceOptions : MessagesProcessingServiceOptions
15 | {
16 | if(services == null)
17 | throw new ArgumentNullException(nameof(services));
18 | if (configuration == null)
19 | throw new ArgumentNullException(nameof(configuration));
20 | if (optionsConfigurator == null)
21 | throw new ArgumentNullException(nameof(optionsConfigurator));
22 |
23 | services.Configure(configuration);
24 | optionsConfigurator(services.AddOptions());
25 |
26 | return services;
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/IMessageHandler.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions
2 | {
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | public interface IMessageHandler
7 | {
8 | Task Handle(TMessage message, CancellationToken cancellationToken);
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/MessagesProcessingServiceOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions
2 | {
3 | using System;
4 | using QueuesFactory.Configuration;
5 |
6 | public abstract class MessagesProcessingServiceOptions
7 | {
8 | public TimeSpan ConnectionAttemptTimeout { get; set; }
9 |
10 | public QueueCreationOptions QueueCreationOptions { get; set; }
11 |
12 | internal MessagesProcessingServiceOptions()
13 | {
14 | }
15 | }
16 |
17 | public abstract class MessagesProcessingServiceOptions : MessagesProcessingServiceOptions
18 | where TQueueCreationOptions : QueueCreationOptions
19 | {
20 | public new TQueueCreationOptions QueueCreationOptions
21 | {
22 | get => (TQueueCreationOptions)base.QueueCreationOptions;
23 | set => base.QueueCreationOptions = value;
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/Queues.Abstractions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with abstractions for working with message queues
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netstandard2.0
12 | Skeleton.Queues.Abstractions
13 | Skeleton.Queues.Abstractions
14 | Skeleton.Queues.Abstractions
15 | Queues
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/Configuration/QueueCreationOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory.Configuration
2 | {
3 | using System;
4 | using ExceptionsHandling;
5 | using ExceptionsHandling.Handlers;
6 |
7 | public abstract class QueueCreationOptions
8 | {
9 | public string QueueName { get; set; }
10 |
11 | public int RetriesCount { get; set; }
12 |
13 | public TimeSpan RetryInitialTimeout { get; set; }
14 |
15 | public ExceptionHandlingPolicy? ExceptionHandlingPolicy { get; set; }
16 |
17 | internal QueueCreationOptions()
18 | {
19 | }
20 | }
21 |
22 | public abstract class QueueCreationOptions : QueueCreationOptions
23 | where TMessageDescription : QueueMessageDescriptionBase, new()
24 | {
25 | public ExceptionHandlerBase ExceptionHandler { get; set; }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/Configuration/QueueCreationOptionsExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory.Configuration
2 | {
3 | using System;
4 | using ExceptionsHandling.Handlers;
5 |
6 | public static class QueueCreationOptionsExtensions
7 | {
8 | public static TQueueCreationOptions WithExceptionHandler(
9 | this TQueueCreationOptions queueCreationOptions,
10 | ExceptionHandlerBase exceptionHandler)
11 | where TQueueCreationOptions : QueueCreationOptions
12 | where TMessageDescription : QueueMessageDescriptionBase, new()
13 | {
14 | if(queueCreationOptions == null)
15 | throw new ArgumentNullException(nameof(queueCreationOptions));
16 | if (exceptionHandler == null)
17 | throw new ArgumentNullException(nameof(exceptionHandler));
18 |
19 | queueCreationOptions.ExceptionHandler = exceptionHandler;
20 | return queueCreationOptions;
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/ExceptionsHandling/ErrorInformation.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory.ExceptionsHandling
2 | {
3 | public class ErrorInformation
4 | {
5 | public string MessageId { get; set; }
6 |
7 | public string MessageContent { get; set; }
8 |
9 | public string ExceptionDescription { get; set; }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/ExceptionsHandling/ExceptionHandlersFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory.ExceptionsHandling
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using Handlers;
7 | using QueuesFactory;
8 |
9 | public class ExceptionHandlersFactory : IExceptionHandlersFactory
10 | where TMessageDescription : QueueMessageDescriptionBase, new()
11 | {
12 | private readonly IReadOnlyDictionary> _supportedPolicies;
13 |
14 | public ExceptionHandlersFactory(IEnumerable> registerdHandlers)
15 | {
16 | if(registerdHandlers == null)
17 | throw new ArgumentNullException(nameof(registerdHandlers));
18 |
19 | var registeredHandlersArray = registerdHandlers.ToArray();
20 | if (registeredHandlersArray.GroupBy(x => x.ExceptionHandlingPolicy).Any(x => x.Count() > 1))
21 | throw new InvalidOperationException("More than one handler was registered for policy");
22 |
23 | _supportedPolicies = registeredHandlersArray.ToDictionary(x => x.ExceptionHandlingPolicy);
24 | }
25 |
26 | public ExceptionHandlerBase GetHandler(ExceptionHandlingPolicy policy)
27 | {
28 | if(_supportedPolicies.TryGetValue(policy, out var handler) == false)
29 | throw new NotSupportedException($"Policy {policy.ToString()} is not supported");
30 |
31 | return handler;
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/ExceptionsHandling/ExceptionHandlingPolicy.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory.ExceptionsHandling
2 | {
3 | public enum ExceptionHandlingPolicy
4 | {
5 | None = 0,
6 | Requeue = 1,
7 | SendToErrorsQueue = 2,
8 | Custom = 3
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/ExceptionsHandling/Handlers/EmptyExceptionHandler.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory.ExceptionsHandling.Handlers
2 | {
3 | using System;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Microsoft.Extensions.Logging;
7 | using QueuesFactory;
8 |
9 | public class EmptyExceptionHandler : ExceptionHandlerBase
10 | where TMessageDescription : QueueMessageDescriptionBase, new()
11 | {
12 | public EmptyExceptionHandler(ILogger> logger)
13 | : base(logger, ExceptionHandlingPolicy.None)
14 | {
15 | }
16 |
17 | protected override async Task HandleExceptionAsync(
18 | QueueBase queue,
19 | TMessageDescription messageDescription,
20 | Exception exception,
21 | CancellationToken cancellationToken)
22 | {
23 | await queue.AcknowledgeMessageAsync(messageDescription, cancellationToken);
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/ExceptionsHandling/Handlers/ErrorsQueuingExceptionHandler.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory.ExceptionsHandling.Handlers
2 | {
3 | using System;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Microsoft.Extensions.Logging;
7 | using QueuesFactory;
8 |
9 | public class ErrorsQueuingExceptionHandler : ExceptionHandlerBase
10 | where TMessageDescription : QueueMessageDescriptionBase, new()
11 | {
12 | public ErrorsQueuingExceptionHandler(ILogger> logger)
13 | : base(logger, ExceptionHandlingPolicy.SendToErrorsQueue)
14 | {
15 | }
16 |
17 | protected override async Task HandleExceptionAsync(
18 | QueueBase queue,
19 | TMessageDescription messageDescription,
20 | Exception exception,
21 | CancellationToken cancellationToken)
22 | {
23 |
24 | await queue.AcknowledgeMessageAsync(messageDescription, cancellationToken);
25 | await queue.ErrorsQueue.SendMessageAsync(
26 | new ErrorInformation
27 | {
28 | ExceptionDescription = exception.ToString(),
29 | MessageId = messageDescription.Id,
30 | MessageContent = messageDescription.Content
31 | },
32 | cancellationToken
33 | );
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/ExceptionsHandling/Handlers/ExceptionHandlerBase.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory.ExceptionsHandling.Handlers
2 | {
3 | using System;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Microsoft.Extensions.Logging;
7 |
8 | public abstract class ExceptionHandlerBase
9 | where TMessageDescription : QueueMessageDescriptionBase, new()
10 | {
11 | protected readonly ILogger Logger;
12 | public ExceptionHandlingPolicy ExceptionHandlingPolicy { get; }
13 |
14 | protected ExceptionHandlerBase(ILogger logger, ExceptionHandlingPolicy exceptionHandlingPolicy)
15 | {
16 | if (logger == null)
17 | throw new ArgumentNullException(nameof(logger));
18 |
19 | Logger = logger;
20 | ExceptionHandlingPolicy = exceptionHandlingPolicy;
21 | }
22 |
23 | protected abstract Task HandleExceptionAsync(
24 | QueueBase queue,
25 | TMessageDescription messageDescription,
26 | Exception exception,
27 | CancellationToken cancellationToken);
28 |
29 | public async Task HandleAsync(
30 | QueueBase queue,
31 | TMessageDescription messageDescription,
32 | Exception exception,
33 | CancellationToken cancellationToken)
34 | {
35 | try
36 | {
37 | await HandleExceptionAsync(queue, messageDescription, exception, cancellationToken);
38 | }
39 | catch (Exception e)
40 | {
41 | Logger.LogError(e, "Error during has occurred during handling previous exception");
42 | }
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/ExceptionsHandling/Handlers/RequeuingExceptionHandler.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory.ExceptionsHandling.Handlers
2 | {
3 | using System;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Microsoft.Extensions.Logging;
7 | using QueuesFactory;
8 |
9 | public class RequeuingExceptionHandler : ExceptionHandlerBase
10 | where TMessageDescription : QueueMessageDescriptionBase, new()
11 | {
12 | public RequeuingExceptionHandler(ILogger> logger)
13 | : base(logger, ExceptionHandlingPolicy.Requeue)
14 | {
15 | }
16 |
17 | protected override async Task HandleExceptionAsync(
18 | QueueBase queue,
19 | TMessageDescription messageDescription,
20 | Exception exception,
21 | CancellationToken cancellationToken)
22 | {
23 | await queue.RejectMessageAsync(messageDescription, cancellationToken);
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/ExceptionsHandling/IExceptionHandlersFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory.ExceptionsHandling
2 | {
3 | using Handlers;
4 | using QueuesFactory;
5 |
6 | public interface IExceptionHandlersFactory where TMessageDescription : QueueMessageDescriptionBase, new()
7 | {
8 | ExceptionHandlerBase GetHandler(ExceptionHandlingPolicy policy);
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/GenericQueuesFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory
2 | {
3 | using System;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Runtime.ExceptionServices;
7 | using Configuration;
8 |
9 | public class GenericQueuesFactory : IGenericQueuesFactory
10 | {
11 | private readonly IServiceProvider _serviceProvider;
12 | private readonly Type _typedQueuesFactoryType;
13 |
14 | public GenericQueuesFactory(IServiceProvider serviceProvider)
15 | {
16 | if(serviceProvider == null)
17 | throw new ArgumentNullException(nameof(serviceProvider));
18 |
19 | _serviceProvider = serviceProvider;
20 | _typedQueuesFactoryType = typeof(ITypedQueuesFactory<>);
21 | }
22 |
23 | public ITypedQueue Create(QueueCreationOptions creationOptions)
24 | {
25 | var creationOptionsType = creationOptions.GetType();
26 | var typedQueuesFactory = _serviceProvider.GetService(_typedQueuesFactoryType.MakeGenericType(creationOptionsType));
27 | var createMethodDefinition = typedQueuesFactory.GetType()
28 | .GetMethods()
29 | .Single(x => x.IsGenericMethod && x.Name == nameof(ITypedQueuesFactory.Create))
30 | .MakeGenericMethod(typeof(TMessage));
31 |
32 | try
33 | {
34 | return (ITypedQueue) createMethodDefinition.Invoke(typedQueuesFactory, new object[] {creationOptions});
35 | }
36 | catch (TargetInvocationException ex)
37 | {
38 | ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
39 | }
40 |
41 | return default(ITypedQueue);
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/IGenericQueuesFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory
2 | {
3 | using Configuration;
4 |
5 | public interface IGenericQueuesFactory
6 | {
7 | ITypedQueue Create(QueueCreationOptions creationOptions);
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/ITypedQueue.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory
2 | {
3 | using System;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 |
7 | public interface ITypedQueue : IDisposable
8 | {
9 | Task> SendMessageAsync(TMessage message, CancellationToken cancellationToken = default(CancellationToken));
10 |
11 | Task> SubscribeAsync(IMessageHandler handler, CancellationToken cancellationToken = default(CancellationToken));
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/ITypedQueuesFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory
2 | {
3 | using Configuration;
4 |
5 | public interface ITypedQueuesFactory where TQueueCreationOptions : QueueCreationOptions
6 | {
7 | ITypedQueue Create(TQueueCreationOptions creationOptions);
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/IUntypedQueuesFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory
2 | {
3 | using Configuration;
4 |
5 | public interface IUntypedQueuesFactory
6 | where TQueueCreationOptions : QueueCreationOptions
7 | where TQueue : QueueBase
8 | {
9 | TQueue Create(TQueueCreationOptions creationOptions);
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.Abstractions/QueuesFactory/QueueMessageDescriptionBase.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.Abstractions.QueuesFactory
2 | {
3 | public abstract class QueueMessageDescriptionBase
4 | {
5 | public string Id { get; set; }
6 |
7 | public string Content { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.RabbitMq/Queues.RabbitMq.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with classes for working with RabbitMq
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netstandard2.0
12 | Skeleton.Queues.RabbitMq
13 | Skeleton.Queues.RabbitMq
14 | Skeleton.Queues.RabbitMq
15 | RabbitMq
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.RabbitMq/QueuesFactory/Configuration/RabbitCredentianls.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.RabbitMq.QueuesFactory.Configuration
2 | {
3 | public class RabbitCredentianls
4 | {
5 | public string UserName { get; set; }
6 |
7 | public string Password { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.RabbitMq/QueuesFactory/Configuration/RabbitQueueCreationOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.RabbitMq.QueuesFactory.Configuration
2 | {
3 | using System.Collections.Generic;
4 | using Abstractions.QueuesFactory.Configuration;
5 |
6 | public class RabbitQueueCreationOptions : QueueCreationOptions
7 | {
8 | public IDictionary AdditionalArguments { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.RabbitMq/QueuesFactory/Configuration/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.RabbitMq.QueuesFactory.Configuration
2 | {
3 | using System;
4 | using Abstractions.QueuesFactory;
5 | using Abstractions.QueuesFactory.ExceptionsHandling;
6 | using Abstractions.QueuesFactory.ExceptionsHandling.Handlers;
7 | using Microsoft.Extensions.DependencyInjection;
8 | using Microsoft.Extensions.DependencyInjection.Extensions;
9 |
10 | public static class ServiceCollectionExtensions
11 | {
12 | public static IServiceCollection AddRabbitMqSupport(this IServiceCollection serviceCollection)
13 | {
14 | if(serviceCollection == null)
15 | throw new ArgumentNullException(nameof(serviceCollection));
16 |
17 | serviceCollection.AddSingleton, EmptyExceptionHandler>();
18 | serviceCollection.AddSingleton, RequeuingExceptionHandler>();
19 | serviceCollection.AddSingleton, ErrorsQueuingExceptionHandler>();
20 | serviceCollection.TryAddSingleton, ExceptionHandlersFactory>();
21 | serviceCollection.TryAddSingleton();
22 | serviceCollection.TryAddSingleton>(x => x.GetService());
23 | serviceCollection.TryAddSingleton>>(x => x.GetService());
24 | serviceCollection.TryAddSingleton();
25 |
26 | return serviceCollection;
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.RabbitMq/QueuesFactory/Configuration/TypedRabbitQueuesFactoryOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.RabbitMq.QueuesFactory.Configuration
2 | {
3 | using System;
4 |
5 | public class TypedRabbitQueuesFactoryOptions
6 | {
7 | public RabbitCredentianls Credentials { get; set; }
8 |
9 | public string[] Hosts { get; set; }
10 |
11 | public TimeSpan NetworkRecoveryInterval { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Queues.RabbitMq/QueuesFactory/RabbitMessageDescription.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Queues.RabbitMq.QueuesFactory
2 | {
3 | using System.Collections.Generic;
4 | using Abstractions.QueuesFactory;
5 |
6 | public class RabbitMessageDescription : QueueMessageDescriptionBase
7 | {
8 | public IDictionary Headers { get; set; }
9 |
10 | public ulong? DeliveryTag { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/ApplicationBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer
2 | {
3 | using System;
4 | using Microsoft.AspNetCore.Builder;
5 |
6 | public static class ApplicationBuilderExtensions
7 | {
8 | public static IApplicationBuilder UseJwtBearerTokensIssuer(this IApplicationBuilder applicationBuilder)
9 | {
10 | if (applicationBuilder == null)
11 | throw new ArgumentNullException(nameof(applicationBuilder));
12 |
13 | return applicationBuilder.UseMiddleware();
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/Configuration/Issuing/IJwtBearerTokensIssuerBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer.Configuration.Issuing
2 | {
3 | using Microsoft.Extensions.DependencyInjection;
4 |
5 | public interface IJwtBearerTokensIssuerBuilder
6 | {
7 | IServiceCollection Services { get; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/Configuration/Issuing/JwtBearerTokensIssuerBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer.Configuration.Issuing
2 | {
3 | using System;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | public class JwtBearerTokensIssuerBuilder : IJwtBearerTokensIssuerBuilder
7 | {
8 | public JwtBearerTokensIssuerBuilder(IServiceCollection services)
9 | {
10 | if (services == null)
11 | throw new ArgumentNullException(nameof(services));
12 |
13 | Services = services;
14 | }
15 |
16 | public IServiceCollection Services { get; }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/Configuration/Issuing/JwtBearerTokensIssuerBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer.Configuration.Issuing
2 | {
3 | using System;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.DependencyInjection.Extensions;
6 | using Microsoft.Extensions.Options;
7 |
8 | public static class JwtBearerTokensIssuerBuilderExtensions
9 | {
10 | public static IJwtBearerTokensIssuerBuilder WithTokenIssueEventHandler(
11 | this IJwtBearerTokensIssuerBuilder issuerBuilder
12 | )
13 | where TEventHandler : ITokenIssueEventHandler
14 | {
15 | if (issuerBuilder == null)
16 | throw new ArgumentNullException(nameof(issuerBuilder));
17 |
18 | issuerBuilder.Services.TryAddEnumerable(
19 | ServiceDescriptor.Transient, TokenIssueEventHandlerSetup>()
20 | );
21 | return issuerBuilder;
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/Configuration/Issuing/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer.Configuration.Issuing
2 | {
3 | using System;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | public static class ServiceCollectionExtensions
7 | {
8 | public static IJwtBearerTokensIssuerBuilder AddJwtBearerTokensIssuer(this IServiceCollection services, Action configure)
9 | {
10 | if(services == null)
11 | throw new ArgumentNullException(nameof(services));
12 | if(configure == null)
13 | throw new ArgumentNullException(nameof(configure));
14 |
15 | services
16 | .AddOptions()
17 | .Configure(configure);
18 |
19 | return new JwtBearerTokensIssuerBuilder(services);
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/Configuration/Issuing/TokenIssueEventHandlerSetup.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer.Configuration.Issuing
2 | {
3 | using System;
4 | using Microsoft.Extensions.Options;
5 |
6 | public class TokenIssueEventHandlerSetup : IConfigureOptions
7 | where TEventHandler : ITokenIssueEventHandler
8 | {
9 | private readonly ITokenIssueEventHandler _eventHandler;
10 |
11 | public TokenIssueEventHandlerSetup(TEventHandler eventHandler)
12 | {
13 | if (eventHandler == null)
14 | throw new ArgumentNullException(nameof(eventHandler));
15 |
16 | _eventHandler = eventHandler;
17 | }
18 |
19 | public void Configure(TokensIssuingOptions options)
20 | {
21 | options.WithTokenIssueEventHandler(_eventHandler);
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/ITokenIssueEventHandler.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer
2 | {
3 | using System;
4 | using System.Security.Claims;
5 |
6 | public interface ITokenIssueEventHandler
7 | {
8 | void IssueSuccessEventHandle(string token, Claim[] user);
9 | void LoginNotFoundEventHandle(string login);
10 | void IncorrectPasswordEventHandle(string login, string password);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/Models/TokenErrorResponseModel.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer.Models
2 | {
3 | public class TokenErrorResponseModel
4 | {
5 | public string ErrorMessage { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/Models/TokenRequestModel.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer.Models
2 | {
3 | public class TokenRequestModel
4 | {
5 | public string Login { get; set; }
6 | public string Password { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/Models/TokenResponseModel.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer.Models
2 | {
3 | using System;
4 |
5 | public class TokenResponseModel
6 | {
7 | public string Token { get; set; }
8 |
9 | public DateTime? ExpirationDate { get; set; }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/TokensIssuingOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer
2 | {
3 | using System;
4 | using Microsoft.IdentityModel.Tokens;
5 |
6 | public class TokensIssuingOptions
7 | {
8 | public string GetEndpoint { get; set; }
9 |
10 | public SecurityKey SigningKey { get; set; }
11 |
12 | public string SigningAlgorithmName { get; set; }
13 |
14 | public TimeSpan? Lifetime { get; set; }
15 |
16 | public ITokenIssueEventHandler TokenIssueEventHandler { get; set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/UserClaimsProvider/Exceptions/IncorrectPasswordException.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer.UserClaimsProvider.Exceptions
2 | {
3 | using System;
4 |
5 | public class IncorrectPasswordException : Exception
6 | {
7 | public IncorrectPasswordException(string login) : base($"Password is incorrect for login {login}")
8 | {
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/UserClaimsProvider/Exceptions/LoginNotFoundException.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer.UserClaimsProvider.Exceptions
2 | {
3 | using System;
4 |
5 | public class LoginNotFoundException : Exception
6 | {
7 | public LoginNotFoundException(string login) : base($"Login {login} wasn't found")
8 | {
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/JwtBearer/UserClaimsProvider/IUserClaimsProvider.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Authentication.JwtBearer.UserClaimsProvider
2 | {
3 | using System.Security.Claims;
4 | using System.Threading.Tasks;
5 |
6 | public interface IUserClaimsProvider
7 | {
8 | Task GetClaimsAsync(string login, string password);
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Authentication/Web.Authentication.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with authentication models implementations
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netcoreapp3.1
12 | Skeleton.Web.Authentication
13 | Skeleton.Web.Authentication
14 | Skeleton.Web.Authentication
15 | WebApi authentication
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Conventions/Responses/ApiExceptionResponse.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Conventions.Responses
2 | {
3 | using System;
4 | using System.Runtime.Serialization;
5 | using System.Text;
6 |
7 | [DataContract]
8 | public class ApiExceptionResponse
9 | {
10 | [DataMember(EmitDefaultValue = false, IsRequired = false, Order = 1)]
11 | public string Message { get; set; }
12 |
13 | [DataMember(EmitDefaultValue = false, IsRequired = false, Order = 2)]
14 | public ExceptionDescription ExceptionDescription { get; set; }
15 |
16 | public ApiExceptionResponse()
17 | {
18 | }
19 |
20 | public ApiExceptionResponse(string message, Exception exception) : this()
21 | {
22 | Message = message;
23 | if(exception != null)
24 | ExceptionDescription = new ExceptionDescription(exception);
25 | }
26 |
27 | public override string ToString()
28 | {
29 | var builder = new StringBuilder();
30 |
31 | if (string.IsNullOrWhiteSpace(Message) == false)
32 | builder.AppendLine(Message);
33 |
34 | var exceptionDescriptionString = ExceptionDescription?.ToString();
35 | if (string.IsNullOrWhiteSpace(exceptionDescriptionString) == false)
36 | builder.AppendLine(exceptionDescriptionString);
37 |
38 | return builder.ToString();
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Conventions/Responses/ApiResponseError.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Conventions.Responses
2 | {
3 | using System.Runtime.Serialization;
4 | using System.Text;
5 |
6 | ///
7 | /// Contract for transmission single error what occurs during Web Api request processing
8 | ///
9 | [DataContract]
10 | public class ApiResponseError
11 | {
12 | ///
13 | /// Error code
14 | ///
15 | [DataMember(EmitDefaultValue = false, IsRequired = false, Order = 1)]
16 | public string Code { get; set; }
17 |
18 | ///
19 | /// Short error description
20 | ///
21 | [DataMember(EmitDefaultValue = false, IsRequired = false, Order = 2)]
22 | public string Title { get; set; }
23 |
24 | ///
25 | /// Full error description
26 | ///
27 | [DataMember(EmitDefaultValue = false, IsRequired = false, Order = 3)]
28 | public string Detail { get; set; }
29 |
30 | public override string ToString()
31 | {
32 | var builder = new StringBuilder();
33 |
34 | if (string.IsNullOrWhiteSpace(Code) == false)
35 | builder.Append($"{nameof(Code)}: {Code}; ");
36 | if (string.IsNullOrWhiteSpace(Title) == false)
37 | builder.Append($"{nameof(Title)}: {Title}; ");
38 | if (string.IsNullOrWhiteSpace(Detail) == false)
39 | builder.Append($"{nameof(Detail)}: {Detail}; ");
40 |
41 | return builder.ToString();
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Conventions/Web.Conventions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with common conventions for web applications development
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netstandard1.1
12 | Skeleton.Web.Conventions
13 | Skeleton.Web.Conventions
14 | Skeleton.Web.Conventions
15 | Web conventions
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Hosting/HostBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Hosting
2 | {
3 | using System.IO;
4 | using Autofac.Extensions.DependencyInjection;
5 | using Configuration;
6 | using Microsoft.AspNetCore.Hosting;
7 | using Microsoft.Extensions.Configuration;
8 | using Microsoft.Extensions.Hosting;
9 | using Serilog;
10 | using Skeleton.Web.Logging.Serilog.Configuration;
11 |
12 | public static class HostBuilderExtensions
13 | {
14 | public static IHostBuilder CreateDefaultWebApiHostBuilder(string[] args) where TStartup : WebApiBaseStartup =>
15 | new HostBuilder()
16 | .UseServiceProviderFactory(new AutofacServiceProviderFactory())
17 | .UseContentRoot(Directory.GetCurrentDirectory())
18 | .ConfigureHostConfiguration(config => config.AddEnvironmentVariables("DOTNET_").AddCommandLine(args))
19 | .ConfigureAppConfiguration(
20 | (context, builder) =>
21 | {
22 | var env = context.HostingEnvironment;
23 |
24 | builder
25 | .AddDefaultConfigs(env)
26 | .AddCommandLine(args);
27 | }
28 | )
29 | .UseSerilog((context, configuration) => configuration.UseDefaultSettings(context.Configuration))
30 | .ConfigureWebHost(
31 | webHostBuilder => webHostBuilder
32 | .UseKestrel(x => x.AllowSynchronousIO = true)
33 | .UseIISIntegration()
34 | .UseStartup()
35 | );
36 | }
37 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Hosting/Web.Hosting.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with common classes for Web Applications hosting
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netcoreapp3.1
12 | Skeleton.Web.Hosting
13 | Skeleton.Web.Hosting
14 | Skeleton.Web.Hosting
15 | Web Hosting
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/BaseApiClient/Configuration/BaseClientOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Integration.BaseApiClient.Configuration
2 | {
3 | using System;
4 | using Serialization.Abstractions;
5 |
6 | public class BaseClientOptions
7 | {
8 | public string BaseUrl { get; set; }
9 |
10 | public TimeSpan Timeout { get; set; }
11 |
12 | public ISerializer Serializer { get; set; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/BaseApiClient/Configuration/HttpClientBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Integration.BaseApiClient.Configuration
2 | {
3 | using System;
4 | using System.Net.Http;
5 | using Microsoft.Extensions.Configuration;
6 | using Microsoft.Extensions.DependencyInjection;
7 | using Microsoft.Extensions.Options;
8 |
9 | public static class HttpClientBuilderExtensions
10 | {
11 | public static IHttpClientBuilder ConfigureClient(
12 | this IHttpClientBuilder httpClientBuilder,
13 | IConfiguration config,
14 | Action> optionsConfigurator)
15 | where TClientOptions : BaseClientOptions
16 | {
17 | if(httpClientBuilder == null)
18 | throw new ArgumentNullException(nameof(httpClientBuilder));
19 | if (config == null)
20 | throw new ArgumentNullException(nameof(config));
21 | if (optionsConfigurator == null)
22 | throw new ArgumentNullException(nameof(optionsConfigurator));
23 |
24 | var services = httpClientBuilder.Services;
25 | services.Configure(config);
26 | optionsConfigurator(services.AddOptions());
27 |
28 | return httpClientBuilder;
29 | }
30 |
31 | public static IHttpClientBuilder UseDefaultPrimaryMessageHandler(
32 | this IHttpClientBuilder httpClientBuilder,
33 | Func handlerConfigurator)
34 | {
35 | if (httpClientBuilder == null)
36 | throw new ArgumentNullException(nameof(httpClientBuilder));
37 |
38 | return httpClientBuilder.ConfigurePrimaryHttpMessageHandler(
39 | x => handlerConfigurator(new HttpClientHandler())
40 | );
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/BaseApiClient/Configuration/HttpClientHandlerExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Integration.BaseApiClient.Configuration
2 | {
3 | using System;
4 | using System.Net;
5 | using System.Net.Http;
6 |
7 | public static class HttpClientHandlerExtensions
8 | {
9 | public static HttpClientHandler WithAutomaticDecompression(this HttpClientHandler handler)
10 | {
11 | if(handler == null)
12 | throw new ArgumentNullException(nameof(handler));
13 |
14 | handler.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
15 | return handler;
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/BaseApiClient/Configuration/OptionsBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Integration.BaseApiClient.Configuration
2 | {
3 | using System;
4 | using Microsoft.Extensions.Options;
5 | using Serialization.Abstractions;
6 |
7 | public static class OptionsBuilderExtensions
8 | {
9 | public static OptionsBuilder WithSerializer(
10 | this OptionsBuilder optionsBuilder,
11 | ISerializer serializer)
12 | where TClientOptions : BaseClientOptions
13 | {
14 | if(optionsBuilder == null)
15 | throw new ArgumentNullException(nameof(optionsBuilder));
16 | if (serializer == null)
17 | throw new ArgumentNullException(nameof(serializer));
18 |
19 | return optionsBuilder.Configure(x => x.Serializer = serializer);
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/BaseApiClient/Configuration/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Integration.BaseApiClient.Configuration
2 | {
3 | using Microsoft.Extensions.DependencyInjection;
4 |
5 | public static class ServiceCollectionExtensions
6 | {
7 | public static IHttpClientBuilder AddClient(this IServiceCollection services)
8 | where TImplementation : BaseClient
9 | {
10 | return services.AddHttpClient();
11 | }
12 |
13 | public static IHttpClientBuilder AddClient(this IServiceCollection services)
14 | where TContract : class
15 | where TImplementation : BaseClient, TContract
16 | {
17 | return services.AddHttpClient();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/BaseApiClient/Exceptions/ApiException.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Integration.BaseApiClient.Exceptions
2 | {
3 | using System;
4 | using System.Net;
5 |
6 | public class ApiException : Exception
7 | {
8 | public HttpStatusCode StatusCode { get; }
9 |
10 | public ApiException(HttpStatusCode statusCode, string message) : base(message)
11 | {
12 | StatusCode = statusCode;
13 | }
14 |
15 | public ApiException(HttpStatusCode statusCode, string message, Exception innerException) : base(message, innerException)
16 | {
17 | StatusCode = statusCode;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/BaseApiClient/Exceptions/BadRequestException.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Integration.BaseApiClient.Exceptions
2 | {
3 | using System;
4 |
5 | public class BadRequestException : Exception
6 | {
7 | public BadRequestException(string message) : base(message)
8 | {
9 | }
10 |
11 | public BadRequestException(string message, Exception innerException) : base(message, innerException)
12 | {
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/BaseApiClient/Exceptions/NotFoundException.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Integration.BaseApiClient.Exceptions
2 | {
3 | using System;
4 |
5 | public class NotFoundException : Exception
6 | {
7 | public NotFoundException(string message) : base(message)
8 | {
9 | }
10 |
11 | public NotFoundException(string message, Exception innerException) : base(message, innerException)
12 | {
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/BaseApiClient/Exceptions/UnauthorizedException.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Integration.BaseApiClient.Exceptions
2 | {
3 | using System;
4 |
5 | public class UnauthorizedException : Exception
6 | {
7 | public UnauthorizedException(string message) : base(message)
8 | {
9 | }
10 |
11 | public UnauthorizedException(string message, Exception innerException) : base(message, innerException)
12 | {
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/BaseApiClient/RequestHeadersExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Integration.BaseApiClient
2 | {
3 | using System;
4 | using System.Net.Http.Headers;
5 | using System.Text;
6 |
7 | public static class HttpRequestHeadersExtensions
8 | {
9 | public static HttpRequestHeaders WithBearerToken(this HttpRequestHeaders headers, string token)
10 | {
11 | if (headers == null)
12 | throw new ArgumentNullException(nameof(headers));
13 | if (string.IsNullOrWhiteSpace(token))
14 | throw new ArgumentNullException(nameof(token));
15 |
16 | headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
17 | return headers;
18 | }
19 |
20 | public static HttpRequestHeaders WithBasicAuth(this HttpRequestHeaders headers, string login, string password)
21 | {
22 | if (headers == null)
23 | throw new ArgumentNullException(nameof(headers));
24 | if (string.IsNullOrWhiteSpace(login))
25 | throw new ArgumentNullException(nameof(login));
26 | if (string.IsNullOrWhiteSpace(password))
27 | throw new ArgumentNullException(nameof(password));
28 |
29 | var value = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{login}:{password}"));
30 | headers.Authorization = new AuthenticationHeaderValue("Basic", value);
31 | return headers;
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/BaseApiFluentClient/BaseFluentClient.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Integration.BaseApiFluentClient
2 | {
3 | using System.Collections.Generic;
4 | using BaseApiClient;
5 |
6 | public abstract class BaseFluentClient
7 | {
8 | protected readonly List ServicesClients;
9 | public dynamic CurrentState { get; protected set; }
10 |
11 | protected BaseFluentClient()
12 | {
13 | ServicesClients = new List();
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Integration/Web.Integration.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library contains base client for integration with WebApi
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netstandard2.0
12 | Skeleton.Web.Integration
13 | Skeleton.Web.Integration
14 | Skeleton.Web.Integration
15 | Integrations;WebApi client
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Logging.Abstractions/ContextsCapturing/CapturedData/CapturedActionExecutingContext.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Logging.Abstractions.ContextsCapturing.CapturedData
2 | {
3 | using System.Collections.Generic;
4 |
5 | internal class CapturedActionExecutingContext
6 | {
7 | public string Method { get; set; }
8 |
9 | public string Url { get; set; }
10 |
11 | public IDictionary Headers { get; set; }
12 |
13 | public IDictionary ActionArguments { get; set; }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Logging.Abstractions/ContextsCapturing/LoggerExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Logging.Abstractions.ContextsCapturing
2 | {
3 | using System;
4 | using System.Linq;
5 | using CapturedData;
6 | using Microsoft.AspNetCore.Http.Extensions;
7 | using Microsoft.AspNetCore.Mvc.Filters;
8 | using Microsoft.Extensions.Logging;
9 |
10 | public static class LoggerExtensions
11 | {
12 | public static IDisposable CaptureActionExecutingContext(this ILogger logger, ActionExecutingContext context)
13 | {
14 | var capturedContext = new CapturedActionExecutingContext();
15 |
16 | if (context.HttpContext?.Request != null)
17 | {
18 | var request = context.HttpContext.Request;
19 |
20 | capturedContext.Method = request.Method;
21 | capturedContext.Url = request.GetDisplayUrl();
22 | capturedContext.Headers = request.Headers.ToDictionary(x => x.Key, x => x.Value.ToString());
23 | }
24 | if (context.ActionArguments != null && context.ActionArguments.Count > 0)
25 | capturedContext.ActionArguments = context.ActionArguments;
26 |
27 | return logger.BeginScope("{@Context}", capturedContext);
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Logging.Abstractions/Web.Logging.Abstractions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Common classes for logging in web application
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netcoreapp3.1
12 | Skeleton.Web.Logging.Abstractions
13 | Skeleton.Web.Logging.Abstractions
14 | Skeleton.Web.Logging.Abstractions
15 | Structured logging
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Logging.NLog/ConfigurationBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Logging.NLog
2 | {
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.IO;
5 | using global::NLog;
6 | using global::NLog.Config;
7 | using Microsoft.Extensions.Configuration;
8 |
9 | public static class ConfigurationBuilderExtensions
10 | {
11 | [ExcludeFromCodeCoverage]
12 | public static IConfigurationBuilder AddNLogConfig(this IConfigurationBuilder configurationBuilder, string relativeConfigPath)
13 | {
14 | var fullConfigPath = Path.Combine(configurationBuilder.GetFileProvider().GetFileInfo(relativeConfigPath).PhysicalPath);
15 | LogManager.Configuration = new XmlLoggingConfiguration(fullConfigPath, false);
16 | return configurationBuilder;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Logging.NLog/LoggingBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Logging.NLog
2 | {
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Reflection;
5 | using global::NLog;
6 | using global::NLog.Extensions.Logging;
7 | using Microsoft.Extensions.Logging;
8 |
9 | public static class LoggingBuilderExtensions
10 | {
11 | [ExcludeFromCodeCoverage]
12 | public static ILoggingBuilder AddNLog(this ILoggingBuilder loggingBuilder)
13 | {
14 | LogManager.AddHiddenAssembly(Assembly.Load(new AssemblyName("Microsoft.Extensions.Logging")));
15 | LogManager.AddHiddenAssembly(Assembly.Load(new AssemblyName("Microsoft.Extensions.Logging.Abstractions")));
16 | LogManager.AddHiddenAssembly(typeof(ConfigureExtensions).GetTypeInfo().Assembly);
17 | LogManager.AddHiddenAssembly(typeof(LoggingBuilderExtensions).GetTypeInfo().Assembly);
18 |
19 | loggingBuilder.AddProvider(new NLogLoggerProvider());
20 | return loggingBuilder;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Logging.NLog/Web.Logging.NLog.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with classe for NLog integration in ASP.NET Core application
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netstandard2.0
12 | Skeleton.Web.Logging.NLog
13 | Skeleton.Web.Logging.NLog
14 | Skeleton.Web.Logging.NLog
15 | NLog AspNetCore
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Logging.Serilog/Configuration/LoggerConfigurationExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Logging.Serilog.Configuration
2 | {
3 | using System;
4 | using Enrichers;
5 | using global::Serilog;
6 | using global::Serilog.Exceptions;
7 | using Microsoft.Extensions.Configuration;
8 |
9 | public static class LoggerConfigurationExtensions
10 | {
11 | public static LoggerConfiguration UseDefaultSettings(
12 | this LoggerConfiguration loggerConfiguration,
13 | IConfiguration configuration)
14 | {
15 | if (loggerConfiguration == null)
16 | throw new ArgumentNullException(nameof(loggerConfiguration));
17 | if (configuration == null)
18 | throw new ArgumentNullException(nameof(configuration));
19 |
20 | return loggerConfiguration
21 | .Enrich.WithApplicationInformationalVersion()
22 | .Enrich.WithExceptionDetails()
23 | .Enrich.WithMessageTemplateHash()
24 | .Enrich.WithLogEventHash()
25 | .Enrich.FromLogContext()
26 | .ReadFrom.Configuration(configuration);
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Logging.Serilog/Enrichers/LogEventHashEnricher.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Logging.Serilog.Enrichers
2 | {
3 | using System;
4 | using System.Diagnostics.CodeAnalysis;
5 | using System.Text;
6 | using global::Serilog.Core;
7 | using global::Serilog.Events;
8 | using Murmur;
9 |
10 | [ExcludeFromCodeCoverage]
11 | public class LogEventHashEnricher : ILogEventEnricher
12 | {
13 | public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
14 | {
15 | var builder = new StringBuilder(logEvent.MessageTemplate.Text);
16 | for (var exception = logEvent.Exception; exception != null; exception = exception.InnerException)
17 | {
18 | builder.AppendLine(exception.GetType().AssemblyQualifiedName);
19 | builder.AppendLine(exception.StackTrace);
20 | }
21 | var bytes = Encoding.UTF8.GetBytes(builder.ToString());
22 |
23 | var hash = MurmurHash.Create32().ComputeHash(bytes);
24 | var numericHash = BitConverter.ToUInt32(hash, 0);
25 |
26 | logEvent.AddPropertyIfAbsent(
27 | propertyFactory.CreateProperty("LogEventHash", numericHash.ToString("x8"))
28 | );
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Logging.Serilog/Enrichers/MessageTemplateHashEnricher.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Logging.Serilog.Enrichers
2 | {
3 | using System;
4 | using System.Diagnostics.CodeAnalysis;
5 | using System.Text;
6 | using global::Serilog.Core;
7 | using global::Serilog.Events;
8 | using Murmur;
9 |
10 | [ExcludeFromCodeCoverage]
11 | public class MessageTemplateHashEnricher : ILogEventEnricher
12 | {
13 | public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
14 | {
15 | var bytes = Encoding.UTF8.GetBytes(logEvent.MessageTemplate.Text);
16 |
17 | var hash = MurmurHash.Create32().ComputeHash(bytes);
18 | var numericHash = BitConverter.ToUInt32(hash, 0);
19 |
20 | logEvent.AddPropertyIfAbsent(
21 | propertyFactory.CreateProperty("MessageTemplateHash", numericHash.ToString("x8"))
22 | );
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Logging.Serilog/Formatting/RenderedJsonFormatter.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Logging.Serilog.Formatting
2 | {
3 | using System;
4 | using System.Diagnostics.CodeAnalysis;
5 | using global::Serilog.Formatting.Json;
6 |
7 | [ExcludeFromCodeCoverage]
8 | public class RenderedJsonFormatter : JsonFormatter
9 | {
10 | public RenderedJsonFormatter(string closingDelimiter = null, IFormatProvider formatProvider = null) :
11 | base(closingDelimiter, true, formatProvider)
12 | {
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Logging.Serilog/Web.Logging.Serilog.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with classe for Serilog integration in ASP.NET Core application
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netstandard2.0
12 | Skeleton.Web.Logging.Serilog
13 | Skeleton.Web.Logging.Serilog
14 | Skeleton.Web.Logging.Serilog
15 | Serilog AspNetCore
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Abstractions/ISerializer.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Abstractions
2 | {
3 | using System.IO;
4 | using System.Net.Http;
5 | using System.Net.Http.Headers;
6 |
7 | public interface ISerializer
8 | {
9 | HttpContent Serialize(object obj);
10 |
11 | T Deserialize(Stream stream);
12 |
13 | MediaTypeHeaderValue MediaType { get; }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Abstractions/Web.Serialization.Abstractions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with abstractions for content serialization in Web API
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netstandard1.1
12 | Skeleton.Web.Serialization.Abstractions
13 | Skeleton.Web.Serialization.Abstractions
14 | Skeleton.Web.Serialization.Abstractions
15 | Serialization
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Jil/Configuration/MvcBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Jil.Configuration
2 | {
3 | using System;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using Microsoft.Extensions.DependencyInjection.Extensions;
7 | using Microsoft.Extensions.Options;
8 |
9 | public static class MvcBuilderExtensions
10 | {
11 | public static IMvcBuilder WithJsonFormattersBasedOnJil(
12 | this IMvcBuilder builder,
13 | global::Jil.Options serializerSettings)
14 | {
15 | if(builder == null)
16 | throw new ArgumentNullException(nameof(builder));
17 |
18 |
19 | builder.Services.AddSingleton(Options.Create(new MvcJilOptions {SerializerSettings = serializerSettings}));
20 | builder.Services.TryAddEnumerable(ServiceDescriptor.Transient, MvcOptionsSetup>());
21 | return builder;
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Jil/Configuration/MvcJilOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Jil.Configuration
2 | {
3 | using global::Jil;
4 |
5 | public class MvcJilOptions
6 | {
7 | public Options SerializerSettings { get; internal set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Jil/Configuration/MvcOptionsSetup.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Jil.Configuration
2 | {
3 | using System;
4 | using Formatters;
5 | using Microsoft.AspNetCore.Mvc;
6 | using Microsoft.AspNetCore.Mvc.Formatters;
7 | using Microsoft.Extensions.Logging;
8 | using Microsoft.Extensions.Options;
9 |
10 | public class MvcOptionsSetup : IConfigureOptions
11 | {
12 | private readonly ILoggerFactory _loggerFactory;
13 | private readonly global::Jil.Options _serializerSettings;
14 |
15 | public MvcOptionsSetup(ILoggerFactory loggerFactory, IOptions jilOptions)
16 | {
17 | if(loggerFactory == null)
18 | throw new ArgumentNullException(nameof(loggerFactory));
19 | if(jilOptions == null)
20 | throw new ArgumentNullException(nameof(jilOptions));
21 |
22 | _loggerFactory = loggerFactory;
23 | _serializerSettings = jilOptions.Value.SerializerSettings;
24 | }
25 |
26 | public void Configure(MvcOptions options)
27 | {
28 | options.InputFormatters.RemoveType();
29 | options.InputFormatters.Add(new JilInputFormatter(_loggerFactory.CreateLogger(), _serializerSettings));
30 |
31 | options.OutputFormatters.RemoveType();
32 | options.OutputFormatters.Add(new JilOutputFormatter(_loggerFactory.CreateLogger(), _serializerSettings));
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Jil/Configuration/OptionsExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Jil.Configuration
2 | {
3 | using global::Jil;
4 |
5 | public static class OptionsExtensions
6 | {
7 | public static Options Default =>
8 | new Options(
9 | prettyPrint: false,
10 | excludeNulls: true,
11 | jsonp: false,
12 | dateFormat: DateTimeFormat.ISO8601,
13 | includeInherited: true,
14 | unspecifiedDateTimeKindBehavior: UnspecifiedDateTimeKindBehavior.IsUTC,
15 | serializationNameFormat: SerializationNameFormat.CamelCase);
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Jil/Formatters/MediaTypeHeaderValues.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Jil.Formatters
2 | {
3 | using Microsoft.Net.Http.Headers;
4 |
5 | public static class MediaTypeHeaderValues
6 | {
7 | public static readonly MediaTypeHeaderValue ApplicationJson = MediaTypeHeaderValue.Parse("application/json").CopyAsReadOnly();
8 | public static readonly MediaTypeHeaderValue TextJson = MediaTypeHeaderValue.Parse("text/json").CopyAsReadOnly();
9 | public static readonly MediaTypeHeaderValue ApplicationJsonPatch = MediaTypeHeaderValue.Parse("application/json-patch+json").CopyAsReadOnly();
10 | public static readonly MediaTypeHeaderValue ApplicationAnyJsonSyntax = MediaTypeHeaderValue.Parse("application/*+json").CopyAsReadOnly();
11 | }
12 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Jil/Web.Serialization.Jil.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library for Jil serializer integration
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netcoreapp3.1
12 | Skeleton.Web.Serialization.Jil
13 | Skeleton.Web.Serialization.Jil
14 | Skeleton.Web.Serialization.Jil
15 | Jil;InputFormatter;OutputFormatter
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.JsonNet/Configuration/MvcBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.JsonNet.Configuration
2 | {
3 | using System;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Newtonsoft.Json;
6 |
7 | public static class MvcBuilderExtensions
8 | {
9 | public static IMvcBuilder WithJsonFormattersBasedOnJsonNet(
10 | this IMvcBuilder builder,
11 | Action settingsConfigurator)
12 | {
13 | if(builder == null)
14 | throw new ArgumentNullException(nameof(builder));
15 | if (settingsConfigurator == null)
16 | throw new ArgumentNullException(nameof(settingsConfigurator));
17 |
18 | builder.AddNewtonsoftJson(x => settingsConfigurator(x.SerializerSettings));
19 | return builder;
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.JsonNet/JsonConverters/DateTimeConverter.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.JsonNet.JsonConverters
2 | {
3 | using System;
4 | using System.Globalization;
5 | using Newtonsoft.Json;
6 | using Newtonsoft.Json.Converters;
7 |
8 | public class DateTimeConverter : IsoDateTimeConverter
9 | {
10 | public DateTimeConverter()
11 | {
12 | DateTimeStyles = DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal;
13 | DateTimeFormat = "o";
14 | }
15 |
16 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
17 | {
18 | string resultString;
19 |
20 | if (value is DateTime)
21 | {
22 | var dateTime = (DateTime)value;
23 |
24 | if ((DateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal && dateTime.Kind == DateTimeKind.Unspecified)
25 | dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
26 | if ((DateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal)
27 | dateTime = dateTime.ToUniversalTime();
28 |
29 | resultString = dateTime.ToString(DateTimeFormat, Culture);
30 | }
31 | else
32 | {
33 | var dateTimeOffset = (DateTimeOffset)value;
34 | resultString = dateTimeOffset.ToString(DateTimeFormat, Culture);
35 | }
36 |
37 | writer.WriteValue(resultString);
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.JsonNet/PropertyNamesResolvers/SnakeCasePropertyNamesContractResolver.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.JsonNet.PropertyNamesResolvers
2 | {
3 | using Newtonsoft.Json.Serialization;
4 |
5 | public class SnakeCasePropertyNamesContractResolver : DefaultContractResolver
6 | {
7 | public SnakeCasePropertyNamesContractResolver()
8 | {
9 | NamingStrategy = new SnakeCaseNamingStrategy(true, true);
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.JsonNet/Serializer/JsonNetSerializer.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.JsonNet.Serializer
2 | {
3 | using System;
4 | using System.IO;
5 | using System.Net.Http;
6 | using System.Net.Http.Headers;
7 | using System.Text;
8 | using Abstractions;
9 | using Configuration;
10 | using Newtonsoft.Json;
11 |
12 | public class JsonNetSerializer : ISerializer
13 | {
14 | private readonly JsonSerializerSettings _settings;
15 |
16 | public JsonNetSerializer(JsonSerializerSettings settings)
17 | {
18 | if(settings == null)
19 | throw new ArgumentNullException(nameof(settings));
20 | _settings = settings;
21 |
22 | MediaType = MediaType = MediaTypeHeaderValue.Parse("application/json; charset=utf-8");
23 | }
24 |
25 | public HttpContent Serialize(object obj)
26 | {
27 | return new StringContent(
28 | JsonConvert.SerializeObject(obj, _settings),
29 | Encoding.GetEncoding(MediaType.CharSet),
30 | MediaType.MediaType
31 | );
32 | }
33 |
34 | public T Deserialize(Stream stream)
35 | {
36 | using (var streamReader = new StreamReader(stream, Encoding.UTF8, true, 4096, true))
37 | using (var jsonTextReader = new JsonTextReader(streamReader))
38 | return JsonSerializer.CreateDefault(_settings).Deserialize(jsonTextReader);
39 | }
40 |
41 | public MediaTypeHeaderValue MediaType { get; }
42 |
43 | public static JsonNetSerializer Default => new JsonNetSerializer(new JsonSerializerSettings().UseDefaultSettings());
44 | }
45 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.JsonNet/Web.Serialization.JsonNet.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with serialization conventions and settings for Newtonsoft.Json
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netcoreapp3.1
12 | Skeleton.Web.Serialization.JsonNet
13 | Skeleton.Web.Serialization.JsonNet
14 | Skeleton.Web.Serialization.JsonNet
15 | JsonNet;Newtonsoft.Json;Conventions
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Protobuf/Configuration/MvcBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Protobuf.Configuration
2 | {
3 | using System;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using Microsoft.Extensions.DependencyInjection.Extensions;
7 | using Microsoft.Extensions.Options;
8 | using ProtoBuf.Meta;
9 |
10 | public static class MvcBuilderExtensions
11 | {
12 | public static IMvcBuilder WithProtobufFormatters(
13 | this IMvcBuilder builder,
14 | Func serializerConfigurator = null)
15 | {
16 | if (builder == null)
17 | throw new ArgumentNullException(nameof(builder));
18 |
19 | builder.Services.AddSingleton(Options.Create(new MvcProtobufOptions {SerializerConfigurator = serializerConfigurator ?? (x => x)}));
20 | builder.Services.TryAddEnumerable(ServiceDescriptor.Transient, MvcOptionsSetup>());
21 | return builder;
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Protobuf/Configuration/MvcOptionsSetup.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Protobuf.Configuration
2 | {
3 | using System;
4 | using Formatters;
5 | using Microsoft.AspNetCore.Mvc;
6 | using Microsoft.Extensions.Logging;
7 | using Microsoft.Extensions.Options;
8 | using ProtoBuf.Meta;
9 |
10 | public class MvcOptionsSetup : IConfigureOptions
11 | {
12 | private readonly ILoggerFactory _loggerFactory;
13 | private readonly Func _serializerConfigurator;
14 |
15 | public MvcOptionsSetup(ILoggerFactory loggerFactory, IOptions protobufOptions)
16 | {
17 | if (loggerFactory == null)
18 | throw new ArgumentNullException(nameof(loggerFactory));
19 | if (protobufOptions == null)
20 | throw new ArgumentNullException(nameof(protobufOptions));
21 |
22 | _loggerFactory = loggerFactory;
23 | _serializerConfigurator = x => protobufOptions.Value.SerializerConfigurator(x).WithDefaultSettings();
24 | }
25 |
26 | public void Configure(MvcOptions options)
27 | {
28 | options.InputFormatters.Add(
29 | new ProtobufInputFormatter(_loggerFactory.CreateLogger(), _serializerConfigurator)
30 | );
31 | options.OutputFormatters.Add(
32 | new ProtobufOutputFormatter(_loggerFactory.CreateLogger(), _serializerConfigurator)
33 | );
34 | options.FormatterMappings.SetMediaTypeMappingForFormat("protobuf", MediaTypeHeaderValues.ApplicationProtobuf);
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Protobuf/Configuration/MvcProtobufOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Protobuf.Configuration
2 | {
3 | using System;
4 | using ProtoBuf.Meta;
5 |
6 | public class MvcProtobufOptions
7 | {
8 | public Func SerializerConfigurator { get; internal set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Protobuf/Formatters/MediaTypeHeaderValues.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Protobuf.Formatters
2 | {
3 | using Microsoft.Net.Http.Headers;
4 |
5 | public static class MediaTypeHeaderValues
6 | {
7 | public static readonly MediaTypeHeaderValue ApplicationProtobuf = MediaTypeHeaderValue.Parse("application/x-protobuf").CopyAsReadOnly();
8 | public static readonly MediaTypeHeaderValue ApplicationProtobufSynonym = MediaTypeHeaderValue.Parse("application/protobuf").CopyAsReadOnly();
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Protobuf/Formatters/Surrogates/DateTimeOffsetSurrogate.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Protobuf.Formatters.Surrogates
2 | {
3 | using System;
4 | using ProtoBuf;
5 |
6 | [ProtoContract]
7 | public class DateTimeOffsetSurrogate
8 | {
9 | [ProtoMember(1)]
10 | public long DateTimeTicks { get; set; }
11 |
12 | [ProtoMember(2)]
13 | public short OffsetMinutes { get; set; }
14 |
15 | public static implicit operator DateTimeOffsetSurrogate(DateTimeOffset value)
16 | {
17 | return new DateTimeOffsetSurrogate
18 | {
19 | DateTimeTicks = value.Ticks,
20 | OffsetMinutes = (short)value.Offset.TotalMinutes
21 | };
22 | }
23 |
24 | public static implicit operator DateTimeOffset(DateTimeOffsetSurrogate value)
25 | {
26 | return new DateTimeOffset(value.DateTimeTicks, TimeSpan.FromMinutes(value.OffsetMinutes));
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Protobuf/Serializer/ProtobufSerializer.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Serialization.Protobuf.Serializer
2 | {
3 | using System;
4 | using System.IO;
5 | using System.Net.Http;
6 | using Abstractions;
7 | using Configuration;
8 | using ProtoBuf.Meta;
9 | using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue;
10 |
11 | public class ProtobufSerializer : ISerializer
12 | {
13 | private readonly RuntimeTypeModel _runtimeTypeModel;
14 |
15 | public ProtobufSerializer(Func serializerConfigurator)
16 | {
17 | if (serializerConfigurator == null)
18 | throw new ArgumentNullException(nameof(serializerConfigurator));
19 | _runtimeTypeModel = serializerConfigurator(RuntimeTypeModel.Create());
20 |
21 | MediaType = MediaTypeHeaderValue.Parse("application/x-protobuf");
22 | }
23 |
24 | public HttpContent Serialize(object obj)
25 | {
26 | using (var stream = new MemoryStream())
27 | {
28 | if (obj != null)
29 | _runtimeTypeModel.Serialize(stream, obj);
30 | return new ByteArrayContent(stream.ToArray()) {Headers = {ContentType = MediaType}};
31 | }
32 | }
33 |
34 | public T Deserialize(Stream stream)
35 | {
36 | return (T)_runtimeTypeModel.Deserialize(stream, null, typeof(T));
37 | }
38 |
39 | public MediaTypeHeaderValue MediaType { get; }
40 |
41 | public static ProtobufSerializer Default => new ProtobufSerializer(x => x.WithDefaultSettings());
42 | }
43 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Serialization.Protobuf/Web.Serialization.Protobuf.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library for protobuf-net serializer integration
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netcoreapp3.1
12 | Skeleton.Web.Serialization.Protobuf
13 | Skeleton.Web.Serialization.Protobuf
14 | Skeleton.Web.Serialization.Protobuf
15 | protobuf-net;InputFormatter;OutputFormatter
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Testing/BaseApiClientTests.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Testing
2 | {
3 | using System;
4 | using System.Threading.Tasks;
5 | using Hosting;
6 | using Integration.BaseApiClient.Configuration;
7 | using Integration.BaseApiFluentClient;
8 | using Microsoft.Extensions.Options;
9 | using Serialization.Jil.Serializer;
10 |
11 | public class BaseApiClientTests where TStartup : WebApiBaseStartup
12 | {
13 | protected readonly BaseApiTestsFixture Fixture;
14 |
15 | protected BaseApiClientTests(BaseApiTestsFixture fixture)
16 | {
17 | Fixture = fixture;
18 | Fixture.MockLogger.Invocations.Clear();
19 | }
20 |
21 | protected TClient CreateClient(Action configureOptions = null)
22 | where TClient : BaseFluentClient
23 | where TClientOptions : BaseClientOptions, new()
24 | {
25 | var clientOptions
26 | = new TClientOptions
27 | {
28 | BaseUrl = Fixture.ClientOptions.BaseAddress.ToString(),
29 | Timeout = Fixture.ApiTimeout,
30 | Serializer = JilSerializer.Default
31 | };
32 | configureOptions?.Invoke(clientOptions);
33 |
34 | return (TClient)Activator.CreateInstance(
35 | typeof(TClient),
36 | Fixture.CreateClient(),
37 | Options.Create(clientOptions)
38 | );
39 | }
40 |
41 | protected dynamic CreateAsyncClient(TClient client) where TClient : BaseFluentClient =>
42 | new FluentChainedTask(Task.FromResult(client));
43 | }
44 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Testing/BaseServiceClientTests.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Testing
2 | {
3 | using System;
4 | using Hosting;
5 | using Integration.BaseApiClient;
6 | using Integration.BaseApiClient.Configuration;
7 | using Microsoft.Extensions.Options;
8 | using Serialization.Jil.Serializer;
9 |
10 | public class BaseServiceClientTests where TStartup : WebApiBaseStartup
11 | {
12 | protected readonly BaseApiTestsFixture Fixture;
13 |
14 | protected BaseServiceClientTests(BaseApiTestsFixture fixture)
15 | {
16 | Fixture = fixture;
17 | Fixture.MockLogger.Invocations.Clear();
18 | }
19 |
20 | protected TClient CreateClient(Action configureOptions = null)
21 | where TClient : BaseClient
22 | where TClientOptions : BaseClientOptions, new()
23 | {
24 | var clientOptions
25 | = new TClientOptions
26 | {
27 | BaseUrl = Fixture.ClientOptions.BaseAddress.ToString(),
28 | Timeout = Fixture.ApiTimeout,
29 | Serializer = JilSerializer.Default
30 | };
31 | configureOptions?.Invoke(clientOptions);
32 |
33 | return (TClient) Activator.CreateInstance(
34 | typeof(TClient),
35 | Fixture.CreateClient(),
36 | Options.Create(clientOptions)
37 | );
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Testing/CustomAutofacServiceProviderFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Testing
2 | {
3 | using System;
4 | using Autofac;
5 | using Autofac.Extensions.DependencyInjection;
6 | using Microsoft.Extensions.DependencyInjection;
7 |
8 | public class CustomAutofacServiceProviderFactory : IServiceProviderFactory
9 | {
10 | private readonly Action _overrideRegisteredDependencies;
11 |
12 | public CustomAutofacServiceProviderFactory(Action overrideRegisteredDependencies)
13 | {
14 | if (overrideRegisteredDependencies == null)
15 | throw new ArgumentNullException(nameof(overrideRegisteredDependencies));
16 |
17 | _overrideRegisteredDependencies = overrideRegisteredDependencies;
18 | }
19 |
20 | public ContainerBuilder CreateBuilder(IServiceCollection services)
21 | {
22 | if (services == null)
23 | throw new ArgumentNullException(nameof(services));
24 |
25 | var builder = new ContainerBuilder();
26 | builder.Populate(services);
27 | return builder;
28 | }
29 |
30 | public IServiceProvider CreateServiceProvider(ContainerBuilder containerBuilder)
31 | {
32 | if (containerBuilder == null)
33 | throw new ArgumentNullException(nameof(containerBuilder));
34 |
35 | _overrideRegisteredDependencies(containerBuilder);
36 | var container = containerBuilder.Build();
37 | return new AutofacServiceProvider(container);
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Testing/Extensions/ConfigurationBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Testing.Extensions
2 | {
3 | using System;
4 | using System.Linq;
5 | using Microsoft.Extensions.Configuration;
6 |
7 | public static class ConfigurationBuilderExtensions
8 | {
9 | private static readonly string[] KnownCiNames;
10 |
11 | static ConfigurationBuilderExtensions()
12 | {
13 | KnownCiNames = new[]
14 | {
15 | "Appveyor",
16 | "Travis"
17 | };
18 | }
19 |
20 | public static IConfigurationBuilder AddCiDependentSettings(this IConfigurationBuilder configurationBuilder, string environment)
21 | {
22 | var ciName = KnownCiNames.FirstOrDefault(x => Environment.GetEnvironmentVariable(x.ToUpper())?.ToUpperInvariant() == "TRUE");
23 | configurationBuilder.AddJsonFile($"appsettings.{environment}.{ciName ?? ""}.json", true, false);
24 |
25 | if(Environment.GetEnvironmentVariable("CI_WINDOWS")?.ToUpperInvariant() == "TRUE")
26 | configurationBuilder.AddJsonFile($"appsettings.{environment}.{ciName ?? ""}.Windows.json", true, false);
27 |
28 | if (Environment.GetEnvironmentVariable("CI_LINUX")?.ToUpperInvariant() == "TRUE")
29 | configurationBuilder.AddJsonFile($"appsettings.{environment}.{ciName ?? ""}.Linux.json", true, false);
30 |
31 | return configurationBuilder;
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Testing/Extensions/WebHostBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Testing.Extensions
2 | {
3 | using Microsoft.AspNetCore.Hosting;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.DependencyInjection.Extensions;
6 | using Microsoft.Extensions.Logging;
7 | using Moq;
8 |
9 | public static class WebHostBuilderExtensions
10 | {
11 | public static IWebHostBuilder UseMockLogger(this IWebHostBuilder builder, Mock mockLogger)
12 | {
13 | var mockLoggerFactory = new Mock();
14 | mockLoggerFactory.Setup(x => x.CreateLogger(It.IsAny())).Returns(mockLogger.Object);
15 |
16 | return builder.ConfigureLogging(x => x.Services.Replace(ServiceDescriptor.Singleton(mockLoggerFactory.Object)));
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web.Testing/Web.Testing.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with common classes for creation WebApi integration tests
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netcoreapp3.1
12 | Skeleton.Web.Testing
13 | Skeleton.Web.Testing
14 | Skeleton.Web.Testing
15 | WebApi integration testing
16 | true
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web/Configuration/ConfigurationBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Configuration
2 | {
3 | using Microsoft.Extensions.Configuration;
4 | using Microsoft.Extensions.Hosting;
5 |
6 | public static class ConfigurationBuilderExtensions
7 | {
8 | public static IConfigurationBuilder AddDefaultConfigs(
9 | this IConfigurationBuilder configurationBuilder,
10 | string configsPath,
11 | string environmentName)
12 | {
13 | return configurationBuilder
14 | .AddEnvironmentVariables()
15 | .SetBasePath(configsPath)
16 | .AddJsonFile("appsettings.json", false, true)
17 | .AddJsonFile($"appsettings.{environmentName}.json", false, true);
18 | }
19 |
20 | public static IConfigurationBuilder AddDefaultConfigs(
21 | this IConfigurationBuilder configurationBuilder,
22 | IHostEnvironment hostEnvironment)
23 | {
24 | return configurationBuilder.AddDefaultConfigs(hostEnvironment.ContentRootPath, hostEnvironment.EnvironmentName);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web/Documentation/AuthResponsesOperationFilter.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Documentation
2 | {
3 | using System.Linq;
4 | using Common.Extensions;
5 | using Microsoft.AspNetCore.Authorization;
6 | using Microsoft.OpenApi.Models;
7 | using Swashbuckle.AspNetCore.Swagger;
8 | using Swashbuckle.AspNetCore.SwaggerGen;
9 |
10 | public class AuthResponsesOperationFilter : IOperationFilter
11 | {
12 | public void Apply(OpenApiOperation operation, OperationFilterContext context)
13 | {
14 | var authAttributes = context?.MethodInfo?.DeclaringType?.GetCustomAttributes(true)
15 | .Union(context.MethodInfo?.GetCustomAttributes(true))
16 | .OfType();
17 |
18 | if (authAttributes.IsNotEmpty())
19 | operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Infrastructure/Web/ExceptionsHandling/ApplicationBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.ExceptionsHandling
2 | {
3 | using System;
4 | using Microsoft.AspNetCore.Builder;
5 |
6 | public static class ApplicationBuilderExtensions
7 | {
8 | public static IApplicationBuilder UseUnhandledExceptionsLoggingMiddleware(this IApplicationBuilder applicationBuilder)
9 | {
10 | if(applicationBuilder == null)
11 | throw new ArgumentNullException(nameof(applicationBuilder));
12 |
13 | return applicationBuilder.UseMiddleware();
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web/ExceptionsHandling/MvcOptionsExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.ExceptionsHandling
2 | {
3 | using Microsoft.AspNetCore.Mvc;
4 |
5 | public static class MvcOptionsExtensions
6 | {
7 | public static MvcOptions UseUnhandledExceptionFilter(this MvcOptions mvcOptions)
8 | {
9 | mvcOptions.Filters.Add(typeof(UnhandledExceptionsFilterAttribute));
10 | return mvcOptions;
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web/ExceptionsHandling/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.ExceptionsHandling
2 | {
3 | using Microsoft.AspNetCore.Hosting;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | public static class ServiceCollectionExtensions
7 | {
8 | public static IServiceCollection AddUnhandledExceptionsStartupFilter(this IServiceCollection services)
9 | {
10 | return services.AddTransient();
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web/ExceptionsHandling/UnhandledExceptionsStartupFilter.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.ExceptionsHandling
2 | {
3 | using System;
4 | using Microsoft.AspNetCore.Builder;
5 | using Microsoft.AspNetCore.Hosting;
6 |
7 | public class UnhandledExceptionsStartupFilter : IStartupFilter
8 | {
9 | public Action Configure(Action next)
10 | {
11 | return builder =>
12 | {
13 | next(builder.UseUnhandledExceptionsLoggingMiddleware());
14 | };
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web/Routing/CentralPrefixConvention.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Routing
2 | {
3 | using Microsoft.AspNetCore.Mvc.ApplicationModels;
4 | using Microsoft.AspNetCore.Mvc.Routing;
5 |
6 | public class CentralPrefixConvention : IApplicationModelConvention
7 | {
8 | private readonly AttributeRouteModel _centralRoutePrefix;
9 |
10 | public CentralPrefixConvention(IRouteTemplateProvider routeTemplateProvider)
11 | {
12 | _centralRoutePrefix = new AttributeRouteModel(routeTemplateProvider);
13 | }
14 |
15 | public void Apply(ApplicationModel application)
16 | {
17 | foreach (var controller in application.Controllers)
18 | {
19 | foreach (var selector in controller.Selectors)
20 | {
21 | if (selector.AttributeRouteModel != null)
22 | selector.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(selector.AttributeRouteModel,
23 | _centralRoutePrefix);
24 | else
25 | selector.AttributeRouteModel = _centralRoutePrefix;
26 | }
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web/Routing/MvcOptionsExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Routing
2 | {
3 | using System;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.AspNetCore.Mvc.Routing;
6 |
7 | public static class MvcOptionsExtensions
8 | {
9 | public static MvcOptions UseCentralRoutePrefix(this MvcOptions mvcOptions, IRouteTemplateProvider routeTemplateProvider)
10 | {
11 | if(mvcOptions == null)
12 | throw new ArgumentNullException(nameof(mvcOptions));
13 | if(routeTemplateProvider == null)
14 | throw new ArgumentNullException(nameof(routeTemplateProvider));
15 |
16 | mvcOptions.Conventions.Insert(0, new CentralPrefixConvention(routeTemplateProvider));
17 | return mvcOptions;
18 | }
19 |
20 | public static MvcOptions UseCentralRoutePrefix(this MvcOptions mvcOptions, string routeTemplate)
21 | {
22 | return UseCentralRoutePrefix(mvcOptions, new RouteAttribute(routeTemplate));
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web/Validation/ModelValidationFilterAttribute.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Validation
2 | {
3 | using System.Linq;
4 | using Conventions.Responses;
5 | using Microsoft.AspNetCore.Mvc;
6 | using Microsoft.AspNetCore.Mvc.Filters;
7 |
8 | public class ModelValidationFilterAttribute : ActionFilterAttribute
9 | {
10 | public override void OnActionExecuting(ActionExecutingContext context)
11 | {
12 | if (context.ModelState.IsValid)
13 | {
14 | base.OnActionExecuting(context);
15 | return;
16 | }
17 |
18 | var modelErrors = context.ModelState.Values
19 | .SelectMany(x => x.Errors)
20 | .Select(x => new ApiResponseError {Title = x.ErrorMessage, Detail = x.Exception?.Message})
21 | .ToArray();
22 | context.Result = new BadRequestObjectResult(ApiResponse.Error(modelErrors));
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web/Validation/MvcOptionsExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Skeleton.Web.Validation
2 | {
3 | using Microsoft.AspNetCore.Mvc;
4 |
5 | public static class MvcOptionsExtensions
6 | {
7 | public static MvcOptions UseModelValidationFilter(this MvcOptions mvcOptions)
8 | {
9 | mvcOptions.Filters.Add();
10 | return mvcOptions;
11 | }
12 |
13 | public static MvcOptions UseParametersValidationFilter(this MvcOptions mvcOptions)
14 | {
15 | mvcOptions.Filters.Add(new ParametersValidationFilterAttribute());
16 | return mvcOptions;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/Infrastructure/Web/Web.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library with common classes for WebApi creation
5 |
6 | $(Description)
7 | Branch: $(RepositoryBranch)
8 | Working tree: $(RepositoryUrl)/tree/$(RepositoryCommit)
9 | Commit message: $(RepositoryCommitMessage)
10 |
11 | netcoreapp3.1
12 | Skeleton.Web
13 | Skeleton.Web
14 | Skeleton.Web
15 | WebApi common classes
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/Web.Application/Controllers/AccountController.cs:
--------------------------------------------------------------------------------
1 | namespace Web.Application.Controllers
2 | {
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Security.Claims;
6 | using Microsoft.AspNetCore.Authorization;
7 | using Microsoft.AspNetCore.Mvc;
8 |
9 | ///
10 | /// Endpoint for account information
11 | ///
12 | public class AccountController : Controller
13 | {
14 | ///
15 | /// Get all claims for current user
16 | ///
17 | ///
18 | [Authorize]
19 | [HttpPost("UserInfo")]
20 | public IEnumerable UserInfo()
21 | {
22 | var identity = (ClaimsIdentity)User.Identity;
23 |
24 | return identity.Claims
25 | .Select(x => $"{x.Type}:{x.Value}")
26 | .ToArray();
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/Web.Application/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyConfiguration("")]
9 | [assembly: AssemblyCompany("")]
10 | [assembly: AssemblyProduct("Web.Application")]
11 | [assembly: AssemblyTrademark("")]
12 |
13 | // Setting ComVisible to false makes the types in this assembly not visible
14 | // to COM components. If you need to access a type in this assembly from
15 | // COM, set the ComVisible attribute to true on that type.
16 | [assembly: ComVisible(false)]
17 |
18 | // The following GUID is for the ID of the typelib if this project is exposed to COM
19 | [assembly: Guid("5f5403fc-219b-4d72-af7e-2bf4e26f9ec4")]
20 |
--------------------------------------------------------------------------------
/src/Web.Application/Services/TokenIssueEventHandler.cs:
--------------------------------------------------------------------------------
1 | namespace Web.Application.Services
2 | {
3 | using System.Security.Claims;
4 | using Microsoft.Extensions.Logging;
5 | using Skeleton.Web.Authentication.JwtBearer;
6 |
7 | public class TokenIssueEventHandler : ITokenIssueEventHandler
8 | {
9 | readonly ILogger _logger;
10 |
11 | public TokenIssueEventHandler(ILogger logger)
12 | {
13 | _logger = logger;
14 | }
15 |
16 | public void IssueSuccessEventHandle(string token, Claim[] user)
17 | {
18 | _logger.LogDebug("Token issued successfully. Token: {0}", token);
19 | }
20 |
21 | public void LoginNotFoundEventHandle(string login)
22 | {
23 | _logger.LogDebug("Token not issued. Login {0} not found.", login);
24 | }
25 |
26 | public void IncorrectPasswordEventHandle(string login, string password)
27 | {
28 | _logger.LogDebug("Token not issued. Incorrect password {0} for login {1}.", password, login);
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/Web.Application/Services/UserClaimsProvider.cs:
--------------------------------------------------------------------------------
1 | namespace Web.Application.Services
2 | {
3 | using System.Security.Claims;
4 | using System.Threading.Tasks;
5 | using JetBrains.Annotations;
6 | using Skeleton.Web.Authentication.JwtBearer.UserClaimsProvider;
7 | using Skeleton.Web.Authentication.JwtBearer.UserClaimsProvider.Exceptions;
8 |
9 | [UsedImplicitly]
10 | public class UserClaimsProvider : IUserClaimsProvider
11 | {
12 | public Task GetClaimsAsync(string login, string password)
13 | {
14 | if (login == "lhp@lhp.com")
15 | {
16 | if (password != "1234")
17 | throw new IncorrectPasswordException(login);
18 | return Task.FromResult(new[] {new Claim(ClaimTypes.Email, login)});
19 | }
20 |
21 | throw new LoginNotFoundException(login);
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Web.Application/Web.Application.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | dmitriy.litichevskiy
7 | netcoreapp3.1
8 | portable
9 | true
10 | Web.Application
11 | Web.Application
12 | false
13 | false
14 | false
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/Web.Client/ApiClient.Account.cs:
--------------------------------------------------------------------------------
1 | namespace Web.Client
2 | {
3 | using ServicesClients.AccountController;
4 |
5 | public partial class ApiClient
6 | {
7 | private readonly AccountControllerClient _accountControllerClient;
8 |
9 | public ApiClient Login(string login, string password)
10 | {
11 | var response = _accountControllerClient.Token(login, password);
12 | CurrentState = response;
13 | _accountControllerClient.SetToken(response.Token);
14 | return this;
15 | }
16 |
17 | public ApiClient UserInfo()
18 | {
19 | CurrentState = _accountControllerClient.UserInfo();
20 | return this;
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/Web.Client/ApiClient.cs:
--------------------------------------------------------------------------------
1 | namespace Web.Client
2 | {
3 | using System;
4 | using System.Net.Http;
5 | using Microsoft.Extensions.Options;
6 | using ServicesClients.AccountController;
7 | using ServicesClients.ValuesService;
8 | using Skeleton.Web.Integration.BaseApiFluentClient;
9 |
10 | public partial class ApiClient : BaseFluentClient
11 | {
12 | public ApiClient(HttpClient httpClient, IOptions clientOptions)
13 | {
14 | if(httpClient == null)
15 | throw new ArgumentNullException(nameof(httpClient));
16 | if (clientOptions == null)
17 | throw new ArgumentNullException(nameof(clientOptions));
18 |
19 | var optionsValue = clientOptions.Value;
20 |
21 | _valuesServiceClient = new ValuesServiceClient(
22 | httpClient,
23 | Options.Create(
24 | new ValuesServiceClientOptions
25 | {
26 | BaseUrl = optionsValue.BaseUrl,
27 | Timeout = optionsValue.Timeout,
28 | Serializer = optionsValue.Serializer
29 | }
30 | )
31 | );
32 | ServicesClients.Add(_valuesServiceClient);
33 |
34 | _accountControllerClient = new AccountControllerClient(
35 | httpClient,
36 | Options.Create(
37 | new AccountControllerClientOptions
38 | {
39 | BaseUrl = optionsValue.BaseUrl,
40 | Timeout = optionsValue.Timeout,
41 | Serializer = optionsValue.Serializer
42 | }
43 | )
44 | );
45 | ServicesClients.Add(_accountControllerClient);
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/src/Web.Client/ApiClientOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Web.Client
2 | {
3 | using Skeleton.Web.Integration.BaseApiClient.Configuration;
4 |
5 | public class ApiClientOptions : BaseClientOptions
6 | {
7 | }
8 | }
--------------------------------------------------------------------------------
/src/Web.Client/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyConfiguration("")]
9 | [assembly: AssemblyCompany("")]
10 | [assembly: AssemblyProduct("Web.Client")]
11 | [assembly: AssemblyTrademark("")]
12 |
13 | // Setting ComVisible to false makes the types in this assembly not visible
14 | // to COM components. If you need to access a type in this assembly from
15 | // COM, set the ComVisible attribute to true on that type.
16 | [assembly: ComVisible(false)]
17 |
18 | // The following GUID is for the ID of the typelib if this project is exposed to COM
19 | [assembly: Guid("1eb8cdd8-c701-4b90-a766-7a9e660e2278")]
20 |
--------------------------------------------------------------------------------
/src/Web.Client/ServicesClients/AccountController/AccountControllerClientOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Web.Client.ServicesClients.AccountController
2 | {
3 | using Skeleton.Web.Integration.BaseApiClient.Configuration;
4 |
5 | public class AccountControllerClientOptions : BaseClientOptions
6 | {
7 | }
8 | }
--------------------------------------------------------------------------------
/src/Web.Client/ServicesClients/AccountController/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Web.Client.ServicesClients.AccountController
2 | {
3 | using System;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using Skeleton.Web.Integration.BaseApiClient.Configuration;
7 | using Skeleton.Web.Serialization.Abstractions;
8 |
9 | public static class ServiceCollectionExtensions
10 | {
11 | public static IHttpClientBuilder AddAccountControllerClient(
12 | this IServiceCollection services,
13 | IConfiguration config,
14 | ISerializer serializer)
15 | {
16 | if (services == null)
17 | throw new ArgumentNullException(nameof(services));
18 | if (config == null)
19 | throw new ArgumentNullException(nameof(config));
20 | if (serializer == null)
21 | throw new ArgumentNullException(nameof(serializer));
22 |
23 | return services
24 | .AddClient()
25 | .ConfigureClient(config, builder => builder.WithSerializer(serializer));
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/Web.Client/ServicesClients/ValuesService/IValuesServiceClient.cs:
--------------------------------------------------------------------------------
1 | namespace Web.Client.ServicesClients.ValuesService
2 | {
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 | using Models.Input;
6 | using Skeleton.Web.Conventions.Responses;
7 |
8 | public interface IValuesServiceClient
9 | {
10 | IEnumerable Get();
11 |
12 | Task> GetAsync();
13 |
14 | string Get(int id);
15 |
16 | Task GetAsync(int id);
17 |
18 | void Set(ValuesModificationRequest request);
19 |
20 | Task SetAsync(ValuesModificationRequest request);
21 |
22 | ApiResponse Post(int id, string value);
23 |
24 | Task> PostAsync(int id, string value);
25 |
26 | void Delete(int id);
27 |
28 | Task DeleteAsync(int id);
29 | }
30 | }
--------------------------------------------------------------------------------
/src/Web.Client/ServicesClients/ValuesService/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Web.Client.ServicesClients.ValuesService
2 | {
3 | using System;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 | using Skeleton.Web.Integration.BaseApiClient.Configuration;
7 | using Skeleton.Web.Serialization.Abstractions;
8 |
9 | public static class ServiceCollectionExtensions
10 | {
11 | public static IHttpClientBuilder AddValuesServiceClient(
12 | this IServiceCollection services,
13 | IConfiguration config,
14 | ISerializer serializer)
15 | {
16 | if (services == null)
17 | throw new ArgumentNullException(nameof(services));
18 | if (config == null)
19 | throw new ArgumentNullException(nameof(config));
20 | if (serializer == null)
21 | throw new ArgumentNullException(nameof(serializer));
22 |
23 | return services
24 | .AddClient()
25 | .ConfigureClient(config, builder => builder.WithSerializer(serializer));
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/Web.Client/ServicesClients/ValuesService/ValuesServiceClientOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Web.Client.ServicesClients.ValuesService
2 | {
3 | using Skeleton.Web.Integration.BaseApiClient.Configuration;
4 |
5 | public class ValuesServiceClientOptions : BaseClientOptions
6 | {
7 | }
8 | }
--------------------------------------------------------------------------------
/src/Web.Client/Web.Client.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | dmitriy.litichevskiy
7 | netcoreapp3.1
8 | portable
9 | Web.Client
10 | Web.Client
11 | false
12 | false
13 | false
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | ApiClient.cs
26 |
27 |
28 | ApiClient.cs
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/Web.DataAccess/Commands/DeleteValueAsyncCommand.cs:
--------------------------------------------------------------------------------
1 | namespace Web.DataAccess.Commands
2 | {
3 | using System;
4 | using System.Threading.Tasks;
5 | using Domain.CommandContexts;
6 | using JetBrains.Annotations;
7 | using Repositories;
8 | using Skeleton.CQRS.Abstractions.Commands;
9 |
10 | [UsedImplicitly]
11 | public class DeleteValueAsyncCommand : IAsyncCommand
12 | {
13 | private readonly IValuesRepository _repository;
14 |
15 | public DeleteValueAsyncCommand(IValuesRepository repository)
16 | {
17 | if (repository == null)
18 | throw new ArgumentNullException(nameof(repository));
19 |
20 | _repository = repository;
21 | }
22 |
23 | public Task Execute(DeleteValueAsyncCommandContext commandContext)
24 | {
25 | _repository.Delete(commandContext.Key);
26 | return Task.FromResult(0);
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/Web.DataAccess/Commands/SetValueCommand.cs:
--------------------------------------------------------------------------------
1 | namespace Web.DataAccess.Commands
2 | {
3 | using System;
4 | using Domain.CommandContexts;
5 | using JetBrains.Annotations;
6 | using Repositories;
7 | using Skeleton.CQRS.Abstractions.Commands;
8 |
9 | [UsedImplicitly]
10 | public class SetValueCommand : ICommand
11 | {
12 | private readonly IValuesRepository _repository;
13 |
14 | public SetValueCommand(IValuesRepository repository)
15 | {
16 | if (repository == null)
17 | throw new ArgumentNullException(nameof(repository));
18 |
19 | _repository = repository;
20 | }
21 |
22 | public void Execute(SetValueCommandContext commandContext)
23 | {
24 | _repository.Set(commandContext.Key, commandContext.Value);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/Web.DataAccess/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyConfiguration("")]
9 | [assembly: AssemblyCompany("")]
10 | [assembly: AssemblyProduct("Web.DataAccess")]
11 | [assembly: AssemblyTrademark("")]
12 |
13 | // Setting ComVisible to false makes the types in this assembly not visible
14 | // to COM components. If you need to access a type in this assembly from
15 | // COM, set the ComVisible attribute to true on that type.
16 | [assembly: ComVisible(false)]
17 |
18 | // The following GUID is for the ID of the typelib if this project is exposed to COM
19 | [assembly: Guid("13f2aac7-af9d-4e1a-ac2d-86b011ed4450")]
20 |
--------------------------------------------------------------------------------
/src/Web.DataAccess/Queries/GetAllValuesQuery.cs:
--------------------------------------------------------------------------------
1 | namespace Web.DataAccess.Queries
2 | {
3 | using System;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Domain.Criteria;
7 | using Domain.Dtos;
8 | using JetBrains.Annotations;
9 | using Microsoft.Extensions.Options;
10 | using Repositories;
11 | using Skeleton.CQRS.Abstractions.Queries;
12 |
13 | [UsedImplicitly]
14 | public class GetAllValuesQuery : IAsyncQuery
15 | {
16 | private readonly IValuesRepository _repository;
17 | private readonly DefaultConfigurationValues _defaultConfigurationValues;
18 |
19 | public GetAllValuesQuery(IValuesRepository repository, IOptions defaultConfigurationValues)
20 | {
21 | if (repository == null)
22 | throw new ArgumentNullException(nameof(repository));
23 | if (defaultConfigurationValues == null)
24 | throw new ArgumentNullException(nameof(defaultConfigurationValues));
25 |
26 | _repository = repository;
27 | _defaultConfigurationValues = defaultConfigurationValues.Value;
28 | }
29 |
30 | public Task Ask(GetAllValuesQueryCriterion criterion)
31 | {
32 | var values = _repository.Get();
33 | var valuesArray = values as string[] ?? values.ToArray();
34 |
35 | return Task.FromResult(valuesArray.Length == 0 ? _defaultConfigurationValues.Values : valuesArray);
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/src/Web.DataAccess/Queries/GetValueQuery.cs:
--------------------------------------------------------------------------------
1 | namespace Web.DataAccess.Queries
2 | {
3 | using System;
4 | using Domain.Criteria;
5 | using JetBrains.Annotations;
6 | using Repositories;
7 | using Skeleton.CQRS.Abstractions.Queries;
8 |
9 | [UsedImplicitly]
10 | public class GetValueQuery : IQuery
11 | {
12 | private readonly IValuesRepository _repository;
13 |
14 | public GetValueQuery(IValuesRepository repository)
15 | {
16 | if (repository == null)
17 | throw new ArgumentNullException(nameof(repository));
18 |
19 | _repository = repository;
20 | }
21 |
22 | public string Ask(GetValueQueryCriterion criterion)
23 | {
24 | return _repository.Get(criterion.Key);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/Web.DataAccess/Repositories/IValuesRepository.cs:
--------------------------------------------------------------------------------
1 | namespace Web.DataAccess.Repositories
2 | {
3 | using System.Collections.Generic;
4 |
5 | public interface IValuesRepository
6 | {
7 | ///
8 | /// Returns all stored values
9 | ///
10 | /// All stored values
11 | IEnumerable Get();
12 |
13 | ///
14 | /// Return value for key from storage
15 | ///
16 | /// Storage key
17 | /// Value for key
18 | /// Value with