I went through the recommended steps to add Ninject to my MVC application. And I added a DbContext
argument to my controllers' constructors.
Controller:
public class MyController : BaseController
{
public ArticlesController(MyDbContext context)
: base(context)
{ }
}
Base Controller:
public class BaseController : Controller
{
protected DbContext MyDbContext;
public BaseController(MyDbContext context)
{
MyDbContext = context;
}
}
This seems to work well. But leaves me with a few questions.
Does Ninject ensure my
DbContext
is cleaned up and disposed in a timely fashion?I have created a base class for all my application's controllers to handle any common initialization, etc. The base class accepts an instance of my
DbContext
argument in the constructor. But this requires me to also add this argument to every controller in my app. Is there any way to not require this?I'm not sure how expensive it is to create an instance of my
DbContext
. Is there any way to make the optimization that it only gets created if the request actually requires me to access the database.
As per this answer:
Simply put, never use a common base class for MVC Controllers. Class inheritance tends to tightly couple your logic and it becomes difficult to maintain over time. It also tends to lead you to create a god object, because creating multiple levels of injected dependencies would mean even more required dependencies for every Controller.
If you have cross-cutting concerns, you should use globally registered filters instead. You can make a separate filter for each piece of logic, which doesn't violate the Single Responsibility Principle as a shared base class would. And if you register your filters globally, you can use constructor injection as in this action filter or this authorization filter. You can also make your own attributes (without behavior) to make them conditional per controller and/or action, if necessary.
Example:
Since you explicitly said you wanted to set common
ViewBag
properties based on the current user, here is how that can be done with filters.CurrentUserProfileFilter
GlobalFilterProvider
MVC has a static
GlobalFiltersCollection
where you are supposed to register filter instances globally. This isn't going to do for filters that have dependencies that have lifetimes that are managed by the DI container (such asDbContext
).To ensure the filters are resolved on demand (per-request), we make an
IFilterProvider
that resolves them through the container (assuming your Ninject container is registered with MVC as the DependencyResolver);Usage
In your Ninject composition root, register the instance of your filter with the
kernel
for the type or types of filter interfaces it implements.In
FilterConfig
, register your filter provider.Now on every request, your user details are populated.
But more importantly, your
ArticlesController
doesn't requireMyDbContext
as a dependency, nor do the rest of your controllers.Have a look at this question: One DbContext per web request... why?