I have read a lot of about IoC and design patterns but I´m not able to find clear answer. I´m doing whole data management in model, so I´m also creating database context in the model, but I found a solution from Benjamin Gale - When should I create a new DbContext(), which I like and it solves me a loft of problems with sharing db context, but my question is, how to pass this context from controller to model?
When I have ActionResult like this:
[Authorize, HttpPost]
public ActionResult AccountEditation(AccountEditationModel accountEditation)
{ ... }
Would be good solution to apply setter injection in AccountEditation actionResult, thats mean in each of actionResult method:
[Authorize, HttpPost]
public ActionResult AccountEditation(AccountEditationModel accountEditation)
{
accountEditation.db = Database; //Database from BaseController
...
}
Or is there any other way to do that?
Despite the name, ASP.NET MVC only loosely follows the MVC pattern. Namely, there's no true Model. Instead, your Model will be a combination of your entity, view models that represent that entity and your DAL, but each of these should be a separate thing. It's totally inappropriate to create or even inject a context into an entity class.
Your DAL will be the sole owner of the context. You should have an interface that represents an API that your application can use. Then, you should have one or more implementations of that interface, one per each discreet data access method (Entity Framework, Web Api, etc.). You'll then inject your context into this implementation and inject the implementation into your controller(s). The controllers, themselves, should only ever reference the interface. This is what's called the provider pattern, and it allows you sub-in different access methods as needed. Decided that you'd rather use Dapper than Entity Framework? Just create a new implementation for Dapper and inject that instead; none of the rest of your code needs to change.
The easiest thing I have found is to inject a repository into the Controller via Unity. And then pass the repository, if you need to, to whatever service or class you're using to process your business logic.
Basically...
public class AccountController : Controller
{
private IRepository<Account> _accountRepository;
public AccountController(IRepository<Account> accountRepository)
{
this._accountRepository = accountRepository;
}
}
When you use Unity and set it up properly, you can automatically inject whatever repository you're using into the AccountController class. After that, you shouldn't have a problem passing that same repository to other services or classes that need it.
Unity Dependency Injection
Related
I would like to pass global custom data from API Level to Application Service, to Repository and DB Context layer, without using parameters in every method.
1) One method is HttpContextAccessor.
Curious if there is any other global parameter embedded in Net Core, or is this the only known strategy? We are passing auditable data, CreateBy, ModifiedDate, but may extend it other properties. We have 100+ apis, application methods, repositories, and trying to prevent passing around a parameter.
_httpContextAccessor.HttpContext.Items["TestKey"] = "SampleData";
DBContext:
public class AuditableDbContext: DbContext
{
private readonly IHttpContextAccessor _httpContextAccessor;
public AuditableDbContext(DbContextOptions<AuditableDbContext> options, IHttpContextAccessor httpContextAccessor)
: base(options)
{
_httpContextAccessor = httpContextAccessor;
}
Custom Data changes based on application behavior and user interaction.
One problem with using context aware objects across multiple layers is the dependency to that context.
It makes it really hard to understand the code in the long run, and, most importantly, it makes it harder to unit test.
Imagine you rely on an HttpContext item coming from your controller in another layer. The unit test of that layer would now have to mimic the controller and set the item on the context to produce a proper state.
Having multiple parameters getting passed around everywhere is bad, too, true.
One way of solving it would be a simple Poco object to store the state and pass that around, that would make unit testing simple and also reduce the number of parameters of methods in all layers.
public class RequestState
{
public User CreateBy { get; }
...
}
The controller would initiate the state object and all layers would use it...
Another way would be to rely on the DI framework and use a scoped lifetime object which gets injected into all layers which you then can abuse to store your state information.
That's pretty similar to http context but at least its your own thing and you can do whatever you want with it and also add strongly typed properties instead of an Items collection.
In your startup, you'd inject the scope object with Scoped lifetime.
You inject the object into your controller and all other classes (works only if those classes are also scoped or transient).
Hello, I'm trying to implement a ViewModelFactory "pattern" and I was wondering what's the best way to achieve it, considering the constraints of the current IoC container.
public class UserCreateViewModelFactory
{
private readonly DbContext db;
public UserCreateViewModelFactory(DbContext db){ this.db = db;}
public void Create(CreateUserViewModel viewModel)
{
//Creates the user
}
}
I have the above class easily injected into my controllers ctor. The head ache will come when I need more ViewModelBuilders, So I want to avoid two things:
Bloat ctor with injections
Bloat container with registrations
I want to be able to inject an IViewModelFactory on my controller and then using it like this:
[HttpGet]
public IActionResult GetUsers(int id)
{
return View(viewModelFactory.Build<GetUserViewModel>(id));
}
Notice that on calling Build(T) it has to call the correct IViewModelFactory implementation.
I know that StructureMap container support binding the concrete implementations to the corresponding interface but I'm trying to come up with a solution without having to add another dependecy to the project.
I think if you have builders for building viewmodels, then factory is extra layer of abstraction which simply can be dropped off.
Because you know the type of created viewmodel at compile time you can just inject a builder you need to the controller constructor.
If your controller create a lot of viewmodels and you end up with a lot of builders you need to inject - this can be considered as a sign of violation of Single Responsibility Principle. In that case you need to separate logic of controller to different controllers.
So I want to avoid two things:
Bloat ctor with injections
Separate class with bloated constructor to another classes with more specific responsibility which takes smaller amount of dependencies.
Or wrap dependencies with one or two, three classes based on their relation
Bloat container with registrations
This cannot be a problem, because dependency containers is usually designed to register whole "object graph" of your application
After sometime researching, I finally came up with a good solution for the this problem.
The solution is basically extending the default IoC capabilities through an IServiceCollection.ConnectImplementations() extension method.
During registration I'll search my concrete classes and connect them with its respective interfaces (like other containers). Then I use a Mediator/Proxy that has IServiceCollection injected and knows which concrete class should be building the view model.
The full solution is better explained by this gist I've created.
I have a big View with about 7 dropdowns to diferents models...
So, in my controller´s constructor I have 9 IRepository, like that :
public CrudController(IRepository<Class1> class1Rep, IRepository<Class2> class2Rep, ...
IRepository<Class9> class9Rep)
{
this.class1Rep = class1Rep;
...
this.class9Rep = class9Rep;
}
So, I can populate my ViewModel with all necessary data...
Is that the right way to do that? I´m using Ninject...
Thanks
Looks like a violation of SRP. Does each View Model require all repositories? Do some ViewModels just use a couple? Are you doing other complex work to create ViewModel? If so I would abstract the general concept of ViewModel construction and ideally use something like Automapper to remove any mappings.
We abstract the concept of populating the select lists and other complex work using an IModelEnricher<T> where T is a ViewModel. IModelEnricher<T> defines one method Enrich which takes an instance of the T ViewModel and returns an instance T. In the Enrich method do any clever work you need to do. If you need two repositories for a ViewModel then you are only injecting those into the constructor of your IModelEnricher<T>
We automatically use an IModelEnricher to enrich ViewModels returned from our Action results. We always also automap our domain model to the ViewModel in the same pipeline. Most Get controller actions are a single line of code as Automapper handles taking Domain Model to ViewModel and enricher does any additional stuff.
retrun AutoMappedView<AConcreteViewModel>(repository.Find(id))
If a class implemeting IModelEnricher is found for AConcreteViewModel it will be called and any work done e.g.
public class AConcreteViewModelEnricher:IModelEnricher<AConcreteViewModel>{
AConcreteViewModelEnricher(Repo1 repo1, Reop2 rep2){
........
}
AConcreteViewModel Enrich(AConcreteViewModel model){
//Do stuff with repo etc and
return model
}
}
See my answer to your other question about drop downs.
Instead of passing multiple repositories, you pass a single instance of a Unit of Work. The trick is to implement it correctly, here is one:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
(the UoW part starts somewhere at the end)
What is still missing there is that you have a uow interface and multiple implementations. For example, an Entity Framework unit of work has the content injected so that it can pass the context down to repositories. An inmemory unit of work can have other dependencies etc.
Ultimately, your IoC container just resolves the Unit of Work.
One simple answer is to simply create a wrapper class that contains all your repositories, then you need only pass the wrapper class.
However, most purists would say that if you have that many repositories, you're probably violating the Single Responsibility Principle and should break out the functionality into other classes.
I just have a quick question. Im trying to use Unity with my asp.net MVC project. Im coming across a problem when using the Unit of Work pattern with an EF context.
Say i inject the uow in the constructor, but have 4 or 5 actions in the controller that need to use the UnitOfWork in a using statement. This isnt going to work! Because Id have to do a
new UnitOfWork() in each action method.
should i be injecting a UnitOfWork into each action method? or into just the constructor? or should I even be injecting this at all!! The problem im facing is that i want to be able to unit test my controller with Mock data, and i can only do this if I inject the UnitOfWork or the DBContext.
Inject factory instead. This way you still achieve separation of concerns and loose coupling, yet you won't face any issues with using statements:
private IUnitOfWorkFactory factory;
public MyController(IUnitOfWorkFactory factory)
{
this.factory = factory;
}
public ActionResult MyAction()
{
using (var uow = factory.CreateUnitOfWork())
{
// ...
}
}
Edit:
Natural advantage of such approach is its configurability - you can register whichever factory you like to serve different controllers and wire it up at composition root:
// Note: this isn't unity syntax, but I hope my point is clear
container.Register<ISessionFactory, ReusableSessionFactory>("Reusable");
container.Register<ISessionFactory, FreshSessionFactory>("Fresh");
container.Register<IController, LoginController>().With("Fresh");
container.Register<IController, HomeController>().With("Reusable");
Now,
LoginController will use factory that under the hood serves new session upon each request
HomeController on the other hand will reuse the same session for all its lifespan
It's worth noting that from the controller point of view, it's irrelevant which factory serves the session as it's a mere implementation detail. That's why we hide session factory dependency behind abstraction (interface in this example) and perform all the object-to-dependency binding at application's root.
If I understand correctly you simply want to be able to test the UOW with something like Moq?
In that case for good design principles and proper separation of concerns you should create a base context for your database that each repository class uses.
Then you should create a repository interface for each domain model entity. Then you can implement the interface in a seperate repository library (this way you can implement a POCO model)
Finally you either create a service layer between your domain objects and your action methods or just use the required repository interfaces within the action methods.
I answer it like this because it depends on your application infrastructure. If you have no service layer then the best practice is to do the following:
public class AccountController : Controller
{
private readonly IAccountRepository _accountrepository;
public AccountController(IAccountRepository repository)
{
_accountrepository = repository;
}
}
I hope this helps.
I have the following Interface
interface IProfileRepo {
}
And it's implementation
public class DBProfileRepo : IProfileRepo {
string _specialValue;
public DBProfileRepo(IAuthorizedController authController) {
_specialValue = authController.SomeValue;
}
}
My binding is
Bind<IProfileRepo>()
.To<DBProfileRepo>()
.InRequestScope();
My MVC controller which implements IAuthorizedController, is receiving this injection of DBProfileRepo, however, DBProfileRepo requires this controller as a constructor argument. How can I do this?
I am using Ninject 2.2.1.0
You have circular dependency between your objects and this is something you should avoid when designing your object hierarchy. A repository should not require a controller instance, that simply doesn't make sense. A repository is a data access class which could be reused in different kind of applications such as Desktop or Silverlight where there are no controllers. It is the controller which should require a repository and that's pretty much all.
If you need to pass some information to this repository which is available only in the controller, like for example a request parameter, simply design an object and pass this object to the repository method from the controller but don't pass an entire controller.