Onion Architecture : Can UI depend on Domain - asp.net-mvc

I am making an ASP.NET MVC website with an Onion architecture. I have implemented a repository pattern and am now creating a Controller method in my project. This is my architecture:
Domain : Entities / Domain Interfaces
Repository : Generic repository (for now) using Entity Framework Code First
Service : Generic Service that calls the Repository
MVC
Now in my MVC project I need to access repository but according to Jeffrey Palermo, MVC is dependant from Service and Domain, but nothing is said of Repository.
Can i make my UI dependant of Repository?
I cannot do anything without the dependency right now, because Service creation depends on Repository. I have tried modifying Startup.cs to not directly use Repository objects in my Controllers, but it still means I need to add a reference to Repository (see http://dotnetliberty.com/index.php/2015/10/15/asp-net-5-mvc6-dependency-injection-in-6-steps/ )

At this point MVC (UI) is the composition root, which would need to know all the layers in order to register them with the DI container.
The start up would either refer to the implementations directly when registering them or indirectly via extension methods exposed from that layer. Either way the composition root needs to reference all lower layers if they are to be added to DI container.
The controllers should also be dependent on abstractions from lower layers and not concretions.
If injecting repositories directly into controllers then I suggest reviewing the design as that may indicate mixing of responsibilities.

Related

Configuring MassTransit in Onion Architecture with ASP.NET MVC and Ninject

I am currently setting up a simple MVC application that is structured as an Onion Architecture. For simplicity's sake, assume that I have the following projects (disregarding the business and database layers, at the moment):
Sample.Web - This is the ASP.NET MVC Application
Sample.Application - This contains the application services.
Sample.Infrastructure - This contains the infrastructure services.
For now, I am using Ninject (although that will likely change). So, with Ninject MVC, I am registering the Application and Infrastructure services at startup, using the Sample.Web to act as the composition root. Application services from Sample.Application are injected into the controllers, and that is straightforward enough and working well.
Where I am having issues, though, is determining how to properly initialize MassTransit, in the equation. Ideally, I want to have a generic interface to wrap the ConsumeContext instance and allow for me to set up the events. I do not seem to be able to fully set up the instance from within Sample.Infrastructure, as the infrastructure does not/should not know what the events are. I would assume that the consumer classes should exist in Sample.Application, and I do not think that the infrastructure should have a dependency on knowing the consumers.
On startup, System.Web will load the NinjectModule from each System.Application and System.Infrastructure. Does that mean that System.Web should have explicit knowledge of the consumer classes, so that it can configure the IBusControl instance, or is there a more elegant solution?
Right now, the path that I think I am going down is that Sample.Web will load the NinjectModule instances, as it does, and then I will configure the ConsumeContext from Application_Start, after I have explicitly loaded the consumers. However, that would mean that I would have to rebuild/redeploy Sample.Web if I ever add consumers, which is less than ideal and is the root of my concerns. Assuming that consumers are defined within Sample.Application, and all event publications and subscriptions exist within Sample.Application, having to touch either Sample.Web or Sample.Infrastructure to add a consumer is code smell.
Many thanks, in advance.
Edit
As always, after hitting submit, something else comes to mind. I think that one possible solution may be to have Sample.Web as Sample.Application for the known endpoints. Since all events will be published and subscribed from Sample.Application, it would make some sense to have Sample.Web create the actual instance in Sample.Infrastructure and compose the endpoints from what it learns from Sample.Application.
Am definitely open to other solutions, though.

Project Structure using CastleWindsor

I have a solution which is made up of several projects such as: DataLayer (Contains the EntityFramework), UnitTests, WebForms(Contains the MVP), CommonClasses (Contains common services classes).
Would you implement a single container for all of these projects, which is in a separate class-library application?
Or would you simply have a separate Windsor setup to handle dependencies within each one alone, but what if there is inner dependency between the individual projects.
Or is it a one for all Windsor Setup, which is inside the main project (The Startup project) to handle all dependencies?
Thanks.
Would you implement a single container for all of these projects
Since classes depend on classes from other assemblies (for instance your presenter would depend on a repository or a service from your business layer), your object graphs (a graph of objects that depend on each other) need to be built by one single container. So yes, you need one single container for all projects.
which is in a separate class-library application?
No. You should usually place this code in the startup path of your application, which -in your case- is the Web Forms project.
but what if there is inner dependency between the individual projects.
There will always be dependencies between your projects. Your web application wouldn't be very useful if it didn't call any business logic or didn't connect to the database.
Take a look at this Stackoverflow question (and answers) for more information about this subject. Here is an answer on the Simple Injector forum that talks about this as well. It's about Simple Injector and Onion architecture, but you'll find the answer informative and applicable to your situation.

Dependency Inject for models

I'm sure someone has asked this before, but I'm struggling to find where.
I'm using Ninject to remove dependencies from my controllers, along with a repository design pattern.
As I understand it, one of the benefits of this approach is that I can easily whip apart my repositories and domain entities and use another assembly should I so wish. Consequently I've kept my domain entities and repositories in external assemblies and can mock all my dependencies from interfaces.
It seems that while I can use interfaces to refer to my domain entities in most places I must use references to my concrete classes when it comes to model binding. I've read that this is to do with serialization which I understand, but is the only way to avoid referring to domain entities to create separate models?
Anything I can do with Custom Model Binding?
A bit of background: I'm an experienced ASP.net developer, but new to MVC.
View Models should be plain data containers with no logic and therefore shouldn't have any dependencies at all. Instead inject the repositories to your controller and have it assign the required data from the repository to the appropriate property of your view model.
The major advantage of using a dependency injection framework is IoC (Inversion of Control):
loosely coupling
more flexibility
easier testing
So what one usually does is to inject repositories through their interfaces like
public class MyController : Controller
{
private IPersonRepository personRepo;
public MyController(IPersonRepository personRepo)
{
this.personRepo = personRepo;
}
...
}
During testing this allows to easily inject my mock repository which returns exactly those values I want to test.
Injecting domain entities doesn't make that much sense as they are more tightly linked with the functionality in the specific class/controller and thus abstracting them further would just be an overhead rather than being a benefit. Instead, if you want to decouple your actual entity model from the controller you might take a look at the MVVM pattern, creating specialized "ViewModels".
Just think in terms of testability of your controller: "What would I want to mock out to unit test it?"
DB accesses -> the repository
External dependencies -> other BL classes, WS calls etc.
I wouldn't include domain entities here as they're normally just a data container.
Some more details would help. A bit of code perhaps?
To start with, you should avoid injecting dependencies into domain entities, but rather use domain services.
Some more info here.
Edit 001:
I think we should clarify our terminology.
There is the domain layer with all you domain entities, e.g. product, category etc.
Then there's the Data Layer with your repositories that hydrate your domain entities and then you have a Service Layer with you application services that talks to the data layer.
Finally you have a presentation layer with your views and controllers. The Controllers talk to you Aplication Service Layer. So a Product Controller talks to a Catalogue Service (e.g. GetProductBySku). The CatalogueService will have one or more repositories injected into its constructor (IProductRepository, ICategoryRepository etc.).
It's quite common in asp.net mvc to have ViewModels too. Put the ViewModels in your Application Service Layer.
So I'm not sure what you mean when you say "models" and "domain enntities" but I hope that clears up the terminology.

structureMap in a multiTier application

I have a asp.net mvc app having three layers
1. dataAccess layer (class library)
2. business layer (class library)
3. web layer (asp.net mvc project)
and also have a domain project (class library for poco)
I am doing the structureMap mappings in my Application_start of the MVC project, but to map the TYPES in dataAccesslayer (for eg. personRepository with IPersonReository) i need the reference of the DAL in my web layer, which i dont think is correct.
What are your suggestions
Thanks
As a pragmatic approach what you are doing may be okay if you can keep the discipline and never use the DAL from the Web Layer. However, once the reference is there, this can be surprisingly hard to do - and what about other developers on the project?
A better option is to split the web layer into two layers:
The Application Bootstrapping layer. This is the real web project, but apart from bootstrapping the container and implementing the Views (.aspx pages) there should be nothing else. This is what we call a Humble Executable. It will contain references to all other projects in order to compose them (via the DI container), but otherwise it doesn't do anything. We call this the Register Resolve Release pattern.
An Application Model layer. This project would contain all of your application logic (as opposed to domain logic): View Models and Controllers. It needs no reference to the DAL, but will get implementations injected into it by the DI container.
There is nothing wrong in having a reference to the DAL in your web project as long as you are not directly making calls to that assembly. But if you are uncomfortable with that approach, you can use a Registry in your Business layer and there register types for the DAL. Since the Web layer would anyway need to have a reference to the Business layer, you can use that registry from the Business layer in Web's App start
Here is some sample code
The registry class in your Bsns layer
public class BusinessRegistry:Registry
{
public BusinessRegistry()
{
For<IDALInterface1>().Use<DALImpl1>();
}
}
and in the Application start method
var container = new Container(x => x.AddRegistry(new BusinessRegistry()));
Like others have said, a reference to your DAL project is not the end of the world unless you use it incorrectly (or maybe at all in your web project). I prefer to have an Infrastructure project contains all things related to cross-cutting concerns. Among other things, this includes my Logging and IoC Container.

ASP.NET MVC Three Tier - what's everyone else doing?

When I start work on a new web application I tend to reach for the same tried & tested architecture of ASP.NET MVC, BLL (consisting of a set of services that contain all business logic) and a DAL (consisting of a set of repositories that facilitate the unit of work pattern over something like EF/*Linq to SQL*).
The controllers talk only to services, the services only to repositories and other services. At the service layer are where models are defined and these are used as input/output to/from the controllers.
My question is: what are others doing? I'm interested in knowing if people are doing anything different in the context of an ASP.NET MVC web application. For instance, there are concepts like CQRS and Domain Events. Is anyone using these to solve a problem with the method I've described above?
This question is mainly a source of attempting to discover what I don't know I don't know. I hope it's not too vague, but I think it's important to see what others are doing to evaluate your own methods.
We're basically doing what you're doing, except that we consider our repository interfaces to be services (they are defined in the business layer), and therefore our controllers often access them directly. An IoC container takes care of injecting the correct repository implementation via constructor injection. So the data layer depends on the business layer, and is in charge of implementing the repositories, while the business layer just assumes that all the repositories it has defined will be available at runtime.
We've further divided our product up into different modules of functionality. Some of the modules depend on one another (for example, everything depends on our core functionality, and most of the other modules depend on the web portal module), but keeping them in separate dlls helps us to avoid making these modules be too tightly coupled. The system can therefore only load the DLLs for the modules that a given client has paid for. We plan to use an event bus with events defined in the core module to allow the modules to communicate via a publish/subscribe model.
I am using CQRS with MVC. Its nice. You still use the MVC pattern, but in the controller I use the command pattern for the write, and just pure NHibernate Linq for the read... also some SolrNet for the read. :-)

Resources