DAL -> BLL <- GUI + composition root. How to setup DI-bindings?
Asked Answered
G

5

16

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?

Gomulka answered 11/3, 2011 at 0:11 Comment(0)
G
8

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.

Gomulka answered 11/3, 2011 at 12:28 Comment(5)
Can you provide some step by steps in creating the root project and what specifically gets moved where, what references are made where??Playtime
I create a new library-project and add references to DAL, BLL and the di-framework of choice. I use Ninject, which is installed with NuGet. That creates some code in Global.asax.cs and a todo-comment about configuring bindings. However the DAL is not referenced there. Instead I call a method in composite root, pass the kernel, and setup the bindings there. Everything else is as usual. (Ninject is not referenced in BLL nor DAL, ordinary constructor-injection is used.)Gomulka
You're referencing Ninject in the MVC project, not the library-project? That part is vague.Playtime
Yes, ninject is referenced in the the library-project. So I use NuGet to add ninject in the mvc-project then add a reference to the ninject-dll from library project. (Are there other recommendations if several projects are using the same package?)Gomulka
This looks like a good plan, but it still ends up with the MVC application having a dependency to the Data Access Layer. It's a shame that there isn't a better way. Mark's answer above gets round that but has other problems, such as the tooling, and even then the views are still in the composition root. I was surprised that the MVC archictecture couldn't handle this, being as it is fairly new and was designed to be IOC friendly.Steelman
E
17

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
Equanimous answered 11/3, 2011 at 8:43 Comment(6)
Thanks, I tried to do this, but did not find a straightforward way to move controllers to another project. I ended up with a slightly different structure described in a separate answer.Gomulka
A Controller is just a class that implements IController (or derives from Controller). You can define a Controller in any project simply by referencing the appropriate ASP.NET MVC assemblies.Equanimous
I've tried the layering described in my answer and it worked well. Still I'm unsure about accepting my own answer over one by the author of the book.Gomulka
It's your question, so you know best what works for you. Here on SO, it's perfectly OK to accept your own answer as the answer.Equanimous
@MarkSeemann I am also unable to achieve getting this root concept to work. Better instruction (step-by-step) is definitely required and would help all of us struggling with successfully implementing a correct DI/IoC strategy. I have your book, read it a few times and keep it as a reference. But still cannot implement the root using ninject and mvc3.Playtime
What seems to be the problem?Equanimous
G
8

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.

Gomulka answered 11/3, 2011 at 12:28 Comment(5)
Can you provide some step by steps in creating the root project and what specifically gets moved where, what references are made where??Playtime
I create a new library-project and add references to DAL, BLL and the di-framework of choice. I use Ninject, which is installed with NuGet. That creates some code in Global.asax.cs and a todo-comment about configuring bindings. However the DAL is not referenced there. Instead I call a method in composite root, pass the kernel, and setup the bindings there. Everything else is as usual. (Ninject is not referenced in BLL nor DAL, ordinary constructor-injection is used.)Gomulka
You're referencing Ninject in the MVC project, not the library-project? That part is vague.Playtime
Yes, ninject is referenced in the the library-project. So I use NuGet to add ninject in the mvc-project then add a reference to the ninject-dll from library project. (Are there other recommendations if several projects are using the same package?)Gomulka
This looks like a good plan, but it still ends up with the MVC application having a dependency to the Data Access Layer. It's a shame that there isn't a better way. Mark's answer above gets round that but has other problems, such as the tooling, and even then the views are still in the composition root. I was surprised that the MVC archictecture couldn't handle this, being as it is fairly new and was designed to be IOC friendly.Steelman
S
3

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.

Seagraves answered 11/3, 2011 at 0:47 Comment(1)
This can work if all members of the team know exactly what they are doing. If that is the case, design knowledge and discipline may be enough to maintain loose coupling. However, if the team looks like that, they might as well just build a 'loosely coupled monolithic' application ;) The main reason to introduce layering is to prevent ourselves from inadvertently introduce tight coupling, which is surprisingly easy to do. Going with option 1 doesn't address that issue.Equanimous
S
2

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

Steelman answered 1/10, 2013 at 16:23 Comment(1)
Thank You Cedd. One thing I want to add is packages.config for each of the projects should be renamed to packages.Reporting.MvcApplication.config and packages.Reporting.MvcUI.config Then there would be no conflict and both projects would work alright.Rella
A
0

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.

Arum answered 14/2, 2016 at 23:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.