16
votes

I have made a three-layer application with refrences going as described in this answer:

DAL with Repositories -> BLL with services and IRepository <- Asp.net mvc-app

To get this running with dependency injection I see a few options:
1. Add a reference to DAL from the web-app to be able to setup bindings on application start.
2. Use a container with xml-configuration
(3. Use reflection to load the dal-assembly and find types)

Option 1. is easy and also makes the DAL.dll be copied to bin but then I suddenly reintroduce the reference I worked so hard to get rid of. The repositories can now be accessed directly. Option 2 and 3 seems unnecessarily complex.

Is there no other way?

5

5 Answers

17
votes

Split up the ASP.NET MVC application in two:

  • One part is your original ASP.NET MVC application, but without any logic whatsover. Just keep the Composition Root and your Views (.aspx, etc.) in this project. Since this is the Composition Root, you can have references to all your other projects. However, since all logic would have been extracted, this is now a Humble Object, so it's okay to have all the references at this level.
  • Extract all the logic (Controllers, etc.) into an Application Model project, which would just be a normal library project (.dll) that references the ASP.NET MVC binaries. This project would need to reference the BLL to get at the interfaces, but that's okay. However, both the Application Model and the BLL are effectively shielded from the DAL.

The resulting layering would look like this:

  • ASP.NET MVC application
  • Application Model
  • BLL
  • DAL
8
votes

Mark Seemann's answer gave me the idea for this variant:

DAL with Repositories -> BLL with services and IRepository <- Asp.net mvc-app
^------------------------^--------- Composition Root <-------ยด

This is meant to illustrate that instead of letting the Web project reference the DAL it references a separate Composition Root-project that references both DAL and BLL. The composition-root-project has a single class with one method that define the bindings. It gives these additional benefits:

  • Only three layers. Four layers would be a tough sell in the team.
  • Loose coupling is ensured. It is not possible to access the DAL from view-code.
  • Better tool support. Controllers remain at the standard location so "Add Controller" is accessible on the context-menu and missing views are highlighted in the controller-code. Also there is no need to configure or write a custom controller factory.

I don't see any big drawbacks.

3
votes

Just go with Option 1.

Just because you have a reference to the assembly doesn't mean your breaking the SoC.

The Web Project still knows nothing about the underlying implementations, only the interface.

The Web Project is the "aggregator" of the below layers therefore it makes sense it should know about them in order to configure them.

2
votes

I split the MVC project in two roughly as described in Mark Seemans Answer.

The MVCApplication is a humble object and requires references to everything, but doesn't have any of the MVC code, apart from global.asax (which it needs) and web.config (which it seems to want).

The MvcUI project only references interfaces and uses dependency injection.

If you put both the projects (.csproj files) in the same directory then the Content, Controllers, Models, Scripts and Views folders are all actually in the same place, so all the tooling works.

The picture of the solution below shows the idea.

MVC Composition Root Solution Explorer

The directory structure looks something like this

MVC Composition Root Directory Structure

And you end up with a Dependency graph like this

MVC Composition Root Dependency Graph

0
votes

Recently i was following the same thing and figured about the MEF (Managed Extensibility Framework). With the help of MEF and reflection you can get rid of that DAL/Unit of work reference from your composition root and you don't need to have 2 mvc projects as discussed above.