Trying to implement clean architecture in a new project, but with some restrictions: I want to loose dependencies as much as possible.
Basic:
Solution has several projects:
WebApi
UseCases (referenced by WebApi, implements business logic)
Gateway (referenced by UseCases, provides repository interfaces to UseCases)
DataAccess.EfCore (referenced by Gateway, implements access to MSSQL)
Domain.Core (Domain model is here)
What is desired and what problems are solved and still here:
- All projects has IHostingStartup implementations where they are configure themselves: UseCases registering some behaviours, Gateway - it's interfaces, EfCore - configuring DbContext and registering it.
Looks fine. Almost. There two architectural problems for now:
Configuring ASP.NET Core Identity. Usually it is done in the WebApi project, but in this case I have to reference EfCore project to be able to write this:
services.AddIdentity<User, Role>().AddEntityFrameworkStores<MyDbContext>();
class "MyDbContext" is declared in EfCore project, so this one line has settings from two worlds:
AddIdentity() : WebApi world
AddEntityFrameworkStores() : DataAccess world (because "MyDbContext" class is belong to it)
If I put Identity configuration into the DataAccess - then I have to configure such things as Identity lockout settings and Login/AccessDenied pages in the DataAccess what is also wrong and what should not be done there.
Is it possible to split the configuration, so DataAccess.EfCore will just register DbContext store for identity and WebApi is configuring lockouts and other stuff?
I'm using user secrets to store connection strings. How to pass it to the IHostingStartup implementation to configure DbContext? Method signature is allowing to work with IWebHostBuilder builder only, so I'm stuck here also.
Any ideas, help, experience?
UPD:
Or, almost forgot about 3rd problem:
When I'm running the app at first time - I want to seed some data into the DB. And the problem here is to seed the IdentityUser entities as they should be added through UserService (password hashing etc), but at the same time I want to do it in the DataAccess.EfCore project: I'm using FluentAPI to configure the models and seeding the data with "HasData" method. So any idea here would also be appreciated!
if you refer with "Clean Architecture" to Uncle Bobs article and book (https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) then your project setup needs a little cleanup.
In Clean Architecture Gateways depend on use cases, not the other way round. One key principle in this architecture is "inversion of control": you define interfaces in the inner circles and keep the implementations details (like EF, DbContext and other frameworks) in the outer circles.
The wiring of the interfaces and implementations happens in the "main component" - which in asp.net core would be the startup class.
More details on implementing Clean Architecture (e.g. in Asp.Net) you can find in my blog series: http://www.plainionist.net/Implementing-Clean-Architecture/
Related
I am learning how to implement onion architecture using .Net core API. I understand that the focus of Onion architecture is more on flow of dependencies rather on how the layers interact with each other. But I found that domain entities are still accessible in the presentation layer (API layer). This is because the presentation layer has a project dependency on the application layer and the application layer depends on the domain layer where domain entities are defined as public. We cannot define it as internal because the entities will not be accessible by the application layer. This way anyone in the team mistakenly access the domain entities instead of the corresponding DTO.
One solution proposed on Udemy Q&A that we can define domain entities as internal and we can specify the assemblies that can access these internal entities by using the below build configuration
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>NameOfProjectToGainAccess</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
But this is causing error in the MyApplicationDbContext file in the Infrastructure project. The compiler flags error in the below code
public DbSet<MyEntity> MyEntity {get; set;}
It says that the DbSet is less accessible than the public property MyEntity.
I get the similar error in the repository contract definition as base interface is less accessible.
public interface IMyEntityRepository : IGenericRepository<MyEntity>
I want domain entities should not be accessible in the presentation/API layer. This layer should only access DTOs.
Please advise if there is way to do this.
One option to address the access problem is to package by component. This technique is described by Simon Brown in the clean architecture book, chapter "the missing chapter", page 318.
The main idea is to use the access modifiers to ensure the architectural constraints. Simon Brown puts all the "use case" related stuff in one package. He can then reduce the access modifiers for all classes and interfaces within the component to hide them from the outside. This would also apply to the entities, even they are not explicitly shown in the diagram.
I guess (I'm a Java programmer) that in C# you would use assemblies to implement the package by component, because the access modifier internal is used to control access to classes within the same assembly. I hope that this is correct.
Questions I anserwed that might also help:
Should layers be visualized in the code structure?
Who must create services with package modifier if I implement architecture from "Clean Architecture" book
Another option is to use tools that scan your source code to ensure architectural constraints or code reviews. Finally I guess we have to ensure it using code reviews and tools, because even with the package by component approach programmers can change the source code and replace the internal access modifier with public. They usually prefer the fast implementation approach over the long lasting and you often have to do a lot of effort to convince them.
If you have your base repository i.e. IGenericRepository<MyEntity> internal, then you can't have the extended one public, your IMyEntityRepository, will also be internal to fix your compiler issue, and same goes for your DbSet, the class is internal, how can you make the fields public? Nobody can reach the class, hence it is less accessible than the DbSet itself.
Edit comments space ran out so here...
Move your Dbmodels inside your Persistence project i.e. the project that only has your DbContext and Entity Configs, now your infrastructure project depends on persistence, which only needs the DbModels and not the DTOs(since DTOs are in Core Project, DbContext don't have access to it either way). Now your consumer e.g. WebApi/WPF don't have DbModels, but only Models(DTOs/ViewModels).
To Sum it up:
Infrastructure depends on Persistence and Core.
Core has all the Models(DTOs/ViewModels), repositories and/or Commands/Queries(in case of mediator pattern), custom exceptions, or even fluent assertion classes.
Infrastructure implements Core repositories, Commands/Queries(in case of mediator pattern), and repositories are designed in a way to only return Models from the core.
Persistence project has the DbContext, EntityConfigurations, and the DBModels(entities).
Nothing depends on Infrastructure(basically the whole point of following this structure lol), Consumer(Web Api/WPF) and Infrastructure depend on Core, and persistence only need DBModels and/or efcore so it depends on nothing, infrastructure depends on Core and Persistence.
Now do some creative coding to register all of this in your DI ;)
Even though access modifiers (internal keyword) and proper packaging already help with dependency governance, specific tools usually give greater flexibility for describing particular rules.
One commonly used tool to analyze .Net code is NDepend.
Another helpful tool to implement dependency governance is NsDepCop.
And of course you can also use Roslyn to develop your own code analyzers and integrate those into your build pipeline. An example analyzer checking for "invalid" assembly references you can find here: http://www.plainionist.net/Dependency-Governance-DotNet/
I'm creating application with layered architecture. I have separate
+ 'DataModel' project with only model classes
+ 'BusinessLogic' project that containing my business
+ 'Core' project for run Business from ui
+ 'ViewModel' project
+ 'Web' project with asp.net core application.
My goal was to separate these projects so that Web project knows nothing about DataModel so the Web project should just reference Core and ViewModel. Everything was great until I configured Asp.Net Identity - in order to configure authorization I had to reference DataModel project which I had wanted to avoid. Is it possible to achieve my goal, and (if so) how to do it.
Note:
I'm using this how to separate model library when using asp.net identity for writing my question and i don't find accepted answer as my answer!
When you create a website that uses Identity directly, you must provide it with various Identity "stores": UserStore<TUser>, RoleStore<TRole>, etc. The default and easiest approach is to use Entity Framework Core as the backing for the store(s), and Identity comes with built-in stores to work with EF Core. However, using that requires access to the context, which means you then will need a dependency on your data layer. There is no way around that when using AddEntityFrameworkStores<TContext>.
If you want to keep your data layer abstracted, then you will need to either 1) use a centralized identity provider, such as IdentityServer or 2) create custom stores.
IdentityServer, for example, supports using both EF and Identity as a backing. That does mean it will need a dependency on your data layer, but IdentityServer would be exist in a separate project. Your actual website would handle auth via IdentityServer endpoints, and therefore would have no dependency on your data layer. In fact, it doesn't even know or care that you're using Identity at all at that point.
Creating custom stores will be a bit more difficult, obviously, and unless you provide an true abstraction layer, you'll still ultimately end up with a dependency on your data layer. That might be something like a microservice(s), where the store will actually make HTTP requests to the service to get the objects it needs, instead of making database queries directly. The microservices, then, will hold the data dependency.
One thing you might not be considering in this is that the dependency is there even without a direct reference. For example, if your Core project uses stuff from your DataModel project, and then your Web project uses stuff from your Core project, your web project has an implicit dependency on your DataModel project. If you look at the bin folder after building, for example, you're see a DLL for your DataModel project and even one for EF Core there, despite not explictly using either one in your Web project. In this case, using separate projects helps only to division the logic in perhaps a more succinct and understandable way, but it does not serve to actually abstract any dependencies.
I am following the Microsoft Architecture Guide for creating an ASP.NET Core Web Application.
The guide implements the clean architecture pattern which is pretty straight forward.
If you look at the sample project which is using the clean architecture pattern you will see that there is an Infrastructure/Identity folder that contains the ApplicationUser.cs class.
My issue:
I am using Entity Framework and one of my Business Entities in the ApplicationCore class library needs to contain a list of ApplicationUser. The ApplicationCore library shouldn't be referencing any other projects. It contains all of the Interfaces and Business Entities. How can I keep the ApplicationUser class in my Infrastructure/Identity project and still use it in one of my business entities in the ApplicationCore project without breaking the rules.
I know one solution is to not store the ApplicationUser entity in my Infrastructure project. However, I feel like it should be there since it will always rely on Identity as it implements IdentityUser.
User is an entity and it should be in Core layer.
But you shouldn't use ApplicationUser : IdentityUser in the Core layer because it's tied up to the ASP.NET Identity. The Core layer should not know what technologies are going to implement the domain.
What if tomorrow you want to use another library for user management? That's not the Core layer's concern.
What you can do is to use an interface or base User class in the Core layer and let the Infrastructure layer be worried about the library choice decision.
In Clean Architecture:
Application Core Types
• Entities (business model classes that are persisted) and Aggregates
• Interfaces
• Services
• DTOs
• Specifications
• Exceptions
Infrastructure Types
• EF Core types (DbContext, Migrations)
• Data access implementation types (Repositories)
• Infrastructure-specific services (FileLogger, SmtpNotifier, etc.)
So the ApplicationUser.cs is an entity, it shouls be in Application Core
This is my own problem as well and it seems opinion based somehow. I end up that if you are depending on any package that has a DbContext specified inside it, so you will reference this package in your Core project.
For example, I am using AspCore.Identity and IdentityServer4 and I have many DbContexts for that but let's say two for now:
ConfigurationDbContext and IdentityDbContext and those two contexts control two entities (just for making things easier) Client (The OAuth2 Client) and IdentityUser So now and I already have all of that as Infrastructure but now I want to have my own Core Entities ApplicationUser and ApplcationClient so how can I put those in my Core without letting them inherited their parents so I can query against them, save them or retrieve them from any source.
I don't know exactly the perfect answer for that but I end up putting those entities in the Core and reference the NuGet packages in my core which obviously not follow the clean architecture roles but I couldn't find a better solution than that.
I have recently done some analysis of ASP.Net Boilerplate (https://aspnetboilerplate.com). I have noticed that the domain layer (MyProject.Core) has folders for the following (these are created by default):
Authorization
Confirguration
Editions
Features
Identity
Localization
MultiTenancy
etc
Why would you put all of this in the Domain Layer of an application? From what I can see; I believe most of this code should be found in the Application Layer (which could also be the service layer).
Good question, if you just look at the folder names. But I suppose you haven't investigated the source code in the folders much.
First of all, I don't say it's the best solution architecture. We are constantly improving it and we may have faults. Notice that our approach is a mix of best practices & pragmatic approach. I will try to explain it briefly.
You are talking about this project: https://github.com/aspnetboilerplate/module-zero-core-template/tree/master/aspnet-core/src/AbpCompanyName.AbpProjectName.Core So, let's investigate the folders:
Localization
It does not include any localization logic (it's done in framework level, in ABP. Thus, it's in infrastructure layer). It just defines localization texts.
While normally it can be easily moved to web layer (no direct dependency in Core project), we put it in the Core layer since we think it may be needed in another application too. Think that you have a Windows Service has only Reference to the .Core project and want to use localization texts, say to send email to a user in his own language. Notice that Windows Service should not have a reference to Web layer normally. So, we have a pragmatic approach here. We could add localization to another dll project, but that would make the solution more complicated.
Authorization
Mainly includes User, Role.. entities and UserManager and RoleManager domain classes. Similar to localization, it does not include actual authorization logic. It also includes some other classes but they do not make much. We thought putting these here would help us if we have more application layers. As you know every application can have it's own application layer as a best practice.
Confirguration
AppConfigurations is here to share 'configuration reading' code between different apps (Migrator and Web app). Again, this could be inside another "Shared Utils" library. But we wanted to keep solution structure balanced, so it reflects major layer and structures yet is not so complicated for intermediate level developers.
Editions
Just includes EditionManager class which is a domain service for Edition management.
Features
Just includes FeatureValueStore which is a repository-like adapter class. See it's code, it's already empty.
MultiTenancy
Includes Tenant entity and TenantManager class which are already parts of domain layer. Again, nothing here includes infrastructure-related multi-tenancy features (like data filtering or determining current tenant).
... and so on...
So, do not just see names and have idea, please check the project deeper. Some code can be moved to upper layers or an utils library, but I think general structure is good to start a DDD architected application.
What you see it is called Module Zero, it aims to implements all fundamental concepts of ASP.NET Boilerplate framework such as tenant management (multi-tenancy), role management, user management, session, authorization (permission management), setting management, language management, audit logging and so on.
Module-Zero defines entities and implements domain logic (domain layer) because it is part of the configuration context of your system.
I am setting up a project structure for an upcoming internal application trialling the Onion Architecture proposed by Palermo (http://jeffreypalermo.com/blog/the-onion-architecture-part-3/).
I have followed his guidelines, however I need some verification on the structure of the project so far.
Before the diagrams, the questions:
I think the References are all correct (set up as per the diagram where an arrow means 'has a reference to')
but some verification would be good.
What should I put in my dependency resolution layer? Is this where
Helpers go? This has a reference to all other projects?
How do the web services & UI, communicate with the DAL? (Through the core? How?)
What should go where? [Broad question I know...]
The simplified conceptual diagram is as follows (Folders represent namespaces):
I think the References are all correct (set up as per the diagram where an arrow means 'has a reference to') but some verification would be good.
1 It looks OK but I am not sure it's a good idea to insert dependency resolution into the diagram.
What should I put in my dependency resolution layer? Is this where Helpers go? This has a reference to all other projects?
2 I believe dependency injection stuff would be here.
How do the web services & UI, communicate with the DAL? (Through the core? How?)
3 It is core according to Palermo's diagram. In core, you will have repositories talking to DAL and domain models, and services (not web services) dealing with repositories and domain models. And UI/web services will mainly talk to services.
What should go where? [Broad question I know...]
4 Again, I think the answer is in Palermo's diagram. But in my opinion, organizing projects can be different and trivial when there is full understanding of the architecture.
Onion architecture became obvious to me once I understood DDD and necessary design patterns such as MVC, Dependency injection, Repository/Service, ORM.
Yes they are, expect for the Dependency Resolution. These dependencies should be the other way around.
As the name (and the corrected references) implies it's purpose is to host
some kind of IoC Container solution. It is no place for Helper
classes, expect helper classes for resolution purposes.
The Core defines Interfaces for DAL or Domain Services. DAL and
WebServices implements these interfaces. Inside the UI you would use
the DAL or Service implementations through the defined interfaces.
the correct implementation would be resolved through the help of the
Dependency Resolution component (have a look at the concept of
"Inversion Of Control" or "Dependency Injection").
As described in 3. the main thing is, that in Core you put the interfaces that will be implemented inside DAL and Web Services. And in Core you would implement your real business model. this model can make use of the DAL and the Web Services via the defined interfaces (with the help of the Dependency Resolution component).