Project structure with own Nuget packages
We are building a project containing of several MicroServices from scratch and thought of how to organize it.
For each microservice we set up an own repository. Which results in the following repo structure:
- MicroService1
- MicroService2
- MicroServiceN
- Global (for shared componenents)
- Documentation (where wiki markdown files and images are stored)
Repositories
Documentation
The documentation is done in the azure devops wiki. Files created and images uploaded are stored automatically in the Documentation
repository.
Global
The global
repository is the repo where we implement componenents which are used by all MicroServices.
MicroServices
For each MicroService there is an own repository. All MicroServices have the same project structure, because they are created from an custom Visual Studio Project Template.
- Service.Web
- Service.Dal
- Service.Entities
- Service.Client (for calling this microservice)
- Service.UnitTests
- Service.IntegrationTests
Builds and Packages
For every repository we have a build pipeline which builds the solution and runs the UnitTests. The pipeline creates package(s), too.
Global
The global repository has build pipeline, too. Packages from global repository are:
- Global.Entities (shared entities)
- Global.System
- Global.Client.System (Base classes for Service.Client project)
MicroService
Then the pipeline creates 2 nuget packages, Service.Entities
and Service.Client
. Those will be published to the azure devops nuget feed.
Using the packages
We thought about how to use packages in development and on devops build.
We wanted to make sure, that you can work an your MicroService without bothering with code from for example the global packages. But still have the possibility to develop directly on the global projects directly in the MicroService solution.
How we did this?
To accomplish this we added the global
repository as a submodule to the MicroService repository.
We have two solutions, one which uses the packages and one which can switch between packages and directly building against the global
projects via the submodule.
Solution with global Submodule
As I described above we have a solution for working with the global
code and building directly against it. This is done by adding a new build configuration
to the WithGlobal
solution.
Here is an example of the project xml with:
<ItemGroup Condition="'$(Configuration)' == 'Debug_Global'">
<ProjectReference Include="..\..\Global_System\src\Service.Entities\Service.Entities.csproj" />
<ProjectReference Include="..\..\Global_System\src\Service.Services.System\Service.Services.System.csproj" />
<ProjectReference Include="..\..\Global_System\src\Service.Client.System\Service.Client.System.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' != 'Debug_Global'">
<PackageReference Include="Service.Entities" Version="1.0.*" />
<PackageReference Include="Service.Services.System" Version="1.0.*" />
<PackageReference Include="Service.Client.System" Version="1.0.*" />
</ItemGroup>
You can see the switch between project reference and nuget package. If you are using the normal solution, there is no such build cfg and the Global_System
projects aren't in the solution at all.
The WithGlobal
solution has the Global_System
projects referenced and has the related build config. You can easily switch between the build/debug with the packages or the projects.
Hint: Maybe you recognized the *
in the version number. This has the benefit, that the project uses the newest package. You don't need to update the packages every time a new package was build.
Recap
The things described above makes working with packages easy possible. The benefit here is, you can directly work with the global
projects. For example editing files, debugging and so on. Edited files can be checked in to the submodule, which then directly triggers an azure devops pipeline and creates a new package.