├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── APIBlox.AspNetCore.CommandsQueriesControllersOhMy ├── APIBlox.AspNetCore.CommandsQueriesControllersOhMy.csproj ├── AssemblyInfo.cs ├── Extensions │ └── ComposedTemplatesExtensions.cs └── Templates │ ├── DeleteBy │ ├── ActionContent.txt │ ├── CtorArgs.txt │ ├── CtorBody.txt │ ├── Fields.txt │ └── Namespaces.txt │ ├── PatchBy │ ├── ActionContent.txt │ ├── CtorArgs.txt │ ├── CtorBody.txt │ ├── Fields.txt │ └── Namespaces.txt │ ├── Post │ ├── ActionContent.txt │ ├── CtorArgs.txt │ ├── CtorBody.txt │ ├── Fields.txt │ ├── Methods.txt │ └── Namespaces.txt │ ├── PostAccepted │ ├── ActionContent.txt │ ├── CtorArgs.txt │ ├── CtorBody.txt │ ├── Fields.txt │ └── Namespaces.txt │ ├── PutBy │ ├── ActionContent.txt │ ├── CtorArgs.txt │ ├── CtorBody.txt │ ├── Fields.txt │ └── Namespaces.txt │ ├── QueryAll │ ├── ActionContent.txt │ ├── CtorArgs.txt │ ├── CtorBody.txt │ ├── Fields.txt │ └── Namespaces.txt │ └── QueryBy │ ├── ActionContent.txt │ ├── CtorArgs.txt │ ├── CtorBody.txt │ ├── Fields.txt │ └── Namespaces.txt ├── APIBlox.AspNetCore.DynamicControllers ├── .gitattributes ├── .gitignore ├── APIBlox.AspNetCore.DynamicControllers.csproj ├── APIBlox.AspNetCore.DynamicControllers.csproj.DotSettings ├── AssemblyInfo.cs ├── Contracts │ └── IComposedTemplate.cs ├── DynamicControllerFactory.cs ├── Exceptions │ └── TemplateCompilationException.cs ├── Extensions │ ├── MvcBuilderExtensions.cs │ └── ServiceCollectionExtensions.cs ├── Filters │ └── PostLocationHeaderResultFilter.cs ├── Templates │ └── DynamicController.txt └── Types │ ├── DynamicAction.cs │ ├── DynamicComments.cs │ ├── DynamicController.cs │ ├── DynamicControllerComposedTemplate.cs │ └── DynamicControllerTemplateOptions.cs ├── APIBlox.AspNetCore ├── .gitattributes ├── .gitignore ├── APIBlox.AspNetCore.csproj ├── APIBlox.AspNetCore.csproj.DotSettings ├── ActionResults │ ├── ProblemResult.cs │ └── ValidationFailureResult.cs ├── AssemblyInfo.cs ├── Attributes │ └── FromQueryWithAlternateNamesAttribute.cs ├── Constants.cs ├── Contracts │ ├── IFilteredQuery.cs │ ├── IOrderedQuery.cs │ ├── IPaginationMetadataBuilder.cs │ ├── IPaginationQuery.cs │ ├── IProjectedQuery.cs │ ├── IQuery.cs │ └── IResource.cs ├── Conventions │ └── RouteTokensConvention.cs ├── Enums │ └── CommonStatusCodes.cs ├── Exceptions │ └── HandledRequestException.cs ├── Extensions │ ├── ApplicationBuilderExtensions.cs │ ├── CollectionExtensions.cs │ ├── ErrorExtensions.cs │ ├── HandlerResponseExtensions.cs │ ├── HttpContextExtensions.cs │ ├── MvcBuilderExtensions.cs │ ├── QueryableExtensions.cs │ ├── RequestErrorObjectExtensions.cs │ └── ServiceCollectionExtensions.cs ├── Filters │ ├── Action Filters │ │ ├── ETagActionFilter.cs │ │ ├── EnsurePaginationResponseResultActionFilter.cs │ │ ├── EnsureResponseResultActionFilter.cs │ │ └── ValidateResourceActionFilter.cs │ ├── Authorization Filters │ │ └── ProblemResultAuthorizationFilter.cs │ └── Exception Filters │ │ └── OperationCanceledExceptionFilter.cs ├── Middleware │ ├── ServerFaultsMiddleware.cs │ └── SimulateWaitTimeMiddleware.cs ├── ModelBinders │ ├── FromQueryWithAlterenateNamesBinderProvider.cs │ └── FromQueryWithAlternateNamesBinder.cs ├── Services │ ├── PaginationMetadata.cs │ └── PaginationMetadataBuilder.cs └── Types │ ├── Errors │ ├── DynamicErrorObject.cs │ ├── RequestErrorObject.cs │ └── ServerErrorObject.cs │ ├── FilteredOrderedQuery.cs │ ├── FilteredPaginationQuery.cs │ ├── FilteredProjectedOrderedPaginationQuery.cs │ ├── FilteredProjectedOrderedQuery.cs │ ├── FilteredProjectedPaginationQuery.cs │ ├── FilteredProjectedQuery.cs │ ├── FilteredQuery.cs │ ├── HandlerResponse.cs │ ├── OrderedPaginationQuery.cs │ ├── OrderedQuery.cs │ ├── PaginationQuery.cs │ ├── ProjectedOrderedPaginationQuery.cs │ ├── ProjectedOrderedQuery.cs │ ├── ProjectedPaginationQuery.cs │ ├── ProjectedQuery.cs │ └── Query.cs ├── APIBlox.NetCore.CommandsAndQueries ├── .gitattributes ├── .gitignore ├── APIBlox.NetCore.CommandsAndQueries.csproj ├── AssemblyInfo.cs ├── Contracts │ ├── ICommandHandler.cs │ └── IQueryHandler.cs ├── Decorators │ ├── Commands │ │ ├── MetricsCommandHandlerDecorator.cs │ │ ├── RetryCommandHandlerDecorator.cs │ │ └── TransactionScopeCommandHandlerDecorator.cs │ └── Queries │ │ └── MetricsQueryHandlerDecorator.cs └── Extensions │ └── ServiceCollectionExtensions.cs ├── APIBlox.NetCore.Common ├── .gitattributes ├── .gitignore ├── APIBlox.NetCore.Common.csproj ├── AssemblyInfo.cs ├── Extensions │ ├── EnumExtensions.cs │ ├── EnumerableExtensions.cs │ ├── ExpressionExtensions.cs │ ├── StringCompressionExtensions.cs │ ├── StringExtensions.cs │ ├── StructExtensions.cs │ ├── TypeExtensions.cs │ └── XmlDocumentationExtensions.cs └── Types │ ├── DynamicDataObject.cs │ ├── JsonBits │ ├── AliasContractResolver.cs │ ├── CamelCasePopulateNonPublicSettersContractResolver.cs │ ├── CamelCaseSettings.cs │ ├── EmptyStringToNullConverter.cs │ └── PopulateNonPublicSettersContractResolver.cs │ └── SimpleMapper.cs ├── APIBlox.NetCore.DomainEvents ├── .gitattributes ├── .gitignore ├── APIBlox.NetCore.DomainEvents.csproj ├── AssemblyInfo.cs ├── Contracts │ ├── IDomainEvent.cs │ ├── IDomainEventHandler.cs │ ├── IDomainEventsDispatcher.cs │ └── IQueuedDomainEventsDispatcher.cs ├── Dispatchers │ ├── DispatcherBase.cs │ ├── DomainEventsDispatcher.cs │ └── QueuedDomainEventsDispatcher.cs ├── Domain Events Notes.txt ├── Extensions │ └── ServiceCollectionExtensions.cs └── Handlers │ ├── DomainEventHandlerBase.cs │ └── DomainEventHandlerWrapper.cs ├── APIBlox.NetCore.EventStore.CosmosDb ├── APIBlox.NetCore.EventStore.CosmosDb.csproj ├── AssemblyInfo.cs ├── CosmosDbRepository.cs ├── DbCollection.cs ├── DbCollectionFactory.cs ├── Extensions │ └── ServiceCollectionExtensions.cs ├── Options │ ├── CosmosDbCollectionProperties.cs │ └── CosmosDbOptions.cs └── bulkInsert.js ├── APIBlox.NetCore.EventStore.EfCore ├── APIBlox.NetCore.EventStore.EfCore.csproj ├── AssemblyInfo.cs ├── DocEx.cs ├── EfCoreSqlRepository.cs ├── EventStoreDbContext.cs ├── EventStoreDocumentMap.cs ├── Extensions │ └── ServiceCollectionExtensions.cs ├── Migrations │ ├── EventStoreDbContextModelSnapshot.cs │ ├── InitialCreate.Designer.cs │ └── InitialCreate.cs ├── Options │ └── EfCoreSqlOptions.cs └── appsettings.json ├── APIBlox.NetCore.EventStore.MongoDb ├── APIBlox.NetCore.EventStore.MongoDb.csproj ├── AssemblyInfo.cs ├── CollectionContext.cs ├── Extensions │ └── ServiceCollectionExtensions.cs ├── MongoDbRepository.cs └── Options │ ├── MongoDbCollectionProperties.cs │ └── MongoDbOptions.cs ├── APIBlox.NetCore.EventStore.RavenDb ├── APIBlox.NetCore.EventStore.RavenDb.csproj ├── AssemblyInfo.cs ├── Extensions │ └── ServiceCollectionExtensions.cs ├── Options │ ├── RavenDbCollectionProperties.cs │ └── RavenDbOptions.cs ├── RavenDbRepository.cs └── StoreContext.cs ├── APIBlox.NetCore.EventStore ├── APIBlox.NetCore.EventStore.csproj ├── AssemblyInfo.cs ├── Contracts │ ├── IEventStoreJsonSerializerSettings.cs │ ├── IEventStoreRepository.cs │ ├── IEventStoreService.cs │ └── IReadOnlyEventStoreService.cs ├── Documents │ ├── DocumentTypes.cs │ ├── EventDocument.cs │ ├── EventStoreDocument.cs │ ├── RootDocument.cs │ └── SnapshotDocument.cs ├── EventSourcedJsonSerializerSettings.cs ├── EventStoreService.cs ├── Exceptions │ ├── EventStoreAccessException.cs │ ├── EventStoreConcurrencyException.cs │ └── EventStoreNotFoundException.cs ├── Extensions │ └── ServiceCollectionExtensions.cs ├── Models │ ├── EventModel.cs │ ├── EventStreamModel.cs │ └── SnapshotModel.cs └── ReadOnlyEventStoreService.cs ├── APIBlox.NetCore ├── .gitattributes ├── .gitignore ├── APIBlox.NetCore.csproj ├── AssemblyInfo.cs ├── Attributes │ ├── InjectableServiceAttribute.cs │ └── MetadataAttribute.cs ├── Contracts │ └── IDependencyInvertedConfiguration.cs ├── Extensions │ ├── LoggerExtensions.cs │ ├── Options │ │ ├── ConfigureOptionsWithDependency.cs │ │ └── ConfigureOptionsWithDependencyContainer.cs │ └── ServiceCollectionExtensions │ │ ├── Other.cs │ │ └── ServiceDecoration.cs └── Types │ ├── AssemblyResolver.cs │ ├── PathParser.cs │ └── ResourceReader.cs ├── ApiBlox.AspNetCore.DynamicControllers └── APIBlox.AspNetCore.DynamicControllers.csproj ├── ApiBlox.AspNetCore └── APIBlox.AspNetCore.csproj ├── ApiBlox.NetCore.Common └── APIBlox.NetCore.Common.csproj ├── ApiBlox.NetCore └── APIBlox.NetCore.csproj ├── CODE_OF_CONDUCT.md ├── Directory.Build.props ├── Examples ├── APIBlox Features │ ├── .gitattributes │ ├── .gitignore │ └── Examples.Features │ │ ├── Configuration │ │ └── SwaggerConfig.cs │ │ ├── Contracts │ │ └── IRandomNumberGeneratorService.cs │ │ ├── Controllers │ │ └── ExamplesController.cs │ │ ├── Examples.Features.csproj │ │ ├── Examples.Features.xml │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── Resources │ │ └── ExampleRequestObject.cs │ │ ├── Services │ │ └── RandomNumberGeneratorService.cs │ │ ├── Startup.cs │ │ ├── appsettings.Development.json │ │ ├── appsettings.Production.json │ │ └── appsettings.json ├── CQRS │ ├── .gitattributes │ ├── .gitignore │ └── Examples.Cqrs │ │ ├── Commands │ │ ├── SimplePostCommand.cs │ │ └── SimplePostCommandDecorator.cs │ │ ├── Configuration │ │ ├── DecoratorsConfig.cs │ │ └── SwaggerConfig.cs │ │ ├── Controllers │ │ └── CqrsController.cs │ │ ├── Examples.Cqrs.csproj │ │ ├── Examples.Cqrs.xml │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── Queries │ │ ├── NoInputsQueryHandler.cs │ │ └── RequiresInputQueryQueryHandler.cs │ │ ├── Resources │ │ └── ExampleRequestObject.cs │ │ ├── Startup.cs │ │ ├── appsettings.Development.json │ │ └── appsettings.json ├── Clean Architecture │ ├── Application Layer │ │ ├── .gitattributes │ │ └── .gitignore │ ├── Cross-Cutting Concerns │ │ ├── .gitattributes │ │ └── .gitignore │ ├── Domain Layer │ │ ├── .gitattributes │ │ └── .gitignore │ ├── Infrastructure Layer │ │ ├── .gitattributes │ │ └── .gitignore │ ├── Persistance Layer │ │ ├── .gitattributes │ │ └── .gitignore │ └── Presentation Layer │ │ ├── .gitattributes │ │ └── .gitignore ├── Domain Events │ ├── .gitattributes │ ├── .gitignore │ └── Examples.DomainEvents │ │ ├── Configuration │ │ └── SwaggerConfig.cs │ │ ├── Contracts │ │ └── ILameRepository.cs │ │ ├── Controllers │ │ └── NonQueuedDomainEventsController.cs │ │ ├── EventBits │ │ ├── RequestObjectCreatedEvent.cs │ │ └── RequestObjectCreatedEventHandler.cs │ │ ├── Examples.DomainEvents.csproj │ │ ├── Examples.DomainEvents.csproj.DotSettings │ │ ├── Examples.DomainEvents.xml │ │ ├── InfrastructureAndDomainBits │ │ ├── DomainModels │ │ │ └── DomainObject.cs │ │ └── LameRepository.cs │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── Resources │ │ └── ExampleRequestObject.cs │ │ ├── Startup.cs │ │ ├── appsettings.Development.json │ │ └── appsettings.json ├── Dynamic Controllers │ ├── .gitattributes │ ├── .gitignore │ └── Examples.DynamicControllers │ │ ├── CmdQueryHandlers │ │ ├── ChildByIdRequestCommandHandler.cs │ │ ├── ChildByIdRequestHandlers.cs │ │ ├── ChildPatchRequestCommandHandler.cs │ │ ├── ChildPostRequestCommandHandler.cs │ │ ├── ChildPutRequestCommandHandler.cs │ │ └── ChildrenRequestQueryHandler.cs │ │ ├── Configuration │ │ ├── Children.cs │ │ ├── Parents.cs │ │ └── SwaggerConfig.cs │ │ ├── Contracts │ │ ├── IChildRequest.cs │ │ └── IRandomNumberGeneratorService.cs │ │ ├── Examples.DynamicControllers.csproj │ │ ├── Examples.DynamicControllers.xml │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── Resources │ │ ├── AllRequest.cs │ │ ├── ByIdRequest.cs │ │ ├── ChildByIdRequest.cs │ │ ├── ChildPatchRequest.cs │ │ ├── ChildPostRequest.cs │ │ ├── ChildPutRequest.cs │ │ ├── ChildRequest.cs │ │ ├── ChildResponse.cs │ │ ├── ParentPostRequest.cs │ │ ├── ParentRequest.cs │ │ ├── ParentResponse.cs │ │ └── PersonModel.cs │ │ ├── Services │ │ └── RandomNumberGeneratorService.cs │ │ ├── Startup.cs │ │ ├── StartupBase.cs │ │ ├── Testme.cs │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ └── swaggerGen.dat └── Event Sourcing │ └── Examples.EventSourcing │ ├── AggregateModels │ ├── Aggregate.cs │ ├── CosmosAggregate.cs │ ├── EfCoreSqlAggregate.cs │ ├── MongoAggregate.cs │ └── RavenAggregate.cs │ ├── Configuration │ └── SwaggerConfig.cs │ ├── Controllers │ ├── EventSourcingController.cs │ ├── EventSourcingCosmosDbController.cs │ ├── EventSourcingEfCoreController.cs │ ├── EventSourcingMongoDbController.cs │ └── EventSourcingRavenDbController.cs │ ├── Events │ ├── SomeValueAdded.cs │ └── SomeValueChanged.cs │ ├── Examples.EventSourcing.csproj │ ├── Examples.EventSourcing.csproj.DotSettings │ ├── Examples.EventSourcing.xml │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Resources │ └── AggregateResource.cs │ ├── Startup.cs │ ├── appsettings.Development.json │ └── appsettings.json ├── Kill Assets.Json.cmd ├── Kill Bin and Obj.cmd ├── LICENSE ├── SlnTests ├── APIBlox.AspNetCore.OpenApi │ └── BuilderTests.cs ├── APIBlox.AspNetCore │ ├── DynamicControllerTests.cs │ └── PaginationTests.cs ├── APIBlox.NetCore.EventStore │ └── InMemoryRepoTests.cs ├── APIBlox.NetCore │ ├── PathParserTests.cs │ ├── ServiceCollectionExtensionsNetCoreOtherTests.cs │ └── SimpleMapperTests.cs └── SlnTests.csproj ├── api-blox.sln ├── logo-blue-large.png ├── logo-blue-small.png ├── readme.md ├── releaseNotes.md └── response-objects.md /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | labels: 5 | 6 | --- 7 | 8 | **Describe the bug** 9 | A clear and concise description of what the bug is. 10 | 11 | **To Reproduce** 12 | Steps to reproduce the behavior: 13 | 1. Go to '...' 14 | 2. Click on '....' 15 | 3. Scroll down to '....' 16 | 4. See error 17 | 18 | **Expected behavior** 19 | A clear and concise description of what you expected to happen. 20 | 21 | **Screenshots** 22 | If applicable, add screenshots to help explain your problem. 23 | 24 | **Desktop (please complete the following information):** 25 | - OS: [e.g. iOS] 26 | - Browser [e.g. chrome, safari] 27 | - Version [e.g. 22] 28 | 29 | **Smartphone (please complete the following information):** 30 | - Device: [e.g. iPhone6] 31 | - OS: [e.g. iOS8.1] 32 | - Browser [e.g. stock browser, safari] 33 | - Version [e.g. 22] 34 | 35 | **Additional context** 36 | Add any other context about the problem here. 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | labels: 5 | 6 | --- 7 | 8 | **Is your feature request related to a problem? Please describe.** 9 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 10 | 11 | **Describe the solution you'd like** 12 | A clear and concise description of what you want to happen. 13 | 14 | **Describe alternatives you've considered** 15 | A clear and concise description of any alternative solutions or features you've considered. 16 | 17 | **Additional context** 18 | Add any other context or screenshots about the feature request here. 19 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/DeleteBy/ActionContent.txt: -------------------------------------------------------------------------------- 1 | [ACTION_COMMENTS] 2 | [RESPONSE_TYPES_COMMENTS] 3 | /// The cancellation token. 4 | [PARAMS_COMMENTS] 5 | [HttpDelete("[ACTION_ROUTE]")] 6 | [Produces("application/json", "application/problem+json")] 7 | [Consumes("application/json")] 8 | [ProducesErrorResponseType(typeof(RequestErrorObject))] 9 | [RESPONSE_TYPES] 10 | public async Task [CONTROLLER_NAME]DeleteBy[REQ_OBJECT]( 11 | [FromServices]ICommandHandler<[REQ_OBJECT], HandlerResponse> handler, 12 | [ACTION_PARAMS] 13 | CancellationToken cancellationToken 14 | ) 15 | { 16 | var ret = await handler.HandleAsync( 17 | [NEW_REQ_OBJECT], 18 | cancellationToken 19 | ); 20 | 21 | if (ret is null) 22 | throw new ArgumentException($"You must return a {nameof(HandlerResponse)} instance!"); 23 | 24 | if (ret.HasErrors) 25 | return new ProblemResult(ret.Error); 26 | 27 | return ret.HasErrors 28 | ? (IActionResult) new ProblemResult(ret.Error) 29 | : NoContent(); 30 | } -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/DeleteBy/CtorArgs.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/DeleteBy/CtorBody.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/DeleteBy/Fields.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/DeleteBy/Namespaces.txt: -------------------------------------------------------------------------------- 1 | System 2 | System.Threading 3 | System.Threading.Tasks 4 | Microsoft.AspNetCore.Http 5 | Microsoft.AspNetCore.Mvc 6 | APIBlox.NetCore.Contracts 7 | APIBlox.AspNetCore.ActionResults 8 | APIBlox.AspNetCore.Contracts 9 | APIBlox.AspNetCore.Types -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PatchBy/ActionContent.txt: -------------------------------------------------------------------------------- 1 | [ACTION_COMMENTS] 2 | [RESPONSE_TYPES_COMMENTS] 3 | /// The cancellation token. 4 | [PARAMS_COMMENTS] 5 | [HttpPatch("[ACTION_ROUTE]")] 6 | [Produces("application/json", "application/problem+json")] 7 | [Consumes("application/json","application/json-patch+json")] 8 | [ProducesErrorResponseType(typeof(RequestErrorObject))] 9 | [RESPONSE_TYPES] 10 | public async Task [CONTROLLER_NAME]PatchBy[REQ_OBJECT]( 11 | [FromServices]ICommandHandler<[REQ_OBJECT], HandlerResponse> handler, 12 | [ACTION_PARAMS] 13 | CancellationToken cancellationToken 14 | ) 15 | { 16 | var ret = await handler.HandleAsync( 17 | [NEW_REQ_OBJECT], 18 | cancellationToken 19 | ); 20 | 21 | if (ret is null) 22 | throw new ArgumentException($"You must return a {nameof(HandlerResponse)} instance!"); 23 | 24 | return ret.HasErrors 25 | ? (IActionResult) new ProblemResult(ret.Error) 26 | : NoContent(); 27 | } -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PatchBy/CtorArgs.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PatchBy/CtorBody.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PatchBy/Fields.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PatchBy/Namespaces.txt: -------------------------------------------------------------------------------- 1 | System 2 | System.Threading 3 | System.Threading.Tasks 4 | Microsoft.AspNetCore.Http 5 | Microsoft.AspNetCore.JsonPatch 6 | Microsoft.AspNetCore.Mvc 7 | APIBlox.NetCore.Contracts 8 | APIBlox.AspNetCore.ActionResults 9 | APIBlox.AspNetCore.Contracts 10 | APIBlox.AspNetCore.Types 11 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/Post/ActionContent.txt: -------------------------------------------------------------------------------- 1 | [ACTION_COMMENTS] 2 | [RESPONSE_TYPES_COMMENTS] 3 | /// The cancellation token. 4 | [PARAMS_COMMENTS] 5 | [HttpPost("[ACTION_ROUTE]")] 6 | [Produces("application/json", "application/problem+json")] 7 | [Consumes("application/json")] 8 | [ProducesErrorResponseType(typeof(RequestErrorObject))] 9 | [RESPONSE_TYPES] 10 | public async Task [CONTROLLER_NAME]Post[REQ_OBJECT]( 11 | [FromServices]ICommandHandler<[REQ_OBJECT], HandlerResponse> handler, 12 | [ACTION_PARAMS] 13 | CancellationToken cancellationToken 14 | ) 15 | { 16 | var ret = await handler.HandleAsync( 17 | [NEW_REQ_OBJECT], 18 | cancellationToken 19 | ); 20 | 21 | if (ret is null) 22 | throw new ArgumentException($"You must return a {nameof(HandlerResponse)} instance!"); 23 | 24 | var errorResult = ret.HasErrors ? new ProblemResult(ret.Error) : null; 25 | 26 | if (errorResult is null && ret.Result is null) 27 | throw new NullReferenceException( 28 | "When responding to a POST you must either set an error or pass some results!" 29 | ); 30 | 31 | if (errorResult is not null) 32 | return errorResult; 33 | 34 | var id = FindId(ret.Result); 35 | 36 | return Equals(id, -1) ? Ok(ret.Result) : CreatedAtRoute(new {id}, ret.Result); 37 | } -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/Post/CtorArgs.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/Post/CtorBody.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/Post/Fields.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/Post/Methods.txt: -------------------------------------------------------------------------------- 1 |  private object FindId(object result) 2 | { 3 | try 4 | { 5 | var t = result.GetType(); 6 | var props = t.GetProperties(); 7 | 8 | var id = props.FirstOrDefault(p => p.Name.EqualsEx("Id")); 9 | 10 | if (id is null) 11 | foreach (var pi in props) 12 | return FindId(t.GetProperty(pi.Name).GetValue(result, null)); 13 | else 14 | return t.GetProperty(id.Name).GetValue(result, null); 15 | } 16 | catch (Exception ex) 17 | { 18 | _log.LogWarning(() => $"Could not determine ID for CreatedAtRoute result! Ex: {ex.Message}"); 19 | 20 | return -1; 21 | } 22 | 23 | return -1; 24 | } -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/Post/Namespaces.txt: -------------------------------------------------------------------------------- 1 | System 2 | System.Linq 3 | System.Threading 4 | System.Threading.Tasks 5 | Microsoft.AspNetCore.Http 6 | Microsoft.AspNetCore.Mvc 7 | Microsoft.Extensions.Logging 8 | APIBlox.NetCore.Contracts 9 | APIBlox.NetCore.Extensions 10 | APIBlox.AspNetCore.ActionResults 11 | APIBlox.AspNetCore.Contracts 12 | APIBlox.AspNetCore.Types 13 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PostAccepted/ActionContent.txt: -------------------------------------------------------------------------------- 1 | [ACTION_COMMENTS] 2 | [RESPONSE_TYPES_COMMENTS] 3 | /// The cancellation token. 4 | [PARAMS_COMMENTS] 5 | [HttpPost("[ACTION_ROUTE]")] 6 | [Produces("application/json", "application/problem+json")] 7 | [Consumes("application/json")] 8 | [ProducesErrorResponseType(typeof(RequestErrorObject))] 9 | [RESPONSE_TYPES] 10 | public async Task [CONTROLLER_NAME]PostAccepted[REQ_OBJECT]( 11 | [FromServices]ICommandHandler<[REQ_OBJECT], HandlerResponse> handler, 12 | [ACTION_PARAMS] 13 | CancellationToken cancellationToken 14 | ) 15 | { 16 | var ret = await handler.HandleAsync( 17 | [NEW_REQ_OBJECT], 18 | cancellationToken 19 | ); 20 | 21 | if (ret is null) 22 | throw new ArgumentException($"You must return a {nameof(HandlerResponse)} instance!"); 23 | 24 | var errorResult = ret.HasErrors 25 | ? new ProblemResult(ret.Error) 26 | : null; 27 | 28 | if (errorResult is not null) 29 | return errorResult; 30 | 31 | return ret.Result is null ? Accepted() : Accepted(ret.Result); 32 | } -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PostAccepted/CtorArgs.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PostAccepted/CtorBody.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PostAccepted/Fields.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PostAccepted/Namespaces.txt: -------------------------------------------------------------------------------- 1 | System 2 | System.Threading 3 | System.Threading.Tasks 4 | Microsoft.AspNetCore.Http 5 | Microsoft.AspNetCore.Mvc 6 | APIBlox.NetCore.Contracts 7 | APIBlox.AspNetCore.ActionResults 8 | APIBlox.AspNetCore.Contracts 9 | APIBlox.AspNetCore.Types 10 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PutBy/ActionContent.txt: -------------------------------------------------------------------------------- 1 | [ACTION_COMMENTS] 2 | [RESPONSE_TYPES_COMMENTS] 3 | /// The cancellation token. 4 | [PARAMS_COMMENTS] 5 | [HttpPut("[ACTION_ROUTE]")] 6 | [Produces("application/json", "application/problem+json")] 7 | [Consumes("application/json")] 8 | [ProducesErrorResponseType(typeof(RequestErrorObject))] 9 | [RESPONSE_TYPES] 10 | public async Task [CONTROLLER_NAME]PutBy[REQ_OBJECT]( 11 | [FromServices]ICommandHandler<[REQ_OBJECT], HandlerResponse> handler, 12 | [ACTION_PARAMS] 13 | CancellationToken cancellationToken 14 | ) 15 | { 16 | var ret = await handler.HandleAsync( 17 | [NEW_REQ_OBJECT], 18 | cancellationToken 19 | ); 20 | 21 | if (ret is null) 22 | throw new ArgumentException($"You must return a {nameof(HandlerResponse)} instance!"); 23 | 24 | return ret.HasErrors 25 | ? (IActionResult) new ProblemResult(ret.Error) 26 | : NoContent(); 27 | } -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PutBy/CtorArgs.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PutBy/CtorBody.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PutBy/Fields.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/PutBy/Namespaces.txt: -------------------------------------------------------------------------------- 1 | System 2 | System.Threading 3 | System.Threading.Tasks 4 | Microsoft.AspNetCore.Http 5 | Microsoft.AspNetCore.Mvc 6 | APIBlox.NetCore.Contracts 7 | APIBlox.AspNetCore.ActionResults 8 | APIBlox.AspNetCore.Contracts 9 | APIBlox.AspNetCore.Types 10 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/QueryAll/ActionContent.txt: -------------------------------------------------------------------------------- 1 | [ACTION_COMMENTS] 2 | [RESPONSE_TYPES_COMMENTS] 3 | /// The cancellation token. 4 | [PARAMS_COMMENTS] 5 | [HttpGet("[ACTION_ROUTE]")] 6 | [Produces("application/json", "application/problem+json")] 7 | [Consumes("application/json")] 8 | [ProducesErrorResponseType(typeof(RequestErrorObject))] 9 | [RESPONSE_TYPES] 10 | public async Task [CONTROLLER_NAME]QueryAll[REQ_OBJECT]( 11 | [FromServices]IQueryHandler<[REQ_OBJECT], HandlerResponse> handler, 12 | [ACTION_PARAMS] 13 | CancellationToken cancellationToken 14 | ) 15 | { 16 | var ret = await handler.HandleAsync( 17 | [NEW_REQ_OBJECT], 18 | cancellationToken 19 | ); 20 | 21 | if (ret is null) 22 | throw new ArgumentException($"You must return a {nameof(HandlerResponse)} instance!"); 23 | 24 | if (ret.HasErrors) 25 | return new ProblemResult(ret.Error); 26 | 27 | if (ret.Result is null) 28 | throw new ArgumentNullException( 29 | nameof(HandlerResponse.Result), 30 | "When responding to a GET you must either set an error or pass a result!" 31 | ); 32 | 33 | return Ok(ret.Result); 34 | } -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/QueryAll/CtorArgs.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/QueryAll/CtorBody.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/QueryAll/Fields.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/QueryAll/Namespaces.txt: -------------------------------------------------------------------------------- 1 | System 2 | System.Threading 3 | System.Threading.Tasks 4 | Microsoft.AspNetCore.Http 5 | Microsoft.AspNetCore.Mvc 6 | APIBlox.NetCore.Contracts 7 | APIBlox.AspNetCore.ActionResults 8 | APIBlox.AspNetCore.Contracts 9 | APIBlox.AspNetCore.Types 10 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/QueryBy/ActionContent.txt: -------------------------------------------------------------------------------- 1 | [ACTION_COMMENTS] 2 | [RESPONSE_TYPES_COMMENTS] 3 | /// The cancellation token. 4 | [PARAMS_COMMENTS] 5 | [HttpGet("[ACTION_ROUTE]")] 6 | [Produces("application/json", "application/problem+json")] 7 | [Consumes("application/json")] 8 | [ProducesErrorResponseType(typeof(RequestErrorObject))] 9 | [RESPONSE_TYPES] 10 | public async Task [CONTROLLER_NAME]QueryBy[REQ_OBJECT]( 11 | [FromServices]IQueryHandler<[REQ_OBJECT], HandlerResponse> handler, 12 | [ACTION_PARAMS] 13 | CancellationToken cancellationToken 14 | ) 15 | { 16 | var ret = await handler.HandleAsync( 17 | [NEW_REQ_OBJECT], 18 | cancellationToken 19 | ); 20 | 21 | if (ret is null) 22 | throw new ArgumentException($"You must return a {nameof(HandlerResponse)} instance!"); 23 | 24 | if (ret.HasErrors) 25 | return new ProblemResult(ret.Error); 26 | 27 | if (ret.Result is null) 28 | throw new ArgumentNullException( 29 | nameof(HandlerResponse.Result), 30 | "When responding to a GET you must either set an error or pass a result!" 31 | ); 32 | 33 | return Ok(ret.Result); 34 | } 35 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/QueryBy/CtorArgs.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/QueryBy/CtorBody.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/QueryBy/Fields.txt: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /APIBlox.AspNetCore.CommandsQueriesControllersOhMy/Templates/QueryBy/Namespaces.txt: -------------------------------------------------------------------------------- 1 | System 2 | System.Threading 3 | System.Threading.Tasks 4 | Microsoft.AspNetCore.Http 5 | Microsoft.AspNetCore.Mvc 6 | APIBlox.NetCore.Contracts 7 | APIBlox.AspNetCore.ActionResults 8 | APIBlox.AspNetCore.Contracts 9 | APIBlox.AspNetCore.Types 10 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.DynamicControllers/APIBlox.AspNetCore.DynamicControllers.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | net5.0 6 | 7 | APIBlox.AspNetCore 8 | 9 | Simple dynamic controllers package that puts the focus on resources. 10 | 11 | APIBlox.AspNetCore.DynamicControllers 12 | 13 | APIBlox.AspNetCore.DynamicControllers 14 | 15 | APIBlox.AspNetCore.DynamicControllers 16 | 17 | latest 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | all 40 | runtime; build; native; contentfiles; analyzers 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.DynamicControllers/APIBlox.AspNetCore.DynamicControllers.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True -------------------------------------------------------------------------------- /APIBlox.AspNetCore.DynamicControllers/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.DynamicControllers/Contracts/IComposedTemplate.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Types; 2 | 3 | namespace APIBlox.AspNetCore.Contracts 4 | { 5 | /// 6 | /// Interface IComposedTemplate 7 | /// 8 | public interface IComposedTemplate 9 | { 10 | /// 11 | /// Gets the action. 12 | /// 13 | /// The action. 14 | DynamicAction Action { get; } 15 | 16 | /// 17 | /// Gets or sets the name. 18 | /// 19 | /// The name. 20 | string Name { get; set; } 21 | 22 | /// 23 | /// Gets the route. 24 | /// 25 | /// The route. 26 | string Route { get; } 27 | 28 | /// 29 | /// Gets the namespace. 30 | /// 31 | /// The namespace. 32 | string Namespace { get; } 33 | 34 | /// 35 | /// Gets the comments. 36 | /// 37 | /// The comments. 38 | string Comments { get; set; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.DynamicControllers/Exceptions/TemplateCompilationException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace APIBlox.AspNetCore.Exceptions 5 | { 6 | /// 7 | /// 8 | /// Class TemplateCompilationException. 9 | /// 10 | [Serializable] 11 | public class TemplateCompilationException : Exception 12 | { 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// The compilation errors. 17 | public TemplateCompilationException(IEnumerable compilationErrors) 18 | : base($"Compilation Errors: \n{string.Join(Environment.NewLine, compilationErrors)}") 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.DynamicControllers/Extensions/MvcBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore; 2 | 3 | // ReSharper disable once CheckNamespace 4 | namespace Microsoft.Extensions.DependencyInjection 5 | { 6 | /// 7 | /// Class MvcBuilderExtensions. 8 | /// 9 | public static class MvcBuilderExtensions 10 | { 11 | /// 12 | /// Adds the post location header result filter. 13 | /// 14 | /// The builder. 15 | /// IMvcBuilder. 16 | public static IMvcBuilder AddPostLocationHeaderResultFilter( 17 | this IMvcBuilder builder 18 | ) 19 | { 20 | return builder.AddFilter(order: 100); 21 | } 22 | 23 | /// 24 | /// Adds the post location header result filter. 25 | /// 26 | /// The builder. 27 | /// IMvcCoreBuilder. 28 | public static IMvcCoreBuilder AddPostLocationHeaderResultFilter( 29 | this IMvcCoreBuilder builder 30 | ) 31 | { 32 | return builder.AddFilter(order: 100); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.DynamicControllers/Templates/DynamicController.txt: -------------------------------------------------------------------------------- 1 | [NAMESPACES] 2 | 3 | namespace [CONTROLLERS_NAMESPACE].Controllers 4 | { 5 | /// 6 | [CONTROLLER_REQ_OBJ_SUMMARY] 7 | /// 8 | [Route("[CONTROLLER_ROUTE]")] 9 | [ApiController] 10 | public sealed class [CONTROLLER_NAME] : ControllerBase 11 | { 12 | [FIELDS] 13 | 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | public [CONTROLLER_NAME]( 18 | [CTOR_ARGS] 19 | ) 20 | { 21 | _log = loggerFactory.CreateLogger<[CONTROLLER_NAME]>(); 22 | 23 | [CTOR_BODY] 24 | } 25 | 26 | [ACTIONS] 27 | 28 | 29 | [METHODS] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore.DynamicControllers/Types/DynamicComments.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using APIBlox.NetCore.Extensions; 3 | 4 | namespace APIBlox.AspNetCore.Types 5 | { 6 | /// 7 | /// Class DynamicComments. 8 | /// 9 | public class DynamicComments 10 | { 11 | private const string RemarksTemplate = @" 12 | /// 13 | /// @remarks 14 | /// 15 | "; 16 | 17 | private const string SummaryTemplate = @" 18 | /// 19 | /// @summary 20 | /// 21 | "; 22 | 23 | /// 24 | /// Gets or sets the summary. 25 | /// 26 | /// The summary. 27 | public string Summary { get; set; } 28 | 29 | /// 30 | /// Gets or sets the remarks. 31 | /// 32 | /// The remarks. 33 | public string Remarks { get; set; } 34 | 35 | /// 36 | /// Returns a that represents this instance. 37 | /// 38 | /// A that represents this instance. 39 | public override string ToString() 40 | { 41 | var summary = Summary.IsEmptyNullOrWhiteSpace() 42 | ? null 43 | : SummaryTemplate.Replace("@summary", Summary.Replace(Environment.NewLine, "\n/// ")); 44 | var remarks = Remarks.IsEmptyNullOrWhiteSpace() 45 | ? null 46 | : RemarksTemplate.Replace("@remarks", Remarks.Replace(Environment.NewLine, "\n/// ")); 47 | 48 | return $"{summary}{remarks}"; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/APIBlox.AspNetCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | net5.0 6 | 7 | APIBlox.AspNetCore 8 | 9 | AspNetCore bits. 10 | 11 | APIBlox.AspNetCore 12 | 13 | APIBlox.AspNetCore 14 | 15 | APIBlox.AspNetCore 16 | 17 | latest 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | all 36 | runtime; build; native; contentfiles; analyzers 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/APIBlox.AspNetCore.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True 3 | True 4 | True -------------------------------------------------------------------------------- /APIBlox.AspNetCore/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.AspNetCore 2 | { 3 | /// 4 | /// Class Constants. 5 | /// 6 | public static class Constants 7 | { 8 | /// 9 | /// Class ResponseTypes. 10 | /// 11 | public static class ResponseTypes 12 | { 13 | /// 14 | /// The error response content type 15 | /// 16 | public const string ErrorResponseContentType = "application/problem+json"; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Contracts/IFilteredQuery.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.AspNetCore.Contracts 2 | { 3 | /// 4 | /// Interface IFilteredQuery 5 | /// 6 | public interface IFilteredQuery : IQuery 7 | { 8 | /// 9 | /// Gets or sets the filter. 10 | /// 11 | /// The filter. 12 | string Filter { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Contracts/IOrderedQuery.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.AspNetCore.Contracts 2 | { 3 | /// 4 | /// Interface IOrderedQuery 5 | /// 6 | public interface IOrderedQuery : IQuery 7 | { 8 | /// 9 | /// Gets or sets the order by. 10 | /// 11 | /// The order by. 12 | string OrderBy { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Contracts/IPaginationMetadataBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using APIBlox.AspNetCore.Services; 3 | using Microsoft.AspNetCore.Mvc.Filters; 4 | 5 | namespace APIBlox.AspNetCore.Contracts 6 | { 7 | internal interface IPaginationMetadataBuilder 8 | { 9 | PaginationMetadata Build(int resultCount, ActionExecutingContext context); 10 | 11 | List Routes { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Contracts/IPaginationQuery.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.AspNetCore.Contracts 2 | { 3 | /// 4 | /// 5 | /// Interface IPaginationQuery 6 | /// 7 | public interface IPaginationQuery : IQuery 8 | { 9 | /// 10 | /// Gets or sets the running count. 11 | /// 12 | /// The running count. 13 | int? RunningCount { get; set; } 14 | 15 | /// 16 | /// Gets or sets the skip. 17 | /// 18 | /// The skip. 19 | int? Skip { get; set; } 20 | 21 | /// 22 | /// Gets or sets the top. 23 | /// 24 | /// The top. 25 | int? Top { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Contracts/IProjectedQuery.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.AspNetCore.Contracts 2 | { 3 | /// 4 | /// Interface IProjectedQuery 5 | /// 6 | public interface IProjectedQuery : IQuery 7 | { 8 | /// 9 | /// Gets or sets the select. 10 | /// 11 | /// The select. 12 | string Select { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Contracts/IQuery.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.AspNetCore.Contracts 2 | { 3 | /// 4 | /// Marker Interface IQuery 5 | /// 6 | public interface IQuery 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Contracts/IResource.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.AspNetCore.Contracts 2 | { 3 | /// 4 | /// Marker interface 5 | /// 6 | public interface IResource 7 | { 8 | } 9 | 10 | /// 11 | /// 12 | /// Interface IResource 13 | /// 14 | /// The type of the t id. 15 | /// 16 | public interface IResource : IResource 17 | { 18 | /// 19 | /// Gets or sets the Id. 20 | /// 21 | /// The Id. 22 | TId Id { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Exceptions/HandledRequestException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using APIBlox.AspNetCore.Types; 3 | 4 | namespace APIBlox.AspNetCore.Exceptions 5 | { 6 | /// 7 | /// 8 | /// Class HandledRequestException. 9 | /// 10 | /// 11 | public class HandledRequestException : Exception 12 | { 13 | /// 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | /// The request error object. 18 | public HandledRequestException(RequestErrorObject requestErrorObject) 19 | { 20 | RequestErrorObject = requestErrorObject; 21 | } 22 | 23 | /// 24 | /// Gets the request error object. 25 | /// 26 | /// The request error object. 27 | public RequestErrorObject RequestErrorObject { get; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Extensions/ErrorExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using APIBlox.AspNetCore.Types; 4 | 5 | namespace APIBlox.AspNetCore.Extensions 6 | { 7 | /// 8 | /// Class ErrorExtensions. 9 | /// 10 | [DebuggerStepThrough] 11 | public static class ErrorExtensions 12 | { 13 | internal static DynamicErrorObject ToDynamicDataObject(this Exception ex, bool noThrow) 14 | { 15 | var ret = new DynamicErrorObject("Error Details", ex.Message) 16 | { 17 | NoThrow = noThrow 18 | }; 19 | 20 | dynamic d = ret; 21 | 22 | d.Type = ex.GetType().Name; 23 | 24 | if (ex.InnerException is null) 25 | return ret; 26 | 27 | ret.Title = "Please refer to the error property for additional information."; 28 | ret.Errors.Add(ex.InnerException.ToDynamicDataObject(noThrow)); 29 | 30 | return ret; 31 | } 32 | 33 | /// 34 | /// Builds an from an exception along with all inner exceptions. 35 | /// 36 | /// The ex. 37 | /// DynamicErrorObject. 38 | public static DynamicErrorObject ToDynamicDataObject(this Exception ex) 39 | { 40 | var ret = new DynamicErrorObject("Error Details", ex.Message); 41 | dynamic d = ret; 42 | 43 | d.Type = ex.GetType().Name; 44 | 45 | if (ex.InnerException is null) 46 | return ret; 47 | 48 | ret.Title = "Please refer to the error property for additional information."; 49 | ret.Errors.Add(ex.InnerException.ToDynamicDataObject()); 50 | 51 | return ret; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Filters/Action Filters/ValidateResourceActionFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using APIBlox.AspNetCore.ActionResults; 3 | using Microsoft.AspNetCore.Mvc.Filters; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace APIBlox.AspNetCore.Filters 7 | { 8 | internal class ValidateResourceActionFilter : IAsyncActionFilter 9 | { 10 | private readonly ILogger _log; 11 | 12 | public ValidateResourceActionFilter(ILoggerFactory loggerFactory) 13 | { 14 | _log = loggerFactory.CreateLogger(); 15 | } 16 | 17 | public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) 18 | { 19 | if (context.ModelState.IsValid) 20 | { 21 | _log.LogInformation(() => $"Validation succeeded for {context.Result}"); 22 | 23 | await next().ConfigureAwait(false); 24 | 25 | return; 26 | } 27 | 28 | _log.LogWarning(() => $"Validation failed for {context}, returning new ValidationFailureResult"); 29 | 30 | context.Result = new ValidationFailureResult(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Filters/Exception Filters/OperationCanceledExceptionFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.AspNetCore.Mvc.Filters; 5 | using Microsoft.Extensions.Logging; 6 | 7 | // ReSharper disable once CheckNamespace 8 | namespace APIBlox.AspNetCore 9 | { 10 | internal class OperationCanceledExceptionFilter : IAsyncExceptionFilter 11 | { 12 | private readonly ILogger _log; 13 | 14 | public OperationCanceledExceptionFilter(ILoggerFactory loggerFactory) 15 | { 16 | _log = loggerFactory.CreateLogger(); 17 | } 18 | 19 | public Task OnExceptionAsync(ExceptionContext context) 20 | { 21 | if (context.Exception is not OperationCanceledException) 22 | { 23 | _log.LogInformation(() => $"Skipping execute, exception is of type {context.Exception.GetType()}"); 24 | 25 | return Task.CompletedTask; 26 | } 27 | 28 | _log.LogInformation(() => $"Request {context.HttpContext.Request.Path} was cancelled."); 29 | 30 | context.ExceptionHandled = true; 31 | 32 | // Client Closed Request, this is a non-standard status code used by NGINX 33 | context.Result = new StatusCodeResult(499); 34 | 35 | return Task.CompletedTask; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/ModelBinders/FromQueryWithAlterenateNamesBinderProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using APIBlox.AspNetCore.Attributes; 4 | using Microsoft.AspNetCore.Mvc.ModelBinding; 5 | using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; 6 | using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; 7 | 8 | namespace APIBlox.AspNetCore.ModelBinders 9 | { 10 | internal class FromQueryWithAlternateNamesBinderProvider : IModelBinderProvider 11 | { 12 | public IModelBinder GetBinder(ModelBinderProviderContext context) 13 | { 14 | if (context == null) 15 | throw new ArgumentNullException(nameof(context)); 16 | 17 | return IsIQuery(context) 18 | ? new BinderTypeModelBinder(typeof(FromQueryAlternateNamesBinder)) 19 | : null; 20 | } 21 | 22 | private static bool IsIQuery(ModelBinderProviderContext c) 23 | { 24 | var attrs = ((DefaultModelMetadata)c.Metadata).Attributes.Attributes; 25 | 26 | return attrs is not null && attrs.Any(pa => pa.GetType() == typeof(FromQueryWithAlternateNamesAttribute)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Services/PaginationMetadata.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.AspNetCore.Services 2 | { 3 | /// 4 | /// Class PaginationMetadata. 5 | /// 6 | public class PaginationMetadata 7 | { 8 | /// 9 | /// Gets or sets the count for this result. 10 | /// 11 | /// The count. 12 | public long? ResultCount { get; set; } 13 | 14 | /// 15 | /// Gets or sets the next. 16 | /// 17 | /// The next. 18 | public string Next { get; set; } 19 | 20 | /// 21 | /// Gets or sets the previous. 22 | /// 23 | /// The previous. 24 | public string Previous { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/Errors/ServerErrorObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using APIBlox.NetCore.Extensions; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace APIBlox.AspNetCore.Types 8 | { 9 | internal class ServerErrorObject : RequestErrorObject 10 | { 11 | public ServerErrorObject(string title, string detail, int status, string instance, string referenceId) 12 | : base(title, detail, status, instance) 13 | { 14 | ReferenceId = referenceId; 15 | } 16 | 17 | private string ReferenceId { get; } 18 | 19 | public override IEnumerable GetDynamicMemberNames() 20 | { 21 | if (ReferenceId.IsEmptyNullOrWhiteSpace()) 22 | { 23 | var msg = $"Although {GetType().Name}.{nameof(ReferenceId)} " + 24 | "is not required by RFC7807, we still want it!"; 25 | 26 | if (NoThrow) 27 | Logger.LogWarning(() => msg); 28 | else 29 | throw new ArgumentException(msg, nameof(ReferenceId)); 30 | } 31 | else 32 | { 33 | Properties.TryAdd("ReferenceId", ReferenceId); 34 | } 35 | 36 | if (Errors is not null && Errors.Any()) 37 | Properties.TryAdd("Errors", Errors); 38 | 39 | return base.GetDynamicMemberNames(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/FilteredOrderedQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class FilteredOrderedQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates In addition to FilteredQuery, OrderBy = $OrderBy, SortBy, $SortBy, Sort, $Sort 16 | /// 17 | /// 18 | public class FilteredOrderedQuery : FilteredQuery, IOrderedQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public FilteredOrderedQuery() 24 | { 25 | Map.TryAdd("OrderBy", new[] { "$OrderBy", "SortBy", "$SortBy", "Sort", "$Sort" }); 26 | } 27 | 28 | /// 29 | /// Sets the order by. Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("orderBy", "$OrderBy", "SortBy", "$SortBy", "Sort", "$Sort" )] 32 | public string OrderBy { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!OrderBy.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("orderBy", OrderBy); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/FilteredPaginationQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class FilteredPaginationQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates In addition to PaginationQuery, Filter = $Where, Where, $Filter 16 | /// 17 | /// 18 | public class FilteredPaginationQuery : PaginationQuery, IFilteredQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public FilteredPaginationQuery() 24 | { 25 | Map.TryAdd("Filter", new[] { "$Where", "Where", "$Filter" }); 26 | } 27 | 28 | /// 29 | /// Sets the filter (where). Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("filter", "$Where", "Where", "$Filter")] 32 | public string Filter { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!Filter.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("filter", Filter); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/FilteredProjectedOrderedQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class FilteredProjectedOrderedQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates In addition to FilteredQuery, Select = $Select, Project, $Project 16 | /// 17 | /// 18 | public class FilteredProjectedOrderedQuery : FilteredQuery, IProjectedQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public FilteredProjectedOrderedQuery() 24 | { 25 | Map.TryAdd("Select", new[] {"$Select", "Project", "$Project"}); 26 | } 27 | 28 | /// 29 | /// Sets the select (projection). Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("select", "$Select", "Project", "$Project" )] 32 | public string Select { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!Select.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("select", Select); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/FilteredProjectedPaginationQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class FilteredProjectedPaginationQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates In addition to FilteredPaginationQuery, Select = $Select, Project, $Project 16 | /// 17 | /// 18 | public class FilteredProjectedPaginationQuery : FilteredPaginationQuery, IProjectedQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public FilteredProjectedPaginationQuery() 24 | { 25 | Map.TryAdd("Select", new[] { "$Select", "Project", "$Project" }); 26 | } 27 | 28 | /// 29 | /// Sets the select (projection). Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("select", "$Select", "Project", "$Project")] 32 | public string Select { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!Select.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("select", Select); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/FilteredProjectedQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class FilteredProjectedQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates In addition to FilteredQuery, Select = $Select, Project, $Project 16 | /// 17 | /// 18 | public class FilteredProjectedQuery : FilteredQuery, IProjectedQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public FilteredProjectedQuery() 24 | { 25 | Map.TryAdd("Select", new[] { "$Select", "Project", "$Project" }); 26 | } 27 | 28 | /// 29 | /// Sets the select (projection). Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("select", "$Select", "Project", "$Project")] 32 | public string Select { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!Select.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("select", Select); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/FilteredQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class FilteredQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates to Filter = $Where, Where, $Filter 16 | /// 17 | /// 18 | public class FilteredQuery : Query, IFilteredQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public FilteredQuery() 24 | { 25 | Map.TryAdd("Filter", new[] { "$Where", "Where", "$Filter" }); 26 | } 27 | 28 | /// 29 | /// Sets the filter (where). Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("filter", "$Where", "$WHERE", "$whERE", "$Where", "Where", "$Filter")] 32 | public string Filter { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!Filter.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("filter", Filter); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/HandlerResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using APIBlox.AspNetCore.Enums; 3 | 4 | namespace APIBlox.AspNetCore.Types 5 | { 6 | /// 7 | /// Class HandlerResponse. 8 | /// 9 | [DebuggerStepThrough] 10 | public sealed class HandlerResponse 11 | { 12 | /// 13 | /// Gets the , I can be set 14 | /// using 15 | /// 16 | /// The error. 17 | public RequestErrorObject Error { get; internal set; } 18 | 19 | /// 20 | /// Gets a value indicating whether this instance has errors. 21 | /// 22 | /// 23 | /// true if the is not null OR a Status that is NOT 24 | /// ; 25 | /// otherwise,false. 26 | /// 27 | public bool HasErrors => Error is not null || Status != CommonStatusCodes.Status200Ok; 28 | 29 | /// 30 | /// Gets or sets the result. 31 | /// 32 | /// The result. 33 | public dynamic Result { get; set; } 34 | 35 | /// 36 | /// Gets or sets the status. 37 | /// 38 | /// The status. 39 | public CommonStatusCodes Status { get; set; } = CommonStatusCodes.Status200Ok; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/OrderedPaginationQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class OrderedPaginationQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates In addition to PaginationQuery, OrderBy = $OrderBy, SortBy, $SortBy, Sort, $Sort 16 | /// 17 | /// 18 | public class OrderedPaginationQuery : PaginationQuery, IOrderedQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public OrderedPaginationQuery() 24 | { 25 | Map.TryAdd("OrderBy", new[] { "$OrderBy", "SortBy", "$SortBy", "Sort", "$Sort" }); 26 | } 27 | 28 | /// 29 | /// Sets the order by. Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("orderBy", "$OrderBy", "SortBy", "$SortBy", "Sort", "$Sort")] 32 | public string OrderBy { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!OrderBy.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("orderBy", OrderBy); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/OrderedQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class OrderedQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates to OrderBy = $OrderBy, SortBy, $SortBy, Sort, $Sort 16 | /// 17 | /// 18 | public class OrderedQuery : Query, IOrderedQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public OrderedQuery() 24 | { 25 | Map.TryAdd("OrderBy", new[] { "$OrderBy", "SortBy", "$SortBy", "Sort", "$Sort" }); 26 | } 27 | 28 | /// 29 | /// Sets the order by. Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("orderBy", "$OrderBy", "SortBy", "$SortBy", "Sort", "$Sort")] 32 | public string OrderBy { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!OrderBy.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("orderBy", OrderBy); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/ProjectedOrderedPaginationQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class ProjectedOrderedPaginationQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates In addition to ProjectedPaginationQuery, OrderBy = $OrderBy, SortBy, $SortBy, Sort, $Sort 16 | /// 17 | /// 18 | public class ProjectedOrderedPaginationQuery : ProjectedPaginationQuery, IOrderedQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public ProjectedOrderedPaginationQuery() 24 | { 25 | Map.TryAdd("OrderBy", new[] { "$OrderBy", "SortBy", "$SortBy", "Sort", "$Sort" }); 26 | } 27 | 28 | /// 29 | /// Sets the order by. Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("orderBy", "$OrderBy", "SortBy", "$SortBy", "Sort", "$Sort")] 32 | public string OrderBy { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!OrderBy.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("orderBy", OrderBy); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/ProjectedOrderedQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class ProjectedOrderedQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates In addition to ProjectedQuery, OrderBy = $OrderBy, SortBy, $SortBy, Sort, $Sort 16 | /// 17 | /// 18 | public class ProjectedOrderedQuery : ProjectedQuery, IOrderedQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public ProjectedOrderedQuery() 24 | { 25 | Map.TryAdd("OrderBy", new[] { "$OrderBy", "SortBy", "$SortBy", "Sort", "$Sort" }); 26 | } 27 | 28 | /// 29 | /// Sets the order by. Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("orderBy", "$OrderBy", "SortBy", "$SortBy", "Sort", "$Sort")] 32 | public string OrderBy { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!OrderBy.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("orderBy", OrderBy); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/ProjectedPaginationQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class ProjectedPaginationQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates In addition to ProjectedQuery, Select = $Select, Project, $Project 16 | /// 17 | /// 18 | public class ProjectedPaginationQuery : PaginationQuery, IProjectedQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public ProjectedPaginationQuery() 24 | { 25 | Map.TryAdd("Select", new[] { "$Select", "Project", "$Project" }); 26 | } 27 | 28 | /// 29 | /// Sets the select (projection). Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("select", "$Select", "Project", "$Project")] 32 | public string Select { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!Select.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("select", Select); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.AspNetCore/Types/ProjectedQuery.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Attributes; 2 | using APIBlox.AspNetCore.Contracts; 3 | using APIBlox.NetCore.Extensions; 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | 6 | namespace APIBlox.AspNetCore.Types 7 | { 8 | /// 9 | /// Class ProjectedQuery. 10 | /// 11 | /// Be sure to also call the AddFromQueryWithAlternateNamesBinder Mvc/MvcCore 12 | /// builder extension method to allow alternate names to be used. 13 | /// 14 | /// 15 | /// Alternates to Select = $Select, Project, $Project 16 | /// 17 | /// 18 | public class ProjectedQuery : Query, IProjectedQuery 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public ProjectedQuery() 24 | { 25 | Map.TryAdd("Select", new[] { "$Select", "Project", "$Project" }); 26 | } 27 | 28 | /// 29 | /// Sets the select (projection). Usage is determined by the API itself, please seek external documentation. 30 | /// 31 | [FromQueryWithAlternateNames("select", "$Select", "Project", "$Project")] 32 | public string Select { get; set; } 33 | 34 | /// 35 | /// Builds the query. 36 | /// 37 | /// QueryBuilder. 38 | protected override QueryBuilder BuildQuery() 39 | { 40 | var qb = base.BuildQuery(); 41 | 42 | if (!Select.IsEmptyNullOrWhiteSpace()) 43 | qb.Add("select", Select); 44 | 45 | return qb; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /APIBlox.NetCore.CommandsAndQueries/APIBlox.NetCore.CommandsAndQueries.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | net5.0 6 | 7 | APIBlox.NetCore 8 | 9 | APIBlox.NetCore.CommandsAndQueries 10 | 11 | Simple CQRS implementation that utilizes the decorator pattern. 12 | 13 | APIBlox.NetCore.CommandsAndQueries 14 | 15 | APIBlox.NetCore.CommandsAndQueries 16 | 17 | latest 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | all 28 | runtime; build; native; contentfiles; analyzers 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /APIBlox.NetCore.CommandsAndQueries/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.NetCore.CommandsAndQueries/Contracts/IQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace APIBlox.NetCore.Contracts 5 | { 6 | /// 7 | /// Interface IQueryHandler, used when your QUERY requires input parameters, IE: GetSomething(requirements) 8 | /// 9 | /// The type of the query. 10 | /// The type of the result. 11 | public interface IQueryHandler 12 | { 13 | /// 14 | /// Handles the specified query. 15 | /// 16 | /// The query. 17 | /// The cancellation token. 18 | /// Task{TResult}. 19 | Task HandleAsync(TRequestQuery query, CancellationToken cancellationToken); 20 | } 21 | 22 | /// 23 | /// Interface IQueryHandler, used when your QUERY does not require input parameters, IE: GetAll() 24 | /// 25 | /// The type of the result. 26 | public interface IQueryHandler 27 | { 28 | /// 29 | /// Handles the specified cancellation token. 30 | /// 31 | /// The cancellation token. 32 | /// Task{TResult}. 33 | Task HandleAsync(CancellationToken cancellationToken); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /APIBlox.NetCore.Common/APIBlox.NetCore.Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | net5.0 6 | 7 | APIBlox.NetCore 8 | 9 | Cross-Cutting.NetCore bits. 10 | 11 | APIBlox.NetCore.Common 12 | 13 | APIBlox.NetCore.Common 14 | 15 | APIBlox.NetCore.Common 16 | 17 | latest 18 | 19 | 20 | 21 | 22 | all 23 | runtime; build; native; contentfiles; analyzers 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /APIBlox.NetCore.Common/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.NetCore.Common/Extensions/EnumExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace APIBlox.NetCore.Extensions 5 | { 6 | /// 7 | /// Class EnumExtensions. 8 | /// 9 | [DebuggerStepThrough] 10 | public static class EnumExtensions 11 | { 12 | /// 13 | /// Gets the type of the attribute of. 14 | /// 15 | /// 16 | /// The enum value. 17 | /// T. 18 | public static T GetAttributeOfType(this Enum enumVal) 19 | where T : Attribute 20 | { 21 | var type = enumVal.GetType(); 22 | var memInfo = type.GetMember(enumVal.ToString()); 23 | var attributes = memInfo[0].GetCustomAttributes(typeof(T), false); 24 | 25 | return attributes.Length > 0 26 | ? (T) attributes[0] 27 | : null; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /APIBlox.NetCore.Common/Extensions/ExpressionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace APIBlox.NetCore.Extensions 4 | { 5 | /// 6 | /// Class ExpressionExtensions. 7 | /// 8 | public static class ExpressionExtensions 9 | { 10 | /// 11 | /// Simplified AndAlso expression generation. 12 | /// 13 | /// The type of the t delegate. 14 | /// The left. 15 | /// The right. 16 | /// Expression<TDelegate>. 17 | public static Expression AndAlso(this Expression left, Expression right) 18 | { 19 | return Expression.Lambda(Expression.AndAlso(left, right), left.Parameters); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /APIBlox.NetCore.Common/Extensions/StructExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.NetCore.Extensions 2 | { 3 | /// 4 | /// Class NumberExtensions. 5 | /// 6 | public static class StructExtensions 7 | { 8 | /// 9 | /// Determines whether [is null or zero] [the specified value]. 10 | /// 11 | /// 12 | /// The value. 13 | /// true if [is null or zero] [the specified value]; otherwise, false. 14 | public static bool IsNullOrZero(this T? value) 15 | where T : struct 16 | { 17 | return !value.HasValue || Equals(value, default(T)); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /APIBlox.NetCore.Common/Types/JsonBits/CamelCaseSettings.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Serialization; 3 | 4 | namespace APIBlox.NetCore.Types.JsonBits 5 | { 6 | /// 7 | /// 8 | /// Class CamelCaseSettings. 9 | /// Implements the 10 | /// 11 | public class CamelCaseSettings : JsonSerializerSettings 12 | { 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | public CamelCaseSettings() 17 | { 18 | ContractResolver = new CamelCasePropertyNamesContractResolver(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /APIBlox.NetCore.DomainEvents/APIBlox.NetCore.DomainEvents.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | 6 | APIBlox.NetCore 7 | 8 | Simple domain events. 9 | 10 | APIBlox.NetCore.DomainEvents 11 | 12 | APIBlox.NetCore.DomainEvents 13 | 14 | APIBlox.NetCore.DomainEvents 15 | 16 | latest 17 | 18 | 19 | 20 | 21 | 22 | all 23 | runtime; build; native; contentfiles; analyzers 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /APIBlox.NetCore.DomainEvents/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.NetCore.DomainEvents/Contracts/IDomainEvent.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.NetCore.Contracts 2 | { 3 | /// 4 | /// Marker Interface 5 | /// 6 | /// Important characteristics of events is that since an event is something that happened in the past, 7 | /// it should not change. Therefore it must be an immutable class. It's name should also be of the past tense. 8 | /// 9 | /// 10 | public interface IDomainEvent 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /APIBlox.NetCore.DomainEvents/Contracts/IDomainEventHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace APIBlox.NetCore.Contracts 5 | { 6 | /// 7 | /// Interface IDomainEventHandler 8 | /// 9 | /// The type of the t domain event. 10 | public interface IDomainEventHandler 11 | where TDomainEvent : IDomainEvent 12 | { 13 | /// 14 | /// Handles the event asynchronous. 15 | /// 16 | /// The domain event. 17 | /// The cancellation token. 18 | /// Task. 19 | Task HandleEventAsync(TDomainEvent domainEvent, CancellationToken cancellationToken = default); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /APIBlox.NetCore.DomainEvents/Contracts/IDomainEventsDispatcher.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace APIBlox.NetCore.Contracts 4 | { 5 | /// 6 | /// Interface IDomainEventsDispatcher 7 | /// 8 | public interface IDomainEventsDispatcher 9 | { 10 | /// 11 | /// Publishes all events asynchronously. 12 | /// 13 | /// The type of the t domain event. 14 | /// The events. 15 | /// Task. 16 | Task PublishEventsAsync(params TDomainEvent[] events) 17 | where TDomainEvent : class, IDomainEvent; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /APIBlox.NetCore.DomainEvents/Contracts/IQueuedDomainEventsDispatcher.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace APIBlox.NetCore.Contracts 4 | { 5 | /// 6 | /// Interface IQueuedDomainEventsDispatcher 7 | /// 8 | public interface IQueuedDomainEventsDispatcher 9 | { 10 | /// 11 | /// Adds an event to the queue. 12 | /// 13 | /// The type of the t domain event. 14 | /// The domain event. 15 | /// Task. 16 | void AddEvent(TDomainEvent domainEvent) 17 | where TDomainEvent : class, IDomainEvent; 18 | 19 | /// 20 | /// Publishes all events, either one at a time or using . 21 | /// 22 | /// if set to true [when all]. 23 | /// Task. 24 | Task PublishEventsAsync(bool whenAll = true); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /APIBlox.NetCore.DomainEvents/Dispatchers/DispatcherBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using APIBlox.NetCore.Contracts; 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | // ReSharper disable once CheckNamespace 9 | namespace APIBlox.NetCore 10 | { 11 | internal abstract class DispatcherBase 12 | { 13 | private readonly IServiceProvider _serviceProvider; 14 | 15 | protected DispatcherBase( 16 | IServiceProvider serviceProvider 17 | ) 18 | { 19 | _serviceProvider = serviceProvider; 20 | } 21 | 22 | protected Task ExecuteHandlers(IDomainEvent de, Action callback) 23 | { 24 | // Find the correct handlers, that has a generic arg that matches the event type. 25 | // Create a wrapper to prevent from invoking magic string methods. 26 | var deType = de.GetType(); 27 | var handlerType = typeof(IDomainEventHandler<>).MakeGenericType(deType); 28 | var handlerWrapperType = typeof(DomainEventHandlerWrapper<>).MakeGenericType(deType); 29 | var handlers = _serviceProvider.GetServices(handlerType).ToList(); 30 | 31 | var wrapped = handlers.Select(h => 32 | (DomainEventHandlerBase) Activator.CreateInstance(handlerWrapperType, h) 33 | ); 34 | 35 | var tasks = new List(); 36 | 37 | foreach (var dh in wrapped) 38 | { 39 | var t = dh?.HandleEventAsync(de); 40 | tasks.Add(t); 41 | callback(t); 42 | } 43 | 44 | Task.WaitAll(tasks.ToArray()); 45 | 46 | return Task.CompletedTask; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /APIBlox.NetCore.DomainEvents/Domain Events Notes.txt: -------------------------------------------------------------------------------- 1 | From: https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/domain-events-design-implementation 2 | 3 | It is important to understand that this event-based communication is not implemented directly within the aggregates; you need to implement 4 | domain event handlers. Handling the domain events is an application concern. The domain model layer should only focus on the domain logic—things 5 | that a domain expert would understand, not application infrastructure like handlers and side-effect persistence actions using repositories. 6 | Therefore, the application layer level is where you should have domain event handlers triggering actions when a domain event is raised. 7 | 8 | 9 | I don't get it, accepted practice is to put events (creating) in entities. What if your application isnt using 10 | events for whatever reason? now theres functionality that is unnecessary. -------------------------------------------------------------------------------- /APIBlox.NetCore.DomainEvents/Handlers/DomainEventHandlerBase.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using APIBlox.NetCore.Contracts; 4 | 5 | // ReSharper disable once CheckNamespace 6 | namespace APIBlox.NetCore 7 | { 8 | internal abstract class DomainEventHandlerBase 9 | { 10 | /// 11 | /// Handles the event asynchronous. 12 | /// 13 | /// The domain event. 14 | /// The cancellation token. 15 | /// Task. 16 | public abstract Task HandleEventAsync(IDomainEvent domainEvent, CancellationToken cancellationToken = default); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /APIBlox.NetCore.DomainEvents/Handlers/DomainEventHandlerWrapper.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using APIBlox.NetCore.Contracts; 4 | 5 | // ReSharper disable once CheckNamespace 6 | namespace APIBlox.NetCore 7 | { 8 | internal class DomainEventHandlerWrapper : DomainEventHandlerBase 9 | where TDomainEvent : IDomainEvent 10 | { 11 | private readonly IDomainEventHandler _handler; 12 | 13 | public DomainEventHandlerWrapper(IDomainEventHandler handler) 14 | { 15 | _handler = handler; 16 | } 17 | 18 | public override Task HandleEventAsync(IDomainEvent domainEvent, CancellationToken cancellationToken = default) 19 | { 20 | return _handler.HandleEventAsync((TDomainEvent) domainEvent, cancellationToken); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.CosmosDb/APIBlox.NetCore.EventStore.CosmosDb.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | 6 | APIBlox.NetCore 7 | 8 | CosmosDB backing for APIBlox.NetCore.EventStore. 9 | 10 | APIBlox.NetCore.EventStore.CosmosDb 11 | 12 | APIBlox.NetCore.EventStore.CosmosDb 13 | 14 | APIBlox.NetCore.EventStore.CosmosDb 15 | 16 | latest 17 | 18 | 19 | 20 | 21 | 22 | all 23 | runtime; build; native; contentfiles; analyzers 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | PreserveNewest 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.CosmosDb/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.CosmosDb/DbCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using APIBlox.NetCore.Options; 3 | 4 | namespace APIBlox.NetCore 5 | { 6 | internal class DbCollection 7 | { 8 | public int DatabaseThroughput { get; set; } 9 | 10 | public string DatabaseId { get; set; } 11 | 12 | public string CollectionId { get; set; } 13 | 14 | public Uri DocumentCollectionUri { get; set; } 15 | 16 | public CosmosDbCollectionProperties ColProps { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.CosmosDb/Options/CosmosDbCollectionProperties.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.Azure.Documents; 3 | 4 | namespace APIBlox.NetCore.Options 5 | { 6 | /// 7 | /// Class CollectionProperties. 8 | /// 9 | public class CosmosDbCollectionProperties 10 | { 11 | /// 12 | /// Gets or sets the models. 13 | /// 14 | public List Models { get; set; } 15 | 16 | /// 17 | /// Gets or sets the unique key policy. 18 | /// 19 | public UniqueKeyPolicy UniqueKeyPolicy { get; set; } = new(); 20 | 21 | /// 22 | /// Gets or sets the offer throughput. 23 | /// 24 | public int OfferThroughput { get; set; } = -1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.CosmosDb/Options/CosmosDbOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.Azure.Documents.Client; 3 | 4 | namespace APIBlox.NetCore.Options 5 | { 6 | /// 7 | /// Class CosmosDbOptions. 8 | /// 9 | public class CosmosDbOptions 10 | { 11 | /// 12 | /// Gets or sets the endpoint. 13 | /// 14 | public string Endpoint { get; set; } 15 | 16 | /// 17 | /// Gets or sets the key. 18 | /// 19 | public string Key { get; set; } 20 | 21 | /// 22 | /// Gets or sets the database identifier. 23 | /// 24 | public string DatabaseId { get; set; } 25 | 26 | /// 27 | /// Gets or sets the connection policy. 28 | /// 29 | public ConnectionPolicy ConnectionPolicy { get; set; } 30 | 31 | /// 32 | /// Gets or sets the offer throughput. 33 | /// 34 | public int OfferThroughput { get; set; } = 400; 35 | 36 | /// 37 | /// Gets or sets the collection properties. 38 | /// 39 | public Dictionary CollectionProperties { get; set; } = 40 | new Dictionary(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.EfCore/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.EfCore/DocEx.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Documents; 2 | 3 | namespace APIBlox.NetCore 4 | { 5 | internal class DocEx : EventStoreDocument 6 | { 7 | public new string Data { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.EfCore/EventStoreDocumentMap.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace APIBlox.NetCore 5 | { 6 | internal class EventStoreDocumentMap 7 | { 8 | private readonly EntityTypeBuilder _builder; 9 | 10 | public EventStoreDocumentMap(EntityTypeBuilder builder) 11 | { 12 | _builder = builder; 13 | } 14 | 15 | public void Map() 16 | { 17 | _builder.ToTable("EventStoreDocuments"); 18 | 19 | _builder.HasKey(p => p.Id); 20 | 21 | _builder.HasIndex(p => p.StreamId); 22 | 23 | //_builder.Ignore(p => p.Data); 24 | _builder.Property(p => p.Data); 25 | 26 | _builder.Property(p => p.DataType).HasMaxLength(1024); 27 | _builder.Property(p => p.DocumentType).HasMaxLength(255); 28 | 29 | // _builder.Property(p => p.SortOrder); 30 | _builder.Property(p => p.StreamId).IsRequired().HasMaxLength(255); 31 | _builder.Property(p => p.TimeStamp).IsRequired(); 32 | _builder.Property(p => p.Version).IsRequired(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.EfCore/Migrations/EventStoreDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | 7 | namespace APIBlox.NetCore.Migrations 8 | { 9 | [DbContext(typeof(EventStoreDbContext))] 10 | internal class EventStoreDbContextModelSnapshot : ModelSnapshot 11 | { 12 | protected override void BuildModel(ModelBuilder modelBuilder) 13 | { 14 | #pragma warning disable 612, 618 15 | modelBuilder 16 | .HasAnnotation("ProductVersion", "2.2.0-rtm-35687") 17 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 18 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 19 | 20 | modelBuilder.Entity("APIBlox.NetCore.Documents.EventStoreDocument", 21 | b => 22 | { 23 | b.Property("Id").ValueGeneratedOnAdd(); 24 | b.Property("DataEx"); 25 | b.Property("DataType").HasMaxLength(1024); 26 | b.Property("DocumentType").HasMaxLength(255); 27 | b.Property("StreamId").IsRequired().HasMaxLength(255); 28 | b.Property("TimeStamp"); 29 | b.Property("Version"); 30 | b.HasKey("Id"); 31 | b.HasIndex("StreamId"); 32 | b.ToTable("EventStoreDocuments"); 33 | } 34 | ); 35 | #pragma warning restore 612, 618 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.EfCore/Migrations/InitialCreate.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using APIBlox.NetCore; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | 8 | namespace APIBlox.NetCore.Migrations 9 | { 10 | [DbContext(typeof(EventStoreDbContext))] 11 | [Migration("InitialCreate")] 12 | partial class InitialCreate 13 | { 14 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 15 | { 16 | #pragma warning disable 612, 618 17 | modelBuilder 18 | .HasAnnotation("ProductVersion", "2.2.0-rtm-35687") 19 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 20 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 21 | 22 | modelBuilder.Entity("APIBlox.NetCore.Documents.EventStoreDocument", b => 23 | { 24 | b.Property("Id").ValueGeneratedOnAdd(); 25 | b.Property("Data"); 26 | b.Property("DataType").HasMaxLength(1024); 27 | b.Property("DocumentType").HasMaxLength(255); 28 | b.Property("StreamId").IsRequired().HasMaxLength(255); 29 | b.Property("TimeStamp"); 30 | b.Property("Version"); 31 | b.HasKey("Id"); 32 | b.HasIndex("StreamId"); 33 | b.ToTable("EventStoreDocuments"); 34 | }); 35 | #pragma warning restore 612, 618 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.EfCore/Migrations/InitialCreate.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | namespace APIBlox.NetCore.Migrations 4 | { 5 | internal partial class InitialCreate : Migration 6 | { 7 | protected override void Down(MigrationBuilder migrationBuilder) 8 | { 9 | migrationBuilder.DropTable( 10 | "EventStoreDocuments" 11 | ); 12 | } 13 | 14 | protected override void Up(MigrationBuilder migrationBuilder) 15 | { 16 | migrationBuilder.CreateTable( 17 | "EventStoreDocuments", 18 | table => new 19 | { 20 | Id = table.Column(), 21 | StreamId = table.Column(maxLength: 255), 22 | DocumentType = table.Column(maxLength: 255), 23 | DataType = table.Column(maxLength: 1024, nullable: true), 24 | DataEx = table.Column(nullable: true), 25 | Version = table.Column(), 26 | TimeStamp = table.Column() 27 | }, 28 | constraints: table => { table.PrimaryKey("PK_EventStoreDocuments", x => x.Id); } 29 | ); 30 | 31 | migrationBuilder.CreateIndex( 32 | "IX_EventStoreDocuments_StreamId", 33 | "EventStoreDocuments", 34 | "StreamId" 35 | ); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.EfCore/Options/EfCoreSqlOptions.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.NetCore.Options 2 | { 3 | /// 4 | /// Class EfCoreSqlOptions. 5 | /// 6 | public class EfCoreSqlOptions 7 | { 8 | /// 9 | /// Gets or sets the CNN string. 10 | /// 11 | /// The CNN string. 12 | public string CnnString { get; set; } 13 | 14 | /// 15 | /// Gets or sets a value indicating whether [enable detailed errors]. 16 | /// 17 | /// true if [enable detailed errors]; otherwise, false. 18 | public bool EnableDetailedErrors { get; set; } 19 | 20 | /// 21 | /// Gets or sets a value indicating whether [enable sensitive data logging]. 22 | /// 23 | /// true if [enable sensitive data logging]; otherwise, false. 24 | public bool EnableSensitiveDataLogging { get; set; } 25 | 26 | /// 27 | /// Gets or sets a value indicating whether [configure warnings]. 28 | /// 29 | /// true if [configure warnings]; otherwise, false. 30 | public bool ConfigureWarnings { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.EfCore/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "EfCoreSqlOptions": { 3 | "CnnString": "Server=.\\sql2017;Database=EventStoreEfCore;Trusted_Connection=True;", 4 | "EnableDetailedErrors": true, 5 | "EnableSensitiveDataLogging": true, 6 | "ConfigureWarnings": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.MongoDb/APIBlox.NetCore.EventStore.MongoDb.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | 6 | APIBlox.NetCore 7 | 8 | MongoDB backing for APIBlox.NetCore.EventStore. 9 | 10 | APIBlox.NetCore.EventStore.MongoDb 11 | 12 | APIBlox.NetCore.EventStore.MongoDb 13 | 14 | APIBlox.NetCore.EventStore.MongoDb 15 | 16 | latest 17 | 18 | 19 | 20 | 21 | 22 | all 23 | runtime; build; native; contentfiles; analyzers 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.MongoDb/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.MongoDb/Options/MongoDbCollectionProperties.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.NetCore.Options 2 | { 3 | /// 4 | /// Class MongoDbCollectionProperties. 5 | /// 6 | public class MongoDbCollectionProperties 7 | { 8 | /// 9 | /// Gets or sets the indexes. 10 | /// 11 | /// The indexes. 12 | public string[] Indexes { get; set; } = new string[0]; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.MongoDb/Options/MongoDbOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace APIBlox.NetCore.Options 4 | { 5 | /// 6 | /// Class MongoDbOptions. 7 | /// 8 | public class MongoDbOptions 9 | { 10 | /// 11 | /// Gets or sets the connection string. 12 | /// 13 | /// The connection string. 14 | public string CnnString { get; set; } 15 | 16 | /// 17 | /// Gets or sets the database identifier. 18 | /// 19 | /// The database identifier. 20 | public string DatabaseId { get; set; } 21 | 22 | /// 23 | /// Gets or sets the collection properties. 24 | /// 25 | /// The collection properties. 26 | public Dictionary CollectionProperties { get; set; } = 27 | new Dictionary(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.RavenDb/APIBlox.NetCore.EventStore.RavenDb.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | 6 | APIBlox.NetCore 7 | 8 | RavenDb backing for APIBlox.NetCore.EventStore. 9 | 10 | APIBlox.NetCore.EventStore.RavenDb 11 | 12 | APIBlox.NetCore.EventStore.RavenDb 13 | 14 | APIBlox.NetCore.EventStore.RavenDb 15 | 16 | latest 17 | 18 | 19 | 20 | 21 | 22 | all 23 | runtime; build; native; contentfiles; analyzers 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.RavenDb/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.RavenDb/Options/RavenDbCollectionProperties.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.NetCore.Options 2 | { 3 | /// 4 | /// Class RavenDbCollectionProperties. 5 | /// 6 | public class RavenDbCollectionProperties 7 | { 8 | /// 9 | /// Gets or sets the indexes. 10 | /// 11 | /// The indexes. 12 | public string[] Indexes { get; set; } = new string[0]; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore.RavenDb/Options/RavenDbOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace APIBlox.NetCore.Options 4 | { 5 | /// 6 | /// Class RavenDbOptions. 7 | /// 8 | public class RavenDbOptions 9 | { 10 | /// 11 | /// Gets or sets the database identifier. 12 | /// 13 | /// The database identifier. 14 | public string DatabaseId { get; set; } 15 | 16 | /// 17 | /// Gets or sets the collection properties. 18 | /// 19 | /// The collection properties. 20 | public Dictionary CollectionProperties { get; set; } = 21 | new Dictionary(); 22 | 23 | /// 24 | /// Gets or sets the urls. 25 | /// 26 | /// The urls. 27 | public string[] Urls { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/APIBlox.NetCore.EventStore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | 6 | APIBlox.NetCore 7 | 8 | Simple data backing agnostic event store. 9 | 10 | APIBlox.NetCore.EventStore 11 | 12 | APIBlox.NetCore.EventStore 13 | 14 | APIBlox.NetCore.EventStore 15 | 16 | latest 17 | 18 | 19 | 20 | 21 | 22 | all 23 | runtime; build; native; contentfiles; analyzers 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/Contracts/IEventStoreJsonSerializerSettings.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace APIBlox.NetCore.Contracts 7 | { 8 | /// 9 | /// Marker Interface 10 | /// 11 | public interface IEventStoreJsonSerializerSettings 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/Documents/DocumentTypes.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.NetCore.Documents 2 | { 3 | /// 4 | /// Enum DocumentType 5 | /// 6 | public enum DocumentType 7 | { 8 | /// 9 | /// The root 10 | /// 11 | Root = 1, 12 | 13 | /// 14 | /// The event 15 | /// 16 | Event, 17 | 18 | /// 19 | /// The snapshot 20 | /// 21 | Snapshot 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/Documents/EventDocument.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.NetCore.Documents 2 | { 3 | internal class EventDocument : EventStoreDocument 4 | { 5 | public override string Id => $"{StreamId}-{Version}"; 6 | 7 | public override DocumentType DocumentType => DocumentType.Event; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/Documents/RootDocument.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.NetCore.Documents 2 | { 3 | internal class RootDocument : EventStoreDocument 4 | { 5 | public override string Id => StreamId; 6 | 7 | public override DocumentType DocumentType => DocumentType.Root; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/Documents/SnapshotDocument.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.NetCore.Documents 2 | { 3 | internal class SnapshotDocument : EventStoreDocument 4 | { 5 | public override string Id => $"{StreamId}-{Version}-S"; 6 | 7 | public override DocumentType DocumentType => DocumentType.Snapshot; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/EventSourcedJsonSerializerSettings.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Contracts; 2 | using APIBlox.NetCore.Types.JsonBits; 3 | using Newtonsoft.Json; 4 | using Newtonsoft.Json.Serialization; 5 | 6 | namespace APIBlox.NetCore 7 | { 8 | internal class EventSourcedJsonSerializerSettings : JsonSerializerSettings, IEventStoreJsonSerializerSettings 9 | { 10 | public EventSourcedJsonSerializerSettings(IContractResolver contractResolver = null) 11 | { 12 | ContractResolver = contractResolver ?? new PopulateNonPublicSettersContractResolver(); 13 | } 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/Exceptions/EventStoreAccessException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace APIBlox.NetCore.Exceptions 4 | { 5 | /// 6 | /// Class EventStoreAccessException. 7 | /// Implements the 8 | /// 9 | public class EventStoreAccessException : Exception 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The message that describes the error. 15 | public EventStoreAccessException(string message) 16 | : base(message) 17 | { 18 | } 19 | 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | /// The error message that explains the reason for the exception. 24 | /// 25 | /// The exception that is the cause of the current exception, or a null reference ( 26 | /// in Visual Basic) if no inner exception is specified. 27 | /// 28 | public EventStoreAccessException(string message, Exception innerException) 29 | : base(message, innerException) 30 | { 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/Exceptions/EventStoreConcurrencyException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace APIBlox.NetCore.Exceptions 4 | { 5 | /// 6 | /// 7 | /// Class EventStoreConcurrencyException. 8 | /// 9 | /// 10 | public class EventStoreConcurrencyException : Exception 11 | 12 | { 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// The message that describes the error. 17 | public EventStoreConcurrencyException(string message) 18 | : base(message) 19 | { 20 | } 21 | 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | /// The error message that explains the reason for the exception. 26 | /// 27 | /// The exception that is the cause of the current exception, or a null reference (Nothing in 28 | /// Visual Basic) if no inner exception is specified. 29 | /// 30 | public EventStoreConcurrencyException(string message, Exception innerException) 31 | : base(message, innerException) 32 | { 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/Exceptions/EventStoreNotFoundException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace APIBlox.NetCore.Exceptions 4 | { 5 | /// 6 | /// Class EventStoreNotFoundException. 7 | /// 8 | /// 9 | public class EventStoreNotFoundException : Exception 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The message that describes the error. 15 | public EventStoreNotFoundException(string message) 16 | : base(message) 17 | { 18 | } 19 | 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | /// The error message that explains the reason for the exception. 24 | /// 25 | /// The exception that is the cause of the current exception, or a null reference (Nothing in 26 | /// Visual Basic) if no inner exception is specified. 27 | /// 28 | public EventStoreNotFoundException(string message, Exception innerException) 29 | : base(message, innerException) 30 | { 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/Models/EventModel.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.NetCore.Models 2 | { 3 | /// 4 | /// Class EventModel. 5 | /// 6 | public class EventModel 7 | { 8 | /// 9 | /// Gets or sets the data. 10 | /// 11 | /// The data. 12 | public object Data { get; set; } 13 | 14 | /// 15 | /// Gets or sets the type of the data. 16 | /// 17 | /// The type of the data. 18 | public string DataType { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/Models/EventStreamModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace APIBlox.NetCore.Models 4 | { 5 | /// 6 | /// Class EventStreamModel. 7 | /// 8 | public class EventStreamModel 9 | { 10 | /// 11 | /// Gets or sets the events. 12 | /// 13 | /// The events. 14 | public EventModel[] Events { get; set; } 15 | 16 | /// 17 | /// Gets or sets the snapshot. 18 | /// 19 | /// The snapshot. 20 | public SnapshotModel Snapshot { get; set; } 21 | 22 | /// 23 | /// Gets or sets the stream identifier. 24 | /// 25 | /// The stream identifier. 26 | public string StreamId { get; set; } 27 | 28 | /// 29 | /// Gets or sets the version. 30 | /// 31 | /// The version. 32 | public long Version { get; set; } 33 | 34 | /// 35 | /// Gets or sets the time stamp. 36 | /// 37 | /// The time stamp. 38 | public DateTimeOffset TimeStamp { get; set; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /APIBlox.NetCore.EventStore/Models/SnapshotModel.cs: -------------------------------------------------------------------------------- 1 | namespace APIBlox.NetCore.Models 2 | { 3 | /// 4 | /// Class SnapshotModel. 5 | /// 6 | public class SnapshotModel 7 | { 8 | /// 9 | /// Gets or sets the data. 10 | /// 11 | /// The data. 12 | public object Data { get; set; } 13 | 14 | /// 15 | /// Gets or sets the type of the data. 16 | /// 17 | /// The type of the data. 18 | public string DataType { get; set; } 19 | 20 | /// 21 | /// Gets or sets the version. 22 | /// 23 | /// The version. 24 | public long Version { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /APIBlox.NetCore/APIBlox.NetCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | net5.0 6 | 7 | APIBlox.NetCore 8 | 9 | .NetCore bits. 10 | 11 | APIBlox.NetCore 12 | 13 | APIBlox.NetCore 14 | 15 | APIBlox.NetCore 16 | 17 | latest 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | all 33 | runtime; build; native; contentfiles; analyzers 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /APIBlox.NetCore/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Sln Tests")] 4 | [assembly: InternalsVisibleTo("SlnTests")] 5 | [assembly: 6 | InternalsVisibleTo( 7 | "DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" 8 | )] 9 | -------------------------------------------------------------------------------- /APIBlox.NetCore/Attributes/InjectableServiceAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace APIBlox.NetCore.Attributes 5 | { 6 | /// 7 | /// Attribute that should be applied to any and all services that are dependencies. 8 | /// 9 | /// Service LifeTime defaults to 10 | /// 11 | /// 12 | /// 13 | /// 14 | [AttributeUsage(AttributeTargets.Class)] 15 | public class InjectableServiceAttribute : Attribute 16 | { 17 | /// 18 | /// Gets or sets the service lifetime. Defaults to 19 | /// 20 | /// 21 | public ServiceLifetime ServiceLifetime { get; set; } = ServiceLifetime.Scoped; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /APIBlox.NetCore/Contracts/IDependencyInvertedConfiguration.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Attributes; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace APIBlox.NetCore.Contracts 7 | { 8 | /// 9 | /// Interface IDependencyInvertedConfiguration for assemblies that contain services that follow the 10 | /// Dependency Inversion Principal, and do not or can not be created 11 | /// solely using the 12 | /// 13 | /// 14 | /// Dependency Inversion Principal: 15 | /// ...Implementations depend on abstractions, not vice versa... IE: application layer 16 | /// holds the contract (abstraction) but persistence layer has the implementation, therefore 17 | /// the application layer would NEVER have a reference to the persistence assembly, using DIP, the 18 | /// flow however would appear that the application layer DOES have a reference to the persistence assembly. 19 | /// 20 | public interface IDependencyInvertedConfiguration 21 | { 22 | /// 23 | /// Configures services 24 | /// 25 | /// The services. 26 | /// The configuration. 27 | /// The logger factory. 28 | /// The environment. 29 | /// 30 | void Configure( 31 | IServiceCollection services, IConfiguration configuration, 32 | ILoggerFactory loggerFactory, string environment 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /APIBlox.NetCore/Extensions/Options/ConfigureOptionsWithDependency.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | // ReSharper disable once CheckNamespace 4 | namespace Microsoft.Extensions.Options 5 | { 6 | /// 7 | /// Class ConfigureOptionsWithDependency. 8 | /// 9 | /// The type of the t options. 10 | /// The type of the t dependent. 11 | /// 12 | public class ConfigureOptionsWithDependency 13 | { 14 | /// 15 | /// Gets or sets the action. 16 | /// 17 | /// The action. 18 | /// 19 | public Action Action { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ApiBlox.AspNetCore.DynamicControllers/APIBlox.AspNetCore.DynamicControllers.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | net5.0 6 | 7 | APIBlox.AspNetCore 8 | 9 | Simple dynamic controllers package that puts the focus on resources. 10 | 11 | APIBlox.AspNetCore.DynamicControllers 12 | 13 | APIBlox.AspNetCore.DynamicControllers 14 | 15 | APIBlox.AspNetCore.DynamicControllers 16 | 17 | latest 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | all 40 | runtime; build; native; contentfiles; analyzers 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ApiBlox.AspNetCore/APIBlox.AspNetCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | net5.0 6 | 7 | APIBlox.AspNetCore 8 | 9 | AspNetCore bits. 10 | 11 | APIBlox.AspNetCore 12 | 13 | APIBlox.AspNetCore 14 | 15 | APIBlox.AspNetCore 16 | 17 | latest 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | all 36 | runtime; build; native; contentfiles; analyzers 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ApiBlox.NetCore.Common/APIBlox.NetCore.Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | net5.0 6 | 7 | APIBlox.NetCore 8 | 9 | Cross-Cutting.NetCore bits. 10 | 11 | APIBlox.NetCore.Common 12 | 13 | APIBlox.NetCore.Common 14 | 15 | APIBlox.NetCore.Common 16 | 17 | latest 18 | 19 | 20 | 21 | 22 | all 23 | runtime; build; native; contentfiles; analyzers 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /ApiBlox.NetCore/APIBlox.NetCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | net5.0 6 | 7 | APIBlox.NetCore 8 | 9 | .NetCore bits. 10 | 11 | APIBlox.NetCore 12 | 13 | APIBlox.NetCore 14 | 15 | APIBlox.NetCore 16 | 17 | latest 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | all 33 | runtime; build; native; contentfiles; analyzers 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | Slacquer 4 | Slacquers Building Blox 5 | false 6 | true 7 | true 8 | true 9 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 10 | https://github.com/Slacquer/api-blox/blob/master/logo-blue-small.png?raw=true 11 | Public Production Release 12 | https://github.com/Slacquer/api-blox 13 | true 14 | 15 | GPL-3.0-or-later 16 | 17 | 0.0.0 18 | dynamic-controllers;controller;netcore2;api-rest;cqrs;aspnetcore;asp-net-core;dependency-injection;inversion-of-control;ioc;ioc-container;event-sourcing;cqrs 19 | https://github.com/Slacquer/api-blox 20 | Slacquers Building Blox 21 | 0.0.0.0 22 | 0.0.0.0 23 | GIT 24 | 25 | -------------------------------------------------------------------------------- /Examples/APIBlox Features/Examples.Features/Configuration/SwaggerConfig.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.OpenApi.Models; 3 | using Swashbuckle.AspNetCore.Swagger; 4 | 5 | // ReSharper disable once CheckNamespace 6 | namespace Microsoft.Extensions.DependencyInjection 7 | { 8 | internal static class SwaggerConfig 9 | { 10 | public static IServiceCollection AddSwaggerExampleFeatures(this IServiceCollection services, string siteTitle, string version) 11 | { 12 | return services.AddSwaggerGen(c => 13 | { 14 | c.SwaggerDoc(version, 15 | new OpenApiInfo 16 | { 17 | Title = siteTitle, 18 | Version = version 19 | } 20 | ); 21 | c.IncludeXmlComments(@".\Examples.Features.xml", true); 22 | } 23 | ); 24 | } 25 | 26 | public static IApplicationBuilder UseSwaggerExampleFeatures(this IApplicationBuilder app, string siteTitle, string version) 27 | { 28 | return app.UseSwagger() 29 | .UseSwaggerUI(s => 30 | s.SwaggerEndpoint($"/swagger/{version}/swagger.json", 31 | $"{siteTitle} {version}" 32 | ) 33 | ); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Examples/APIBlox Features/Examples.Features/Contracts/IRandomNumberGeneratorService.cs: -------------------------------------------------------------------------------- 1 | namespace Examples.Contracts 2 | { 3 | /// 4 | /// Interface IRandomNumberGeneratorService 5 | /// 6 | public interface IRandomNumberGeneratorService 7 | { 8 | /// 9 | /// Generates the number. 10 | /// 11 | /// System.Int32. 12 | int GenerateNumber(int max); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Examples/APIBlox Features/Examples.Features/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Examples 7 | { 8 | internal class Program 9 | { 10 | public static void Main(string[] args) 11 | { 12 | StartupLogger = LoggerFactory.Create(a => a.AddConsole()); 13 | 14 | CreateHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static ILoggerFactory StartupLogger { get; private set; } 18 | 19 | private static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Examples/APIBlox Features/Examples.Features/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:52094", 7 | "sslPort": 44365 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "Examples.Features": { 13 | "commandName": "Project", 14 | "launchUrl": "swagger", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | }, 18 | "applicationUrl": "http://localhost:5000" 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Examples/APIBlox Features/Examples.Features/Resources/ExampleRequestObject.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Examples.Resources 4 | { 5 | /// 6 | /// Class ExampleRequestObject. 7 | /// 8 | public class ExampleRequestObject 9 | { 10 | /// 11 | /// Gets the parent value id. 12 | /// 13 | /// The action filter will populate private properties from query and route params. 14 | /// 15 | /// 16 | /// The parent value id. 17 | public int ValueId { get; private set; } // We can either do this or add FromRoute/FromQuery explicitly. 18 | 19 | /// 20 | /// Gets or sets the cool new value. I am required, so if 21 | /// you omit me, then the APIBlox ValidateResourceActionFilter will kick in resulting in an 400. 22 | /// 23 | /// The cool new value. 24 | [Required] 25 | public string CoolNewValue { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Examples/APIBlox Features/Examples.Features/Services/RandomNumberGeneratorService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using APIBlox.NetCore.Attributes; 3 | using Examples.Contracts; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace Examples.Services 7 | { 8 | /// 9 | /// Class RandomNumberGeneratorService. 10 | /// 11 | /// 12 | [InjectableService(ServiceLifetime = ServiceLifetime.Singleton)] 13 | public class RandomNumberGeneratorService : IRandomNumberGeneratorService 14 | { 15 | private static readonly Random Rnd = new((int) (DateTime.Now.Ticks % 100)); 16 | 17 | /// 18 | /// Generates the number. 19 | /// 20 | /// System.Int32. 21 | public int GenerateNumber(int max) 22 | { 23 | return Rnd.Next(1, max); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Examples/APIBlox Features/Examples.Features/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | }, 9 | "ExampleTokens": { 10 | "Version": "1", 11 | "environment": "Dev" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Examples/APIBlox Features/Examples.Features/appsettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | }, 9 | "ExampleTokens": { 10 | "Version": "1", 11 | "environment": "Dev" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Examples/APIBlox Features/Examples.Features/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } 9 | -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/Commands/SimplePostCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using APIBlox.AspNetCore.Types; 4 | using APIBlox.NetCore.Attributes; 5 | using APIBlox.NetCore.Contracts; 6 | using Examples.Resources; 7 | 8 | namespace Examples.Commands 9 | { 10 | [InjectableService] 11 | internal class SimplePostCommand : ICommandHandler 12 | { 13 | public Task HandleAsync(ExampleRequestObject requestCommand, CancellationToken cancellationToken) 14 | { 15 | // This implementation does NOT return anything (other than the task object obviously). 16 | 17 | var res = new HandlerResponse().SetErrorTo400BadRequest("Some Big Fat Error!"); 18 | res.Result = requestCommand.SomeValue; 19 | 20 | return Task.FromResult(res); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/Commands/SimplePostCommandDecorator.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using APIBlox.AspNetCore.Types; 4 | using APIBlox.NetCore.Contracts; 5 | using Examples.Resources; 6 | 7 | namespace Examples.Commands 8 | { 9 | // Not needed as we must explicitly wrap decorators. 10 | //[InjectableService] 11 | internal class SimplePostCommandDecorator : ICommandHandler 12 | { 13 | private readonly ICommandHandler _thingWeAreDecorating; 14 | 15 | public SimplePostCommandDecorator(ICommandHandler thingWeAreDecorating) 16 | { 17 | _thingWeAreDecorating = thingWeAreDecorating; 18 | } 19 | 20 | public async Task HandleAsync(ExampleRequestObject requestCommand, CancellationToken cancellationToken) 21 | { 22 | // Do some kind of test or perhaps domain validation, prior to letting the actual command handler deal with it. 23 | // If validation failed, we could short circuit the process by NOT calling the decorated handler. 24 | var ret = await _thingWeAreDecorating.HandleAsync(requestCommand, cancellationToken); 25 | 26 | // Do something after the handler has dealt with it. 27 | 28 | return ret; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/Configuration/DecoratorsConfig.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Decorators.Commands; 2 | using APIBlox.NetCore.Extensions; 3 | using Examples.Commands; 4 | using Microsoft.Extensions.Logging; 5 | 6 | // ReSharper disable once CheckNamespace 7 | namespace Microsoft.Extensions.DependencyInjection 8 | { 9 | internal static class DecoratorsConfig 10 | { 11 | public static IServiceCollection AddCqrsDecorators(this IServiceCollection services, ILoggerFactory loggerFactory) 12 | { 13 | services.AddCommandHandlerDecoration(loggerFactory, 14 | 15 | // 16 | // Nothing more than a stopwatch. Ideally (my opinion) an API 17 | // call should never take more than 3 seconds. 18 | typeof(MetricsCommandHandlerDecorator<,>), 19 | 20 | // 21 | // This one is still a work in progress and is most likely 22 | // more valuable when combined with domain events. 23 | typeof(TransactionScopeCommandHandlerDecorator<,>), 24 | typeof(SimplePostCommandDecorator) 25 | ); 26 | 27 | return services; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/Configuration/SwaggerConfig.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.OpenApi.Models; 3 | using Swashbuckle.AspNetCore.Swagger; 4 | 5 | // ReSharper disable once CheckNamespace 6 | namespace Microsoft.Extensions.DependencyInjection 7 | { 8 | internal static class SwaggerConfig 9 | { 10 | public static IServiceCollection AddSwaggerExampleFeatures(this IServiceCollection services, string siteTitle, string version) 11 | { 12 | return services.AddSwaggerGen(c => 13 | { 14 | c.SwaggerDoc(version, 15 | new OpenApiInfo 16 | { 17 | Title = siteTitle, 18 | Version = version 19 | } 20 | ); 21 | c.IncludeXmlComments(@".\Examples.Cqrs.xml", true); 22 | } 23 | ); 24 | } 25 | 26 | public static IApplicationBuilder UseSwaggerExampleFeatures(this IApplicationBuilder app, string siteTitle, string version) 27 | { 28 | return app.UseSwagger() 29 | .UseSwaggerUI(s => 30 | s.SwaggerEndpoint($"/swagger/{version}/swagger.json", 31 | $"{siteTitle} {version}" 32 | ) 33 | ); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/Examples.Cqrs.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | Examples 6 | latest 7 | 8 | .\Examples.Cqrs.xml 9 | 10 | 11 | 12 | 13 | TRACE;UseAPIBlox 14 | 15 | 16 | 17 | TRACE;UseAPIBlox1 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Examples 7 | { 8 | internal class Program 9 | { 10 | public static void Main(string[] args) 11 | { 12 | StartupLogger = LoggerFactory.Create(a => a.AddConsole()); 13 | 14 | CreateHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static ILoggerFactory StartupLogger { get; private set; } 18 | 19 | private static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:51384", 7 | "sslPort": 44338 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "api/values", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "Examples.Cqrs": { 21 | "commandName": "Project", 22 | "launchUrl": "swagger", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | }, 26 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/Queries/NoInputsQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using APIBlox.NetCore.Attributes; 5 | using APIBlox.NetCore.Contracts; 6 | 7 | namespace Examples.Queries 8 | { 9 | [InjectableService] 10 | internal class NoInputsQueryHandler : IQueryHandler> 11 | { 12 | public Task> HandleAsync(CancellationToken cancellationToken) 13 | { 14 | var lst = new List {"a", "b", "c"}; 15 | 16 | return Task.FromResult>(lst); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/Queries/RequiresInputQueryQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using APIBlox.NetCore.Attributes; 4 | using APIBlox.NetCore.Contracts; 5 | 6 | namespace Examples.Queries 7 | { 8 | [InjectableService] 9 | internal class RequiresInputQueryQueryHandler : IQueryHandler 10 | { 11 | public Task HandleAsync(int query, CancellationToken cancellationToken) 12 | { 13 | return Task.FromResult(query * 100); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/Resources/ExampleRequestObject.cs: -------------------------------------------------------------------------------- 1 | namespace Examples.Resources 2 | { 3 | /// 4 | /// Class ExampleRequestObject. 5 | /// 6 | public class ExampleRequestObject 7 | { 8 | /// 9 | /// Gets or sets some value. 10 | /// 11 | /// Some value. 12 | public int SomeValue { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /Examples/CQRS/Examples.Cqrs/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/Configuration/SwaggerConfig.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.OpenApi.Models; 3 | 4 | // ReSharper disable once CheckNamespace 5 | namespace Microsoft.Extensions.DependencyInjection 6 | { 7 | internal static class SwaggerConfig 8 | { 9 | public static IServiceCollection AddSwaggerExampleFeatures(this IServiceCollection services, string siteTitle, string version) 10 | { 11 | return services.AddSwaggerGen(c => 12 | { 13 | c.SwaggerDoc(version, 14 | new OpenApiInfo 15 | { 16 | Title = siteTitle, 17 | Version = version 18 | } 19 | ); 20 | c.IncludeXmlComments(@".\Examples.DomainEvents.xml", true); 21 | } 22 | ); 23 | } 24 | 25 | public static IApplicationBuilder UseSwaggerExampleFeatures(this IApplicationBuilder app, string siteTitle, string version) 26 | { 27 | return app.UseSwagger() 28 | .UseSwaggerUI(s => 29 | s.SwaggerEndpoint($"/swagger/{version}/swagger.json", 30 | $"{siteTitle} {version}" 31 | ) 32 | ); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/Contracts/ILameRepository.cs: -------------------------------------------------------------------------------- 1 | using Examples.DomainModels; 2 | 3 | namespace Examples.Contracts 4 | { 5 | /// 6 | /// Interface ILameRepository 7 | /// 8 | public interface ILameRepository 9 | { 10 | /// 11 | /// Adds the domain object. 12 | /// 13 | /// The domain object. 14 | void AddDomainObject(DomainObject domainObject); 15 | 16 | /// 17 | /// Saves the changes. 18 | /// 19 | void SaveChanges(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/EventBits/RequestObjectCreatedEvent.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Contracts; 2 | 3 | namespace Examples.EventBits 4 | { 5 | /// 6 | /// Class RequestObjectCreatedEvent. 7 | /// 8 | /// 9 | public class RequestObjectCreatedEvent : IDomainEvent 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The value that was created. 15 | /// 16 | /// Some other domain specific event value needed for consumption. 17 | /// 18 | public RequestObjectCreatedEvent(int theValueThatWasCreated, string someOtherDomainSpecificEventValueNeededForConsumption) 19 | { 20 | TheValueThatWasCreated = theValueThatWasCreated; 21 | SomeOtherDomainSpecificEventValueNeededForConsumption = someOtherDomainSpecificEventValueNeededForConsumption; 22 | } 23 | 24 | /// 25 | /// Gets the value that was created. 26 | /// 27 | /// The value that was created. 28 | public int TheValueThatWasCreated { get; } 29 | 30 | /// 31 | /// Gets some other domain specific event value needed for consumption. 32 | /// 33 | public string SomeOtherDomainSpecificEventValueNeededForConsumption { get; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/EventBits/RequestObjectCreatedEventHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using APIBlox.NetCore.Attributes; 4 | using APIBlox.NetCore.Contracts; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace Examples.EventBits 8 | { 9 | [InjectableService] 10 | internal class RequestObjectCreatedEventHandler : IDomainEventHandler 11 | { 12 | private readonly ILogger _log; 13 | 14 | public RequestObjectCreatedEventHandler(ILoggerFactory loggerFactory) 15 | { 16 | _log = loggerFactory.CreateLogger(); 17 | } 18 | 19 | public Task HandleEventAsync(RequestObjectCreatedEvent domainEvent, CancellationToken cancellationToken = default) 20 | { 21 | _log.LogInformation(() => 22 | "------------------\n\nHandling created event. Its special value " + 23 | $"is {domainEvent.SomeOtherDomainSpecificEventValueNeededForConsumption}, the " + 24 | $"value that was used during request was {domainEvent.TheValueThatWasCreated}\n\n-------------\n\n" 25 | ); 26 | 27 | // Not actually doing anything outside of a log entry. 28 | // Just imagine I am part of a different aggregate root. 29 | 30 | return Task.CompletedTask; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/Examples.DomainEvents.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | Examples 6 | latest 7 | 8 | .\Examples.DomainEvents.xml 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/Examples.DomainEvents.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/InfrastructureAndDomainBits/DomainModels/DomainObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using APIBlox.NetCore.Contracts; 5 | using Examples.EventBits; 6 | 7 | namespace Examples.DomainModels 8 | { 9 | /// 10 | /// Class DomainObject. 11 | /// 12 | public class DomainObject 13 | { 14 | private readonly List _domainEvents = new(); 15 | 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | /// Some value to save. 20 | public DomainObject(int someValueToSave) 21 | { 22 | SomeValueToSave = someValueToSave; 23 | 24 | _domainEvents.Add(new RequestObjectCreatedEvent(someValueToSave, DateTime.Now.ToLongTimeString())); 25 | } 26 | 27 | /// 28 | /// Gets some value to save. 29 | /// 30 | /// Some value to save. 31 | public int SomeValueToSave { get; } 32 | 33 | /// 34 | /// Gets or sets the identifier. 35 | /// 36 | /// The identifier. 37 | public int Id { get; set; } 38 | 39 | /// 40 | /// Gets the events. 41 | /// 42 | /// The events. 43 | public IEnumerable Events => _domainEvents.ToList(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/InfrastructureAndDomainBits/LameRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using APIBlox.NetCore.Attributes; 3 | using APIBlox.NetCore.Contracts; 4 | using Examples.Contracts; 5 | using Examples.DomainModels; 6 | 7 | namespace Examples 8 | { 9 | [InjectableService] 10 | internal class LameRepository : ILameRepository 11 | { 12 | private static readonly Dictionary Models = new(); 13 | private readonly IDomainEventsDispatcher _dispatcher; 14 | 15 | public LameRepository(IDomainEventsDispatcher dispatcher) 16 | { 17 | _dispatcher = dispatcher; 18 | } 19 | 20 | public void AddDomainObject(DomainObject domainObject) 21 | { 22 | if (Models.ContainsKey(domainObject.Id)) 23 | Models.Remove(domainObject.Id); 24 | 25 | Models.Add(domainObject.Id, domainObject); 26 | } 27 | 28 | public void SaveChanges() 29 | { 30 | var lst = new List(); 31 | 32 | foreach (var obj in Models.Values) 33 | lst.AddRange(obj.Events); 34 | 35 | _dispatcher.PublishEventsAsync(lst.ToArray()); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Examples 7 | { 8 | internal class Program 9 | { 10 | 11 | public static void Main(string[] args) 12 | { 13 | StartupLogger = LoggerFactory.Create(a => a.AddConsole()); 14 | 15 | CreateHostBuilder(args).Build().Run(); 16 | } 17 | 18 | public static ILoggerFactory StartupLogger { get; private set; } 19 | 20 | private static IHostBuilder CreateHostBuilder(string[] args) => 21 | Host.CreateDefaultBuilder(args) 22 | .ConfigureWebHostDefaults(webBuilder => 23 | { 24 | webBuilder.UseStartup(); 25 | }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:52705", 7 | "sslPort": 0 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchUrl": "swagger", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "Examples.DomainEvents": { 20 | "commandName": "Project", 21 | "launchUrl": "swagger", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | }, 25 | "applicationUrl": "http://localhost:5000" 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/Resources/ExampleRequestObject.cs: -------------------------------------------------------------------------------- 1 | namespace Examples.Resources 2 | { 3 | /// 4 | /// Class ExampleRequestObject. 5 | /// 6 | public class ExampleRequestObject 7 | { 8 | /// 9 | /// Gets or sets some value. 10 | /// 11 | /// Some value. 12 | public int SomeValue { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /Examples/Domain Events/Examples.DomainEvents/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/CmdQueryHandlers/ChildByIdRequestCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using APIBlox.AspNetCore.Types; 4 | using APIBlox.NetCore.Attributes; 5 | using APIBlox.NetCore.Contracts; 6 | using Examples.Resources; 7 | 8 | namespace Examples.CmdQueryHandlers 9 | { 10 | [InjectableService] 11 | internal class ChildByIdRequestCommandHandler : ICommandHandler 12 | { 13 | public Task HandleAsync(ChildByIdRequest requestCommand, CancellationToken cancellationToken) 14 | { 15 | var ret = new HandlerResponse 16 | { 17 | Result = new ChildResponse {Age = 4} 18 | }; 19 | 20 | return Task.FromResult(ret); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/CmdQueryHandlers/ChildByIdRequestHandlers.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using APIBlox.AspNetCore.Types; 6 | using APIBlox.NetCore.Attributes; 7 | using APIBlox.NetCore.Contracts; 8 | using Examples.Resources; 9 | 10 | namespace Examples.CmdQueryHandlers 11 | { 12 | [InjectableService] 13 | internal class ChildByIdRequestHandlers : 14 | IQueryHandler 15 | { 16 | public Task HandleAsync(ChildByIdRequest query, CancellationToken cancellationToken) 17 | { 18 | var ret = new HandlerResponse 19 | { 20 | Result = new List 21 | { 22 | new() 23 | { 24 | Age = 5, 25 | FirstName = "Sebastian", 26 | Id = 1, 27 | LastName = "Booth", 28 | Parents = new Collection 29 | { 30 | new() 31 | { 32 | Age = 29, 33 | LastName = "Booth", 34 | FirstName = "Britani" 35 | } 36 | } 37 | } 38 | } 39 | }; 40 | 41 | //ret.CreateError().SetErrorToBadRequest("OMG!"); 42 | 43 | return Task.FromResult(ret); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/CmdQueryHandlers/ChildPatchRequestCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using APIBlox.AspNetCore.Types; 4 | using APIBlox.NetCore.Attributes; 5 | using APIBlox.NetCore.Contracts; 6 | using Examples.Resources; 7 | 8 | namespace Examples.CmdQueryHandlers 9 | { 10 | [InjectableService] 11 | internal class ChildPatchRequestCommandHandler : ICommandHandler 12 | { 13 | public Task HandleAsync(ChildPatchRequest requestCommand, CancellationToken cancellationToken) 14 | { 15 | var ret = new HandlerResponse(); 16 | 17 | return Task.FromResult(ret); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/CmdQueryHandlers/ChildPostRequestCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using APIBlox.AspNetCore.Types; 4 | using APIBlox.NetCore.Attributes; 5 | using APIBlox.NetCore.Contracts; 6 | using Examples.Resources; 7 | 8 | namespace Examples.CmdQueryHandlers 9 | { 10 | [InjectableService] 11 | internal class ChildPostRequestCommandHandler : ICommandHandler 12 | { 13 | public Task HandleAsync(ChildPostRequest requestCommand, CancellationToken cancellationToken) 14 | { 15 | var ret = new HandlerResponse(); 16 | 17 | // if we don't return something the controller will complain. It will also complain if 18 | // it can not find a property that ends with "id", as it can't create a CreatedAtRoute. 19 | 20 | ret.Result = new {id = 1, Foo = "barrrr"}; 21 | 22 | return Task.FromResult(ret); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/CmdQueryHandlers/ChildPutRequestCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using APIBlox.AspNetCore.Types; 4 | using APIBlox.NetCore.Attributes; 5 | using APIBlox.NetCore.Contracts; 6 | using Examples.Resources; 7 | 8 | namespace Examples.CmdQueryHandlers 9 | { 10 | [InjectableService] 11 | internal class ChildPutRequestCommandHandler : ICommandHandler 12 | { 13 | public Task HandleAsync(ChildPutRequest requestCommand, CancellationToken cancellationToken) 14 | { 15 | var ret = new HandlerResponse(); 16 | 17 | return Task.FromResult(ret); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/CmdQueryHandlers/ChildrenRequestQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using APIBlox.AspNetCore.Types; 5 | using APIBlox.NetCore.Attributes; 6 | using APIBlox.NetCore.Contracts; 7 | using Examples.Resources; 8 | 9 | namespace Examples.CmdQueryHandlers 10 | { 11 | [InjectableService] 12 | internal class ChildrenRequestQueryHandler : IQueryHandler 13 | { 14 | public Task HandleAsync(ChildrenRequest query, CancellationToken cancellationToken) 15 | { 16 | var ret = new HandlerResponse (); 17 | 18 | // if we do not return something then the controller will get mad at us! 19 | var kids = new List(); 20 | 21 | for (var i = 0; i < 10; i++) 22 | kids.Add(new ChildResponse { Age = i }); 23 | 24 | ret.Result = kids; 25 | 26 | return Task.FromResult(ret); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Configuration/SwaggerConfig.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Extensions; 2 | //using MicroElements.Swashbuckle.FluentValidation; 3 | using Microsoft.AspNetCore.Builder; 4 | using Microsoft.OpenApi.Models; 5 | 6 | // ReSharper disable once CheckNamespace 7 | namespace Microsoft.Extensions.DependencyInjection 8 | { 9 | internal static class SwaggerConfig 10 | { 11 | public static IServiceCollection AddSwaggerExampleFeatures(this IServiceCollection services, string siteTitle, string version, 12 | string dynamicControllersXmlFile 13 | ) 14 | { 15 | return services.AddSwaggerGen(c => 16 | { 17 | c.SwaggerDoc(version, 18 | new OpenApiInfo 19 | { 20 | Title = siteTitle, 21 | Version = version 22 | } 23 | ); 24 | c.IncludeXmlComments(@".\Examples.DynamicControllers.xml", true); 25 | 26 | if (!dynamicControllersXmlFile.IsEmptyNullOrWhiteSpace()) 27 | c.IncludeXmlComments(dynamicControllersXmlFile, true); 28 | 29 | //c.AddFluentValidationRules(); 30 | //c.SchemaFilter(); 31 | //c.OperationFilter(); 32 | } 33 | ); 34 | } 35 | 36 | public static IApplicationBuilder UseSwaggerExampleFeatures(this IApplicationBuilder app, string siteTitle, string version) 37 | { 38 | return app.UseSwagger() 39 | .UseSwaggerUI(s => 40 | s.SwaggerEndpoint($"/swagger/{version}/swagger.json", 41 | $"{siteTitle} {version}" 42 | ) 43 | ); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Contracts/IChildRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Examples.Contracts 2 | { 3 | internal interface IChildRequest 4 | { 5 | bool LikesCandy { get; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Contracts/IRandomNumberGeneratorService.cs: -------------------------------------------------------------------------------- 1 | namespace Examples.Contracts 2 | { 3 | /// 4 | /// Interface IRandomNumberGeneratorService 5 | /// 6 | public interface IRandomNumberGeneratorService 7 | { 8 | /// 9 | /// Generates the number. 10 | /// 11 | /// System.Int32. 12 | int GenerateNumber(int max); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Examples.DynamicControllers.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | Examples 6 | latest 7 | 8 | .\Examples.DynamicControllers.xml 9 | 10 | 11 | 12 | TRACE;UseAPIBlox 13 | 14 | 15 | 16 | TRACE;UseAPIBlox1 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Examples 7 | { 8 | internal class Program 9 | { 10 | public static void Main(string[] args) 11 | { 12 | StartupLogger = LoggerFactory.Create(a => a.AddConsole()); 13 | 14 | CreateHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static ILoggerFactory StartupLogger { get; private set; } 18 | 19 | private static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:52094", 7 | "sslPort": 44365 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "Examples.Features": { 13 | "commandName": "Project", 14 | "launchUrl": "swagger", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | }, 18 | "applicationUrl": "http://localhost:5000" 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/AllRequest.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace Examples.Resources 5 | { 6 | /// 7 | /// Class AllRequest. 8 | /// 9 | public class AllRequest 10 | { 11 | /// 12 | /// The required value, and it must be three characters. please check out http://www.kids.com for more info. 13 | /// 14 | /// The required value must be three characters. 15 | [FromQuery] 16 | [Required] 17 | [StringLength(3, MinimumLength = 3, ErrorMessage = "Value must be exactly 3 characters long.")] 18 | public string RequiredValueMustBeThreeCharacters { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/ByIdRequest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Examples.Resources 4 | { 5 | /// 6 | /// 7 | /// ByIdRequest. 8 | /// 9 | public class ByIdRequest : AllRequest 10 | { 11 | /// 12 | /// Gets or sets some identifier. 13 | /// 14 | /// Some identifier. 15 | [FromRoute(Name = "someId")] 16 | public int Id { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/ChildByIdRequest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Examples.Resources 4 | { 5 | /// 6 | /// This comment came from the first request object as part of the first 7 | /// action that was added to this controller. The request object is the type ChildByIdRequest. 8 | /// 9 | public class ChildByIdRequest 10 | { 11 | /// 12 | /// Sets the child id. 13 | /// 14 | [FromRoute(Name = "childId")] 15 | public int Id { get; set; } 16 | 17 | /// 18 | /// Gets or sets the parent identifier. 19 | /// 20 | /// The parent identifier. 21 | [FromRoute] 22 | public int ParentId { get; set; } 23 | 24 | /// 25 | /// Gets or sets a value indicating whether this is help. 26 | /// 27 | /// null if [help] contains no value, true if [help]; otherwise, false. 28 | [FromQuery] 29 | public bool? Help { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/ChildPatchRequest.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Microsoft.AspNetCore.JsonPatch; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace Examples.Resources 6 | { 7 | /// 8 | /// Class ChildPutRequest. 9 | /// 10 | public class ChildPatchRequest : ChildByIdRequest 11 | { 12 | /// 13 | /// Gets or sets an query value we want. 14 | /// 15 | /// An query value we want. 16 | [FromQuery] 17 | [Required] 18 | public int AQueryValueWeWant { get; set; } 19 | 20 | /// 21 | /// Sets the body (patch document). 22 | /// 23 | /// The body. 24 | [FromBody] 25 | public JsonPatchDocument Body { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/ChildPostRequest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Examples.Resources 4 | { 5 | /// 6 | /// Class ChildPostRequest. 7 | /// 8 | public class ChildPostRequest 9 | { 10 | /// 11 | /// Gets or sets the parent identifier. 12 | /// 13 | /// The parent identifier. 14 | [FromRoute(Name = "parentId")] 15 | public int ParentId { get; set; } 16 | 17 | /// 18 | /// Gets or sets the body. 19 | /// 20 | /// The body. 21 | [FromBody] 22 | public PersonModel Child { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/ChildPutRequest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Examples.Resources 4 | { 5 | /// 6 | /// Class ChildPutRequest. 7 | /// 8 | public class ChildPutRequest : ChildByIdRequest 9 | { 10 | /// 11 | /// Gets or sets an query value we want. 12 | /// 13 | /// An query value we want. 14 | [FromQuery] 15 | public int? AnQueryValueWeWant { get; set; } 16 | 17 | /// 18 | /// Gets or sets the body. 19 | /// 20 | /// The body. 21 | [FromBody] 22 | public PersonModel Body { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/ChildRequest.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Types; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace Examples.Resources 5 | { 6 | /// 7 | /// Class ChildRequest. 8 | /// 9 | /// 10 | /// 11 | public class ChildrenRequest : FilteredQuery 12 | { 13 | /// 14 | /// Gets or sets the parent identifier. 15 | /// 16 | /// The parent identifier. 17 | [FromRoute] 18 | public int ParentId { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/ChildResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using APIBlox.AspNetCore.Contracts; 3 | 4 | namespace Examples.Resources 5 | { 6 | /// 7 | /// Class ChildResponse. 8 | /// 9 | public class ChildResponse : IResource 10 | { 11 | /// 12 | /// Gets or sets the age. 13 | /// 14 | /// The age. 15 | public int Age { get; set; } 16 | 17 | /// 18 | /// Gets or sets the first name. 19 | /// 20 | /// The first name. 21 | public string FirstName { get; set; } 22 | 23 | /// 24 | /// Gets or sets the Id. 25 | /// 26 | /// The Id. 27 | public int Id { get; set; } 28 | 29 | /// 30 | /// Gets or sets the last name. 31 | /// 32 | /// The last name. 33 | public string LastName { get; set; } 34 | 35 | /// 36 | /// Gets or sets the parents. 37 | /// 38 | /// The parents. 39 | public Collection Parents { get; set; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/ParentPostRequest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Examples.Resources 4 | { 5 | /// 6 | /// Class ParentPostRequest. 7 | /// 8 | public class ParentPostRequest 9 | { 10 | /// 11 | /// Gets or sets the body. 12 | /// 13 | /// The body. 14 | [FromBody] 15 | public PersonModel Body { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/ParentRequest.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.AspNetCore.Types; 2 | 3 | namespace Examples.Resources 4 | { 5 | /// 6 | /// This is the summary shown since it is the FIRST template generated. 7 | /// 8 | public class ParentRequest : FilteredPaginationQuery 9 | { 10 | ///// 11 | ///// Gets or sets the identifier. 12 | ///// 13 | ///// The identifier. 14 | //[FromRoute(Name = "parentId")] 15 | //public int Id { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/ParentResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using APIBlox.AspNetCore.Contracts; 3 | 4 | namespace Examples.Resources 5 | { 6 | /// 7 | /// Class ParentResponse. 8 | /// 9 | /// 10 | public class ParentResponse : IResource 11 | { 12 | /// 13 | /// 14 | /// Gets or sets the Id. 15 | /// 16 | /// The Id. 17 | public int Id { get; set; } 18 | 19 | /// 20 | /// Gets or sets the age. 21 | /// 22 | /// The age. 23 | public int Age { get; set; } 24 | 25 | /// 26 | /// Gets or sets the first name. 27 | /// 28 | /// The first name. 29 | public string FirstName { get; set; } 30 | 31 | /// 32 | /// Gets or sets the last name. 33 | /// 34 | /// The last name. 35 | public string LastName { get; set; } 36 | 37 | /// 38 | /// Gets or sets the children. 39 | /// 40 | /// The children. 41 | public Collection Children { get; set; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Resources/PersonModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Examples.Resources 4 | { 5 | /// 6 | /// Class PersonModel. 7 | /// 8 | public class PersonModel 9 | { 10 | /// 11 | /// Gets or sets the age. 12 | /// 13 | /// The age. 14 | [Required] 15 | public int Age { get; set; } 16 | 17 | /// 18 | /// Gets or sets the first name. 19 | /// 20 | /// The first name. 21 | [Required] 22 | public string FirstName { get; set; } 23 | 24 | /// 25 | /// Gets or sets the last name. 26 | /// 27 | /// The last name. 28 | [Required] 29 | public string LastName { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Services/RandomNumberGeneratorService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using APIBlox.NetCore.Attributes; 3 | using Examples.Contracts; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace Examples.Services 7 | { 8 | /// 9 | /// 10 | /// Class RandomNumberGeneratorService. 11 | /// 12 | /// 13 | [InjectableService(ServiceLifetime = ServiceLifetime.Singleton)] 14 | public class RandomNumberGeneratorService : IRandomNumberGeneratorService 15 | { 16 | private static readonly Random Rnd = new((int) (DateTime.Now.Ticks % 100)); 17 | 18 | /// 19 | /// 20 | /// Generates the number. 21 | /// 22 | /// System.Int32. 23 | public int GenerateNumber(int max) 24 | { 25 | return Rnd.Next(1, max); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using APIBlox.AspNetCore.Contracts; 3 | using Examples.Configuration; 4 | using Microsoft.AspNetCore.Hosting; 5 | 6 | namespace Examples 7 | { 8 | /// 9 | /// 10 | /// Class Startup. 11 | /// Implements the 12 | /// 13 | public class Startup : StartupBase 14 | { 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// The environment. 19 | public Startup(IWebHostEnvironment environment) 20 | : base(environment) 21 | { 22 | } 23 | 24 | /// 25 | /// Builds the templates. 26 | /// 27 | /// The templates. 28 | /// IEnumerable<IComposedTemplate>. 29 | protected override IEnumerable BuildTemplates(List templates) 30 | { 31 | templates 32 | .AddChildrenControllerTemplates() 33 | .AddParentsControllerTemplates() 34 | ; 35 | 36 | return templates; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } -------------------------------------------------------------------------------- /Examples/Dynamic Controllers/Examples.DynamicControllers/swaggerGen.dat: -------------------------------------------------------------------------------- 1 | -a c:\Source\Repos\Fks\api-blox\Examples\Dynamic Controllers\Examples.DynamicControllers\bin\debug\netcoreapp2.2\Examples.DynamicControllers.dll 2 | -ap c:\Source\Repos\Fks\api-blox\Examples\Dynamic Controllers\Examples.DynamicControllers\appsettings.json 3 | -t Startup 4 | -o c:\Source\Repos\Fks\api-blox\Examples\Dynamic Controllers\Examples.DynamicControllers\bin\debug\netcoreapp2.2\swagger.json 5 | 6 | -pretty -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/AggregateModels/CosmosAggregate.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Contracts; 2 | 3 | namespace Examples.AggregateModels 4 | { 5 | /// 6 | /// 7 | /// Class CosmosAggregate. 8 | /// Implements the 9 | /// 10 | public class CosmosAggregate : Aggregate 11 | { 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | /// The event store service. 16 | /// The stream identifier. 17 | public CosmosAggregate(IEventStoreService eventStoreService, string streamId) 18 | : base(eventStoreService, streamId) 19 | { 20 | } 21 | } 22 | 23 | /// 24 | /// 25 | /// Class CosmosAggregate. 26 | /// Implements the 27 | /// 28 | public class CosmosAggregate2 : Aggregate 29 | { 30 | /// 31 | /// Initializes a new instance of the class. 32 | /// 33 | /// The event store service. 34 | /// The stream identifier. 35 | public CosmosAggregate2(IEventStoreService eventStoreService, string streamId) 36 | : base(eventStoreService, streamId) 37 | { 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/AggregateModels/EfCoreSqlAggregate.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Contracts; 2 | 3 | namespace Examples.AggregateModels 4 | { 5 | /// 6 | /// 7 | /// Class EfCoreSqlAggregate. 8 | /// Implements the 9 | /// 10 | public class EfCoreSqlAggregate : Aggregate 11 | { 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | /// The event store service. 16 | /// The stream identifier. 17 | public EfCoreSqlAggregate(IEventStoreService eventStoreService, string streamId) 18 | : base(eventStoreService, streamId) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/AggregateModels/MongoAggregate.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Contracts; 2 | 3 | namespace Examples.AggregateModels 4 | { 5 | /// 6 | /// 7 | /// Class MongoAggregate. 8 | /// Implements the 9 | /// 10 | public class MongoAggregate : Aggregate 11 | { 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | /// The event store service. 16 | /// The stream identifier. 17 | public MongoAggregate(IEventStoreService eventStoreService, string streamId) 18 | : base(eventStoreService, streamId) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/AggregateModels/RavenAggregate.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Contracts; 2 | 3 | namespace Examples.AggregateModels 4 | { 5 | /// 6 | /// 7 | /// Class RavenAggregate. 8 | /// Implements the 9 | /// 10 | public class RavenAggregate : Aggregate 11 | { 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | /// The event store service. 16 | /// The stream identifier. 17 | public RavenAggregate(IEventStoreService eventStoreService, string streamId) 18 | : base(eventStoreService, streamId) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/Configuration/SwaggerConfig.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.OpenApi.Models; 4 | 5 | namespace Examples.Configuration 6 | { 7 | internal static class SwaggerConfig 8 | { 9 | public static IServiceCollection AddSwaggerExampleFeatures(this IServiceCollection services, string siteTitle, string version) 10 | { 11 | return services.AddSwaggerGen(c => 12 | { 13 | c.SwaggerDoc(version, 14 | new OpenApiInfo 15 | { 16 | Title = siteTitle, 17 | Version = version 18 | } 19 | ); 20 | c.IncludeXmlComments(@".\Examples.EventSourcing.xml", true); 21 | } 22 | ); 23 | } 24 | 25 | public static IApplicationBuilder UseSwaggerExampleFeatures(this IApplicationBuilder app, string siteTitle, string version) 26 | { 27 | return app.UseSwagger() 28 | .UseSwaggerUI(s => 29 | s.SwaggerEndpoint($"/swagger/{version}/swagger.json", 30 | $"{siteTitle} {version}" 31 | ) 32 | ); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/Controllers/EventSourcingEfCoreController.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Contracts; 2 | using Examples.AggregateModels; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace Examples.Controllers 6 | { 7 | /// 8 | /// 9 | /// Class EventSourcingController. 10 | /// Implements the 11 | /// 12 | /// 13 | /// 14 | /// 15 | [Route("api/[controller]")] 16 | [ApiController] 17 | public class EventSourcingEfCoreController : EventSourcingController 18 | { 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// 22 | /// The SVC. 23 | public EventSourcingEfCoreController(IEventStoreService svc) 24 | : base(svc) 25 | { 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/Controllers/EventSourcingMongoDbController.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Contracts; 2 | using Examples.AggregateModels; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace Examples.Controllers 6 | { 7 | /// 8 | /// 9 | /// Class EventSourcingController. 10 | /// Implements the 11 | /// 12 | /// 13 | /// 14 | /// 15 | [Route("api/[controller]")] 16 | [ApiController] 17 | public class EventSourcingMongoDbController : EventSourcingController 18 | { 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// 22 | /// The SVC. 23 | public EventSourcingMongoDbController(IEventStoreService svc) 24 | : base(svc) 25 | { 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/Controllers/EventSourcingRavenDbController.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Contracts; 2 | using Examples.AggregateModels; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace Examples.Controllers 6 | { 7 | /// 8 | /// 9 | /// Class EventSourcingController. 10 | /// Implements the 11 | /// 12 | /// 13 | /// 14 | /// 15 | [Route("api/[controller]")] 16 | [ApiController] 17 | public class EventSourcingRavenDbController : EventSourcingController 18 | { 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// 22 | /// The SVC. 23 | public EventSourcingRavenDbController(IEventStoreService svc) 24 | : base(svc) 25 | { 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/Events/SomeValueAdded.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Examples.Events 4 | { 5 | internal class SomeValueAdded 6 | { 7 | public SomeValueAdded(Guid aggregateId, string someValue) 8 | { 9 | AggregateId = aggregateId; 10 | SomeValue = someValue; 11 | } 12 | 13 | public string SomeValue { get; } 14 | 15 | public Guid AggregateId { get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/Events/SomeValueChanged.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Examples.Events 4 | { 5 | internal class SomeValueChanged 6 | { 7 | public SomeValueChanged(Guid aggregateId, string someValue) 8 | { 9 | AggregateId = aggregateId; 10 | SomeValue = someValue; 11 | } 12 | 13 | public string SomeValue { get; } 14 | 15 | public Guid AggregateId { get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/Examples.EventSourcing.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | Examples 6 | latest 7 | 8 | 9 | 10 | .\Examples.EventSourcing.xml 11 | TRACE;UseAPIBlox 12 | 13 | 14 | 15 | TRACE;UseAPIBlox1 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/Examples.EventSourcing.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | False 3 | False -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Examples 7 | { 8 | internal class Program 9 | { 10 | public static void Main(string[] args) 11 | { 12 | StartupLogger = LoggerFactory.Create(a => a.AddConsole()); 13 | 14 | CreateHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static ILoggerFactory StartupLogger { get; private set; } 18 | 19 | private static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:52518", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "Examples.EventSourcing": { 19 | "commandName": "Project", 20 | "launchUrl": "http://localhost:5000/swagger", 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/Resources/AggregateResource.cs: -------------------------------------------------------------------------------- 1 | namespace Examples.Resources 2 | { 3 | /// 4 | /// Class AggregateResource. 5 | /// 6 | public class AggregateResource 7 | { 8 | /// 9 | /// Gets or sets the first name. 10 | /// 11 | /// The first name. 12 | public string FirstName { get; set; } 13 | 14 | /// 15 | /// Gets or sets some value. 16 | /// 17 | /// Some value. 18 | public string SomeValue { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Event Sourcing/Examples.EventSourcing/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*", 8 | 9 | "CosmosDbOptions": { 10 | "Endpoint": "https://localhost:8081", 11 | "Key": "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==", 12 | "DatabaseId": "APIBloxExamples", 13 | 14 | "CollectionProperties": { 15 | "DemoData": { 16 | "Models": [ "CosmosAggregate" ], 17 | "UniqueKeyPolicy": { 18 | "uniqueKeys": [] 19 | }, 20 | "OfferThroughput": -1 21 | }, 22 | "DemoData2": { 23 | "Models": [ "CosmosAggregate2" ], 24 | "UniqueKeyPolicy": { 25 | "uniqueKeys": [] 26 | }, 27 | "OfferThroughput": -1 28 | } 29 | } 30 | }, 31 | 32 | "MongoDbOptions": { 33 | "CnnString": "mongodb://localhost:27017", 34 | "DatabaseId": "APIBloxExamples", 35 | 36 | "CollectionProperties": { 37 | "MongoAggregate": { 38 | "Indexes": [ "{streamId:1}", "{documentType:1}" ] 39 | } 40 | } 41 | }, 42 | 43 | "RavenDbOptions": { 44 | "Urls": [ "http://127.0.0.1:8080" ], 45 | "DatabaseId": "APIBloxExamples", 46 | 47 | "CollectionProperties": { 48 | "RavenAggregate": { 49 | } 50 | } 51 | }, 52 | 53 | "EfCoreSqlOptions": { 54 | "CnnString": "Server=.;Database=UserSettingsDb;Trusted_Connection=True;", 55 | "EnableDetailedErrors": true, 56 | "EnableSensitiveDataLogging": true, 57 | "ConfigureWarnings": true 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Kill Assets.Json.cmd: -------------------------------------------------------------------------------- 1 | attrib -r *.assets.json /s 2 | del *.assets.json /s /q -------------------------------------------------------------------------------- /Kill Bin and Obj.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | cls 3 | dir bin /s /AD /b > clean.tmp 4 | dir obj /s /AD /b >> clean.tmp 5 | for /F "tokens=*" %%A in (clean.tmp) do echo rmdir /S /Q "%%A" 6 | echo This command will remove ALL BIN and OBJ folders in this tree. 7 | rem echo To run the commands as listed ... 8 | rem pause 9 | for /F "tokens=*" %%A in (clean.tmp) do rmdir /S /Q "%%A" 10 | del clean.tmp 11 | rem pause 12 | timeout /t 5 -------------------------------------------------------------------------------- /SlnTests/APIBlox.AspNetCore.OpenApi/BuilderTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Xunit; 3 | 4 | namespace SlnTests.APIBlox.AspNetCore.OpenApi 5 | { 6 | #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 7 | public class BuilderTests 8 | { 9 | [Fact] 10 | public void DocumentShouldNotBeEmpty() 11 | { 12 | var col = new ServiceCollection(); 13 | 14 | //col.AddOpenApiBits(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SlnTests/APIBlox.NetCore/SimpleMapperTests.cs: -------------------------------------------------------------------------------- 1 | using APIBlox.NetCore.Types; 2 | using APIBlox.NetCore.Types.JsonBits; 3 | using Newtonsoft.Json; 4 | using Xunit; 5 | 6 | namespace SlnTests.APIBlox.NetCore 7 | { 8 | #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 9 | 10 | public class SimpleMapperTests 11 | { 12 | public class Foo 13 | { 14 | public string Name { get; set; } 15 | } 16 | 17 | public class Bar 18 | { 19 | public string Name { get; private set; } 20 | } 21 | 22 | [Fact] 23 | public void Success() 24 | { 25 | var foo = new Foo {Name = " "}; 26 | 27 | var bar = foo.MapTo(settings: new JsonSerializerSettings 28 | { 29 | Converters = new JsonConverter[] {new EmptyStringToNullConverter()}, 30 | ContractResolver = new PopulateNonPublicSettersContractResolver() 31 | } 32 | ); 33 | 34 | Assert.Null(bar.Name); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /logo-blue-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slacquer/api-blox/0f27afa37480bf991ff9745dc9739bc9707660a6/logo-blue-large.png -------------------------------------------------------------------------------- /logo-blue-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slacquer/api-blox/0f27afa37480bf991ff9745dc9739bc9707660a6/logo-blue-small.png --------------------------------------------------------------------------------