In my project I had a controller dependency on IRepositoryProvider among others.
public class HomeController : BaseController
{
public HomeController(ISessionWrapper sessionWrapper,
IRepositoryProvider repositoryProvider,
IApplicationConfiguration applicationConfiguration)
: base(sessionWrapper, repositoryProvider, applicationConfiguration)
{}
...
}
IRepositoryProvider and its implementation live in a BLL layer. Another thing to note is that IRepositoryProvider has some parameters also. These are used to determine which connection strings to use (Environment*5 possible connections).
public RepositoryProvider(string environment, IApplicationConfiguration applicationConfiguration)
{
_applicationConfiguration = applicationConfiguration;
_environment = environment;
}
This all works fine with two layers and this Ninject config.
kernel.Bind<IRepositoryProvider>()
.To<RepositoryProvider>()
.InRequestScope()
.WithConstructorArgument("environment",
context => context.Kernel.Get<ISessionWrapper>().CurrentEnvironment)
.WithConstructorArgument("applicationConfiguration",
context => context.Kernel.Get<IApplicationConfiguration>());
My issue develops when I introduced a service layer. Instead of relying on IRepositoryProvider in my controllers for data access, I want to use the service layer. Ideally then I don't want to reference the BLL layer, and only the Service layer.
public class HomeService : IHomeService
{
public IRepositoryProvider RepositoryProvider { get; private set; }
public HomeService(IRepositoryProvider repositoryProvider)
{
RepositoryProvider = repositoryProvider;
}
...
}
So my question is this: Is it possible for me to not reference both the Service and BLL layers from the MVC project? Or is this whole setup a massive code smell?
Thanks.
UPDATE: I suppose I should have said my ideal references. Web -> Service -> BLL. At the moment Web references both Service and BLL in order for Ninject to resolve everything.
UPDATE 2: Does this seem like a possible solution? How to tell Ninject to bind to an implementation it doesn't have a reference to
This is how I usually architect my MVC projects depending on requirements.
Presentation Layer > Service Layer > Business Layer > Data Access Layer.
Presentation Layer contains : ViewModels, Views, Controllers. (References the Service Layer, Ninject ddl)
Service Layer : WCF. (References the BAL, etc)
Business Layer : Contains what I call Orchestrators and their interfaces (References DAL, Domain)
Data Access Layer: Contains the Repositories and their Interfaces (References Domain)
Domain: Contains the POCO objects
Core : Where I actually install and configure Ninject (References the BAL, DAL, etc)
To Add Ninject to a another Project other than the Presentation Layer:
Add the following to Global.Asasx.cs:
DependencyResolver.SetResolver(new NinjectDependencyResolver());
Then create a new project sucche as core. Install Ninject there and add the following class:
You will need to reference the Ninject dll from the Presentation Layer
public class NinjectDependencyResolver : IDependencyResolver {
private IKernel kernel;
public NinjectDependencyResolver()
{
kernel = new StandardKernel();
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
public IBindingToSyntax<T> Bind<T>()
{
return kernel.Bind<T>();
}
public IKernel Kernel
{
get { return kernel; }
}
private void AddBindings()
{
//Add your Bindings here
}
}
IRepositoryProvider and its implementation live in a BLL layer...
Is it possible for me to not reference both the Service and BLL layers
from the MVC project
With those two statement of yours the answer is NO, it is not possible for you "not" to reference those layers. The best approach of minimizing references is to separate your interfaces from the implementations. You can have for example the following:
The Domain Layer, contains your POCO and interface
Product (a sample class)
IRepository (an interface)
The Service Layer, contains the implementaion of your interfaces
Have a reference to the Domain layer
Implements IRepository (e.g. ProductRepository : IRepository)
Dependency Injection Layer
Is aware of both the Domain and Service layers
The MVC Project
Have a reference to the Domain layer to know about the POCOs and repository signatures
Have a reference to the DI layer but doesn't know how it exactly
works. So you can swap out DI framework later and everything will still work.
You can expand that layer as you see fit. You can insert the BLL layer in between the Domain and Service layer and you don't need reference it anywhere.
Related
I understand the basics of DI in .NET Core, but I'm having trouble figuring out how to use it with multiple projects. Imagine I'm setting up a database context in the Startup class of ASP.NET Core:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<GalleryDb>();
}
I know how to access that context in an API controller:
public class AlbumController : Microsoft.AspNetCore.Mvc.Controller
{
private GalleryDb _ctx;
public AlbumController(GalleryDb ctx)
{
_ctx = ctx;
}
}
But what does one do when there are many layers and functions between the API controller and the data access class? Eventually the code reaches my repository class, which is the one that actually requires the context. It looks like this:
public class AlbumRepository
{
private GalleryDb _ctx;
public AlbumRepository(GalleryDb ctx)
{
_ctx = ctx;
}
public void Save(AlbumEntity entity)
{
// Use _ctx to persist to DB.
}
}
I understand that I could pass the context from the API entry point all the way down, but that seems like an anti-pattern because it means passing it as a parameter through multiple classes and functions that have no interest in it.
Instead, I'd like to do something like this at the point where I invoke the repository class:
public void Save(AlbumEntity album)
{
var ctx = DependencyResolver.GetInstance<GalleryDb>();
var repo = new AlbumRepository(ctx);
repo.Save(album);
}
I believe some DI frameworks have something like this, but I'm trying to figure out how to do it with native .NET Core 2.0. Is this possible? What is the best practice? I found one thread (ASP.NET Core DependencyResolver) talk about using IServiceProvider but the implication was that this was not a desirable solution.
I'm hoping whatever the solution is, I can extend it to apply to other DI classes like ASP.NET Identity's RoleManager and SignInManager.
The key breakthrough chris-pratt helped me understand is that the only way this works is to use DI through all the layers. For example, down in the data layer I get a DB context through DI:
public class AlbumRepository
{
private GalleryDb _ctx;
public AlbumRepository(GalleryDb ctx)
{
_ctx = ctx;
}
}
In the business layer I use DI to get a reference to the data layer:
public class Album
{
private AlbumRepository _repo;
public Album(AlbumRepository repo)
{
_repo = repo;
}
}
Then, in the web layer, I use DI to get a reference to the business layer class:
[Route("api/[controller]")]
public class AlbumController : Microsoft.AspNetCore.Mvc.Controller
{
private Album _album;
public AlbumController (Album album)
{
_album = album;
}
}
By using DI through every layer, the DI system is able to construct all the necessary classes at the point where they are needed.
This requirement has a profound impact on the architecture of an application, and I now realize that my initial hope to tweak an existing, non-DI app to start using DI for the DB context is a major undertaking.
I understand that I could pass the context from the API entry point all the way down, but that seems like an anti-pattern because it means passing it as a parameter through multiple classes and functions that have no interest in it.
No, that's not an anti-pattern. That's how you should do it. However, the bit about "classes and functions that have no interest in it" makes no sense.
Simply, if you're working with something like a repository that wraps a DbContext (a horrible idea, by the way, but we'll put a pin in that), then you shouldn't ever be dealing directly with that DbContext. Instead, you should be injecting your repository into your controllers and then simply let the context be injected into that:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<GalleryDb>();
services.AddScoped<AlbumRepository>();
}
Since ASP.NET Core knows how to inject GalleryDb, and AlbumRepository takes GalleryDb as a constructor param, you simply register AlbumRepository for injection as well (using a "scoped" or request lifetime).
Now, you can inject AlbumRepository the same way you're currently injecting the context:
public class AlbumController : Microsoft.AspNetCore.Mvc.Controller
{
private AlbumRepository _repo;
public AlbumController(AlbumRepository repo)
{
_repo = repo;
}
}
Where this starts to get tricky is when you have many repositories, especially if you have controllers that need to interact with several repositories. Eventually, your code will become a rat's nest of service config and injection boilerplate. However, at that point, you should really be employing the unit of work pattern as well, encapsulating all your repositories in one class that you can inject instead. But wait, oh yeah, that's what DbContext is already. It's a unit of work encapsulating multiple repositories, or DbSets. This is why you shouldn't being using the repository pattern in conjunction with Entity Framework. It's a pointless abstraction that does nothing but add additional and unnecessary entropy to your code.
If you want to abstract DbContext, then you should use something like the service layer pattern (not to be confused with the RPC bull excrement Microsoft refers to as the "service pattern") or the CQRS (Command Query Responsibility Segregation) pattern. The repository pattern is for one thing: abstracting away raw SQL. If you don't have raw SQL, you should not be implementing that pattern.
I am making a website using ASP.NET MVC and an onion architecture. I have the following architecture:
Domain : Entities / Domain Interfaces
Repository : Generic repository (for now) using Entity Framework Code First Approach
Service : Generic Service that calls the Repository
MVC
Now I am trying to create a method in my controller to start testing the methods I have implemented in Repository and Service, and I am having a hard time as to what I am allowed to create in this controller. I want to test a simple Get method in the Repository, but to do that I need GenericService object and GenericRepository object in my controller. To demonstrate what I mean here's a snippet of my GenericRepository(I will skip the interfaces):
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private readonly PrincipalServerContext context;
private DbSet<T> entities;
public Repository(PrincipalServerContext context)
{
this.context = context;
entities = context.Set<T>();
}
}
Now my GenericService:
public class GenericService<T> : IGenericService<T> where T : class
{
private IRepository<T> repository;
public GenericService(IRepository<T> repository)
{
this.repository = repository;
}
public T GetEntity(long id)
{
return repository.Get(id);
}
}
And finally, my question, am I allowed to create these objects in my controller as follows (using my dbcontext called PrincipalServerContext):
public class NavigationController : Controller
{
private IGenericService<DomainModelClassHere> domainService;
private IGenericRepository<DomainModelClassHere> domainRepo;
private PrincipalServerContext context;
public ActionResult MyMethod(){
context = new PrincipalServerContext();
domainRepo = new GenericRepository<DomainModelClassHere>(context);
domainService = new GenericService<DomainModelClassHere>(domainRepo);
if(domainService.GetEntity(1)==null)
return View("UserNotFound");//Just as an example
return View();
}
}
Is this allowed? According to Jeffrey Palermo, UI can depend on Service and Domain so I don't know about the Repository. Technically I am not using methods from repository, but I do need to add a reference to the project.
If I can't then how can I create a new GenericService if I don't have a GenericRepository? Is there a better way to instantiate my objects ?
EDIT I think the answer to my question resides in Startup.cs where I can put something like service.addScoped(typeof(IGenericRepository<>),typeof(GenericRepository<>));
but I 'm not sure about this, any ideas?
I'll answer this on my own if ever someone encounters the same problem. There are configuration methods we can use to create instances of classes when needed. In the Startup.cs file you have to add ConfigureServices(IServiceCollection services) method and inside there are several methods that can be applied to services to create these instances. For example you can use:
services.AddTransient(IGenericRepository, GenericRepository)
What is the difference between services.AddTransient, service.AddScope and service.AddSingleton methods in Asp.Net Core 1? (this link explains differences between methods).
AddTransient is good in my case because it creates an instance of an object through the whole lifespan of the application, which is what I need. This means UI is dependant on the rest of the solution, because Startup.cs needs to know about the Repositories as well as the Services.
A pretty good answer can be found here :Onion Architecture : Can UI depend on Domain.
I'm working in asp.net mvc 4 with Entity Framework 5 (with edmx). I'm trying to get Ninject to work correctly, but using the bindings has got me quite confused. I've seen Ninject being used before, but that was in a WCF project where the DI was being set in the WCF-layer.
Right now I have 4 layers:
DataAcces (contains edmx and repositories, which I will show later)
BusinessLogic (standard BL)
Common (models)
Gui (a mvc4 project)
Now here's the tricky part: I want to use DI here. The way I saw it being used in my previous WCF-project was that my WCF-layer went to my DataAccess so I can use the kernel.bind.
Now I don't want that here. I'm not using WCF. I also don't want to call my DataAccess in my Gui.
Since I said I'd show some code for insight:
Repository in DataAccess
public class Repo: IRepo
{
Entities context = new Entities();
public IQueryable<PictureSource> PictureSource
{
get { return context.PictureSource; }
}
}
my IRepository is just this:
public interface IRepository
{
IQueryable<PictureSource> PictureSource { get; }
}
What I want to be able to do is in my BusinessLogic. I want to be able to do the following:
public List<Picture> GetStuff(IRepository Repo)
{
//code
}
Now I've looked a lot on the internet. About 80% of the examples use Web Apim which is useless to me. The other 20% just seem to do whatever they want "because it's just a demo" and violate Gui-BL-DA principle. I've seen examples consisting of a single layer to examples doing Business Logic in Data Access.
The ninject wiki also didn't help me as I'm new to DI and I've only seen it being used in an existing application.
Try to code using Poor-Man's-DI. Inject your dependencies in your constructor!
public class BusinessLogic
{
private _repository;
public BusinessLogic(IRepo repository)
{
_repository = repository;
}
public List<Picture> GetStuff()
{
_repository.PictureSource.Where(x=>x.Published == false);
}
}
Once you have your codebase right, register your dependencies in Ninject. Ninject then takes care to inject your Repository to you BusinessLogic class.
Please note that you have an IQueryable in your IRepo, which you should avoid (http://www.infoq.com/news/2012/03/IQueryable-api)
Edit:
This would be your solution structure and the references:
MVC4 (GUI)
-> DataAccess
-> BusinessLogic
-> Common
You need to setup this references, to wire up your bindings.
BusinessLogic
-> Common (including your Interfaces!)
DataAccess
-> Common
IKernel kernel = new StandardKernel();
kernel.Load("*.dll");
This should load NinjectModules in all .dlls in the current directory. So you don't need to add reference to the DAL.
What is the best way to manage the context of Entity Framework when using MVC application?
I am using a Repository/Service pattern.
Edit
After looking through some of these questions: stackoverflow.com/users/587920/sam-striano, I am more confused then before. Some say use the context per repository, but wht if I want to use multiple repositories in one controller method?
And to follow good separation design, how do you use UnitOfWork in the MVC app with out making it dependent on EF? I want to be able to unit test my controllers, model, services, etc. using a mock context?
Use a Dependency Injector/Inversion of Control framework like:
Ninject
Autofac
StructureMap
Unity
Using an IoC container, you can tell it how to manage a single data context (most commonly, per request). When you set the data context to per request, the container will auto-magically give any class that needs a data context the same data context per request.
Here is a good article on setting up Ninject.
What your code will most likely end up looking like, assuming you're using a generic repository:
Ninject Module:
public class NinjectRegistrationModule : NinjectModule
{
public override void Load()
{
Bind<MyDataContext>().ToSelf().InRequestScope();
Bind(typeof(RepositoryImplementation<>)).ToSelf().InRequestScope();
}
}
Generic Repository:
public RepositoryImplementation<T> : IRepository<T> where T : class
{
MyDataContext _dataContext;
public RepositoryImplementation<T>(MyDataContext dataContext)
{
_dataContext = dataContext;
}
// bunch of methods that utilize _dataContext
}
Service Class:
public class MyServiceClass
{
IRepository<SomeEntity> _someEntityRepository;
public MyServiceClass(IRepository<SomeEntity> someEntityRepository)
{
_someEntityRepository = someEntityRepository;
}
// do stuff with _someEntityRepository = someEntityRepository;
}
Controller:
public class MyController
{
MyServiceClass _myServiceClass;
public MyController(MyServiceClass myServiceClass)
{
// Ninject will auto-magically give us a myServiceClass
// which will Ninject will inject a repository into MyServiceClass's constructor
_myServiceClass = myServiceClass;
}
public ActionResult MyAction()
{
// use _myServiceClass to do stuff
return View();
}
}
If your functionality is straight forward, then you should create a new ObjectContext in each Repository. They are cheap to instantiate.
If this creates a conflict, you can use a Unit of Work pattern as was suggested in the comment.
I would advise that you be extremely cautious when integrating an ObjectContext or DataContext with a DI container. Many do not use the appropriate scope for their life cycle by default.
I'm currently injecting dependencies into controllers using a IoC container (Castle). This is possible because you need to create a custom controller factory which enables the dependency injection.
What are other examples of dependency injection? At which point in an MVC application would you use it, and where does a 'factory' come into play?
I am using Ninject. At my project:
Service layer objects are injected into controllers (using constructor).
Repositories are injected into service layer objects (using constructor).
ObjectContext is injected into repositories (using constructor).
web.config setting are encapsulated into a class, which implements IAppSettings interface, which is then injected into service layer.
NinjectActionInvoker is injected as IActionInvoker. It takes care of injecting services into ActionFilters.
I have my own implementation of IPrincipal interface, which is injected into service layer, instead of referring to HttpContext.Current.User.
Example using Ninject:
public class UserService : GenericService<User>, IUserService
{
public ISettingService SettingService { get; set; }
public ICTEmailSender CTEmailSender { get; set; }
public ICTSettings CTSettings { get; set; }
public ICTPrincipal User { get; set; }
}
Ninject rules:
Bind<ICTPrincipal>().ToMethod(c => (ICTPrincipal)HttpContext.Current.User).OnlyIf(a => HttpContext.Current.User is ICTPrincipal);
Bind<ICTEmailSender>().To<CTEmailSender>();
Bind<ICTSettings>().To<CTSettings>();
Not only service is injected into controller, but parts of service are injected into it. It makes service more testable. I am sure it can be easily ported into Castle.