- Visual Studio 2017
- NCrunch 3.16.0.1 for continous testing
- reSharper 2018.1
- .NET Core 2.0
FluentAssertions(https://github.com/fluentassertions/fluentassertions)FakeItEasyfor mocking (https://github.com/FakeItEasy/FakeItEasy)xUnitfor test runner (https://github.com/xunit/xunit)Bogusfor faking some values (https://github.com/bchavez/Bogus)
cakebuild(https://cakebuild.net/)changeversion.shandbuild.shfor unix pipelinechangeversion.ps1for windows ci pipeline- These files are being used in
build.cakefile
- These files are being used in
Directory.build.propsfor injectingVersionto allcsprojfiles
buildNumberbranchcfg- To execute:
./build.ps1 -buildNumber=102 -branch="dev" -cfg="release"
Cake calls changeversion.ps1 or changeverison.sh with buildNumber depending to your build environment, that will allow to produce a new version of your Nuget packages.
Changing the version affects the BasketContext.Client only. It is assumed as nuget package that should be published by user with every successful dev to master merge.
This Web API application can be hosted with Docker.
Build: docker build -t basketcontext .
Run: docker run -p 5000:5000 -i -t basketcontext
There is a nugetApiKey variable inside of Cake script. If developer wants to produce and push a Nuget package to Official Nuget Repository(which is assumed) then user needs to provide an environment variable with named as nugetApiKey.
To create a new nuget package and build you can execute:
./build.ps1 -buildNumber=102 -branch="master" -cfg="release"
Note that only master branch can create a Nuget package when it is built.
Domain Driven Design principles are used in this problem. Therefore given name is BasketContext to this solution. Context means that, this is a bounded context which provides a solution to Basket domain.
BasketContext has an API to interact with.
API uses;
- Swagger for documentation
- EntityFrameworkCore in-memory to database
- MediatR for emphasizing and handling for the commands. Also this brings that initial implementation of CQRS with seperating command side from the query side
- NSwag for auto client API creation
- FluentValidation for request validation
There is a framework project in the solution. That provides an infrastructure to modeling the domain. That means that, for instance if we need to create an event-aware domain model we need to take AggregateRoot as a base class of our domain model. Like as Basket : AggregateRoot<Guid>. Framework project simply provides a base solution for registering domain events. Also this is same for Entity, the lense we look for the Domain Driven Design needs that BasketItem must be entity. Therefore BasketItem should be an Entity like BasketItem : Entity<Guid>.
There is a command handler which named BasketCommandHandler and it handles use cases of context.
Another part is domain events. Domain events are published from Basket aggregate root and they are handled by BasketEventHandler for informing other bounded contexts or creating some projections.
Event Storming is used for modeling the domain. To help this out WebEventStorming is used.
There are 3 parts of testing. Two of them are integration testings the other one is unit test.
BasketContext.Api.IntegrationTests uses:
- Microsoft.AspNetCore.TestHost for controller tests
BasketContext.Domain.IntegrationTests uses:
- EntityFrameworkCore in-memory database as application itself does.
BasketContext.Domain.Tests uses:
- For testing the behaviors of
Basketaggregate root. Ensuring the behaviors of aggregate root can be made with ensuring the domain events that in consequence of use-cases which needed to be modeled at the first place. This need is implemented with an extension:
aggregate.ShouldPublishDomainEvents(basketCreatedEvent);
JWT Bearer token is used for this purpose. There is a TokenController that provides token for BasketController requests.
Client API is generated by NSwag. There is a BasketContext.nswag file in solution directory. When it needs to re-generate the client API then execute:
nswag run /runtime:NetCore20
It provides newly generated API codes and BasketClient.cs file according to your contract changes of controller. After that build pipeline can handle the nuget publishing.
- Basket doesn’t know about User, Basket should be found by its own unique identifier, not the User's.
- All Ids are trusted. Client can provide BasketId and ItemId. Assumed that there are some Anti-Corruption layers to achieve this trustworthiness.




