Using ninject with repositories, in mvc 5 ef 6 - asp.net

I set up my first mvc project with ninject, and im not sure if i understand this fully. I have the following simple setup.
I am using entity framework 6 as my orm.
Customer repository
public class CustomerRepository : ICustomerRepository
{
private readonly ApplicationDbContext db;
public CustomerRepository(ApplicationDbContext db)
{
this.db = db;
}
public IEnumerable<Customer> GetAll()
{
return this.db.Customers.ToList();
}
}
ICustomerRepository
public interface ICustomerRepository
{
IEnumerable<Customer> GetAll();
}
Ninject
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICustomerRepository>().To<CustomerRepository>().InRequestScope();
kernel.Bind<ICustomerDetailsRepository>().To<CustomerDetailsRepository>().InRequestScope();
kernel.Bind<ApplicationDbContext>().To<ApplicationDbContext>().InRequestScope();
}
Controller
public HomeController(ICustomerRepository customerRepository, ICustomerDetailsRepository customerDetailsRepository)
{
this.customerRepository = customerRepository;
this.customerDetailsRepository = customerDetailsRepository;
}
As you can see, i am calling both repositories from the same controller. Both repositories are setup exactly the same way.
Will both my repositories use the same dbcontext when requested, and will it automaticly be disposed afterwards??
This is not a real life setup. I made it really basic to try and understand how ninject work.

The fact that you configured your binding to be InRequestScope means that the requested object will be created the first time it's resolved after a new request starts, and for every subsequent resolutions of the same object within the same request, you will get the same instance.
Keep in mind that the lifetime of the request is determined by the lifetime of the HttpContext.Current object.
Just for reference:
As you can see here:
InThreadScope matches the lifetime of your object to the lifetime of System.Threading.Thread.CurrentThread
InSingletonScope matches the lifetime of your object to the lifetime of Ninject's Kernel
InTransientScope matches the lifetime of your object to the lifetime of null
Update
Regarding your comment about people implementing Dispose():
Even if you don't dispose your objects manually, when the dependency injection container disposes your object, it calls the dispose method if it implements IDisposable

Related

Why is the IConfiguration object null after injecting it to DbContext? [ASP.NET Core 3.1]

Before posting this question I have gone through multiple posts that are similar. My question focuses on "why is it happening despite applying the common and possibly right solution?".
I am developing a .NET Core 3.1 web app. I have a DbContext named 'SkipQContext'. I am trying to access the connection string from appsettings.json in the SkipQContext file using Configuration object.
For that, I have injected IConfiguration as a service to the SkipQContext constructor.
Constructor:
private readonly string ConnectionString;
public SkipQContext()
{
}
public SkipQContext(DbContextOptions<SkipQContext> options, IConfiguration configuration)
: base(options)
{
ConnectionString = configuration.GetConnectionString("DefaultConnection");
}
I have also registered in ConfigureServices method of Startup class.
services.AddSingleton(Configuration);
Now when I instantiate SkipQContext in one of my repository classes, the default constructor of SkipQContext is called. When I try to fetch data using it, I get the "IConfiguration object is null."
I applied breakpoints in ConfigureServices method and can see that the IConfiguration object has the connection string value.
My first question is, why is it null in SkipQContext when I am registering it in ConfigureServices and also injecting it in SkipQContext constructor? Multiple answers online state this as the right method.
Also, I am thinking, I might not be instantiating the SkipQContext rightly. As my statement :
SkipQContext db = new SkipQContext();
hits the default constructor of SkipQContext which is empty and not the overloaded constructor where IConfiguration is injected.
P.S. If the last question is dumb. I am still a bit unclear about how dependency injection works in .NET Core.
Also, I am thinking, I might not be instantiating the SkipQContext rightly. As my statement:
SkipQContext db = new SkipQContext();
hits the default constructor of SkipQContext which is empty and not the overloaded constructor where IConfiguration is injected.
You are right, this is not how dependency injection is supposed to work. Whenever you do new Something, then you are explicitly going around dependency injection. The main point about dependency injection is that a component that has a dependency (e.g. a database context) does not need to create that dependency itself, or even know how to create that dependency itself.
When you call new SkipQContext(), you are explicitly creating that depenndency, so you are tightly coupled to that SkipQContext and whatever that context needs in order to work properly (in this case, it needs DbContextOptions and IConfiguration). What you want instead is components to be loosely coupled to their dependencies. So you just declare what dependencies you need and require that someone or something else fulfills these dependencies for you. And that’s exactly where dependency injection comes in:
With dependency injection, you have a “dependency injection container” which takes care of creating all the dependencies that you or some component may require. You configure the container in a central location, in Startup.ConfigureServices, and then you are able to simply declare what dependencies you need via a service’s constructor. But in order for the container to provide these dependencies to that service, the service will have to be created by the container itself.
So what you will see is that you will basically have to consume everything through dependency injection. But this also makes it easy to realize when you are not using dependency injection: Whenever you write new Something, then that something won’t be created by the container and as such won’t have its dependencies automatically fulfilled. Depending on what that something is that might be what you want, or maybe not (e.g. creating a List<string> or a DTO object is something you want to do directly, creating a service or something that has other dependencies likely isn’t).
Coming back to your problem, in order to have the DI container take care of the dependencies in the constructor of SkipQContext, you will have to let the DI container create that context for you. So you cannot create it with new but instead you will have to depend on it by adding it to the constructor of whatever component you need it in.
E.g. if you have a controller, just add it as a dependency there:
public class HomeController : Controller
{
private readonly SkipQContext _db;
public HomeController(SkipQContext db)
{
_db = db;
}
public async Task<IActionResult> Index()
{
var items = await _db.Items.ToListAsync();
return View(new IndexViewModel
{
Items = items,
});
}
}
One final note regarding your database context: If you register the database context correctly with the DI container, then it will already be configured using the DbContextOptions that gets passed to the constructor. These options will also include the connection string the context needs to open the database connection. So you do not need to pass the IConfiguration manually or extract the connection string there. It will be automatically done for you by EF Core.
A proper context setup could look like this (in ConfigureServices):
services.AddDbContext<SkipQContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
There is no need to instantiate the Configuration as a Singleton, the Default builder of WebHost already inject the configuration in the request , your Startup Class should look like this
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
string conn = Configuration.GetConnectionString("NAME OF YOUR CONNECTION STRING IN THE application.json FILE");
services.AddDbContext<CLASSOFURDBCONTEXT>(config =>
{
config.UseSqlServer(conn);
});
}
}
And your dbcontext should have the following constructor
public YourDbContext(DbContextOptions<YourDbContext> options) : base(options)
{
}
Then you only need to call the DbContext in a controller or a service and the DI will do the rest
As per why your IConfiguration throw the null reference exception i can think of 2 possibilities. Either you need to do the other kind instanciation which would be like this
services.AddSingleton<IConfiguration,Configuration>();
Or maybe it is because you are not using DI into the DbContext itself, you shouldnt need to do the new YourContextDbContext(). You should just simply put it in the constructor of the service or controller and it should work "magically" without you actually need to make an instance of it.

DbContext gets disposed in ActionFilterAttribute, not reloaded on subsequent requests

I'm trying to inject a UOW container into a WebApi 2 actionfilter attribute
public class VerifyApiToken : ActionFilterAttribute
{
[Inject]
public IUOW Uow { get; set; }
public override void OnActionExecuting(HttpActionContext actionContext)
{
//get and save data to any repository in the uow container
base.OnActionExecuting(actionContext);
}
The UOW container gets injected like its supposed to and on the first request everything works fine. On subsequent request EF throws an exception saying that the DbContext has been disposed.
All the dependancies are bound in request scope, so its normal that the underlying dbcontext gets disposed. When using constructor injection in WebApi controllers everything works, resources are recreated on each request, why are they not recreated when trying to use Property injection in ActionFilterAttributes and how could this be resolved?
The IFilterProvider I'm using:
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
IEnumerable<FilterInfo> controllerFilters = actionDescriptor.ControllerDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Controller));
IEnumerable<FilterInfo> actionFilters = actionDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Action));
IEnumerable<FilterInfo> filters = controllerFilters.Concat(actionFilters);
foreach (FilterInfo filter in filters)
{
_kernel.Inject(filter.Instance);
}
return filters;
}
The "Inject" method description says "Injects the specified instance, without managing its lifecycle". So I take it that my VerifyApiToken attribute is injected once per App lifecycle (basically Application_Start) and thus on the following requests the same instance is used (with a disposed DbContext of course).
Is it even possible to configure Ninject to use a new IUOW container for each request in ActionFilterAttributes?
Filters are cached and reused by the WebApi Framework. You should thus not inject any dependency in request scope; use a factory instead.
For more information see the documentation
I was able to follow qujck's hint and instead inject a Func to the actionfilter.
It is required the following binding:
kernel.Bind<Func<IUOW>>().ToMethod(m => () => m.Kernel.Get<IUOW>());

MVC Custom Membership and Role Provider context lifetime issue

I'm having problems with custom membership within MVC 4 I keep getting a context lifetime related error when I do a ajax call to get a partial result from the server(controller), the error is always {"The provider has been closed"} or {"There is already an open DataReader associated with this Command which must be closed first."} the error always lands within the custom RoleProvider.
I will try to explain the current setup im using.
I have inherited from the Membership and RoleProvier and overridden all the methods like so
public class CustomRoleProvider : RoleProvider
{
private IAccountService _accountService;
public CustomRoleProvider()
{
_accountService = new AccountService();
}
public override string[] GetRolesForUser(string username)
{
return _accountService.GetRolesForUser(username);
}
}
The Membership provider is implemented in the same way the IAccountService above is the service layer that deals with all user accounts & roles all the service layer classes implement a base service class called ServiceBase that creates the DB context
public class ServiceBase
{
protected Context Context;
protected ServiceBase() : this("Context") {}
protected ServiceBase(string dbName)
{
IDatabaseInitializer<Context> initializer = new DbInitialiser();
Database.SetInitializer(initializer);
Context = new Context(dbName);
}
}
The Controller that has the ajax to made to it
[Authorize(Roles = "Administrator,Supplier")]
public class AuctionController : Controller
{
private IAuctionService _service;
public AuctionController()
{
_service = new AuctionService();
}
public AuctionController(IAuctionService service)
{
_service = service;
}
[CacheControl(HttpCacheability.NoCache), HttpGet]
public ActionResult RefreshAuctionTimes(int auctionId)
{
return PartialView("_AuctionTimer", BusinessLogic.Map.ConvertAuction(_service.GetAuction (auctionId)));
}
}
The problem only started when I added the [Authorize(Roles = "Administrator,Supplier")] attribute to the controller that handled the ajax call, I know this is the lifetime of the DbContext being for the life of the app and the controllers service layer being destroyed and recreated on every post but I'm not sure of the best way to handle this, I have used this setup before but with DI and Windsor and never had this problem as the IOC was controlling the context.
Would it be best to create the providers its own DB context or is the conflict between the 2 providers and really they need to share the same db context?
Any help would be great thanks
The problem is exactly what you're suspecting. Is due to the fact that you're creating a single instance of the DbContext and therefore you're having connection issues. If you use it with an IOC/DI schema, you're going to fix it. The other option is to manually handle the connections.
An example of how to do this using Ninject as IOC container is here
They need to share the same context in order for the problem to stop.
I would suggest you create your service layer class on each call to GetRolesForUser:
public override string[] GetRolesForUser(string username)
{
return new AccountService().GetRolesForUser(username);
}

Web API controller parameterized constructor called only once, parameterless constructor on subsequent requests

I'm attempting to use Unity to inject a dependency per this article:
http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
Here is what I have in my global.asax
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterType<CustomerController>();
unity.RegisterType<TPS.Data.Can.IUnitOfWork, TPS.Data.Can.EFRepository.UnitOfWork>(new HierarchicalLifetimeManager());
config.DependencyResolver = new IoCContainer(unity);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureApi(GlobalConfiguration.Configuration);
}
Here is my API controller:
public class CustomerController : ApiController
{
private TPS.Data.Can.IRepository<tblCustomer> _repo;
private TPS.Data.Can.IUnitOfWork _uow;
public CustomerController() { }
public CustomerController(TPS.Data.Can.IUnitOfWork uow) {
_uow = uow;
_repo = uow.CustomerRepository;
}
// GET api/customer/5
public IEnumerable<Customer> Get()
{
string identity = HttpContext.Current.User.Identity.Name;
//REFACTOR THIS
if (String.IsNullOrWhiteSpace(identity))
identity = "chardie";
var customers = from c in _repo.Get()
where c.SalesRep == identity
select new Customer
{
IDCUST = null,
CustCode = c.CustCode,
CustName = c.CustName
};
return customers.ToList();
}
This works when I first start debugging my application. If I set a breakpoint in the parameterized constructor, the breakpoint will be hit when I hit the Web API for the first time. When I hit refresh in my browser, the constructor does not get called, the dependency doesn't get injected, and the Get() action throws an exception because the expected repository is null.
Can anyone tell me why my constructor isn't being called after the first request?
Thanks!
Chris
EDIT
FWIW, I removed the parameterless constructor entirely from the Web API controller, and on my second request to it, I get the exception:
Type 'TPS.Website.Api.CustomerController' does not have a default constructor
So it appears I'm getting my repo dependency injected on the first request, but after that every instantiation of the Web API controller is done through the parameterless constructor.
You're not specifying a lifecycle for the controller. MSDN states
If you do not specify a value for the lifetime, the instance will have
the default container-controlled lifetime. It will return a reference
to the original object on each call to Resolve.
If the IUnitOfWork dependency is transient, then the controller should be transient too. So try
unity.RegisterType<CustomerController>(new TransientLifetimeManager());
This might not solve the whole problem but it sounds like part of it. You certainly shouldn't need the parameterless constructor.
I had this as I was returning my resolver for my dependency scope using this and then disposing the container in the dispose. So after the first request the container was disposed.
Looks like it's because you're not using singleton pattern for the Unity Container.
Have a private static variable instead of the var container = new UnityContainer();
internal static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => new UnityContainer());
Then access within code using the .Value property.

How to pass unit of work container into constructor of repository using dependency injection

I'm trying to work out how to complete my implementation of the Repository pattern in an ASP.NET web application.
At the moment, I have a repository interface per domain class defining methods for e.g. loading and saving instances of that class.
Each repository interface is implemented by a class which does the NHibernate stuff. Castle Windsor sorts out the DI of the class into the interface according to web.config. An example of an implemented class is provided below:
public class StoredWillRepository : IStoredWillRepository
{
public StoredWill Load(int id)
{
StoredWill storedWill;
using (ISession session = NHibernateSessionFactory.OpenSession())
{
storedWill = session.Load<StoredWill>(id);
NHibernateUtil.Initialize(storedWill);
}
return storedWill;
}
public void Save(StoredWill storedWill)
{
using (ISession session = NHibernateSessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.SaveOrUpdate(storedWill);
transaction.Commit();
}
}
}
}
As pointed out in a previous thread, the repository class needs to accept an unit of work container (i.e. ISession) rather than instantiating it in every method.
I anticipate that the unit of work container will be created by each aspx page when needed (for example, in a property).
How do I then specify that this unit of work container instance is to be passed into the constructor of StoredWillRepository when Windsor is creating it for me?
Or is this pattern completely wrong?
Thanks again for your advice.
David
I have a persistence framework built on top of NHibernate that is used in a few Web apps. It hides the NH implementation behind an IRepository and IRepository<T> interface, with the concrete instances provided by Unity (thus I could in theory swap out NHibernate for, say, Entity Framework fairly easily).
Since Unity doesn't (or at least the version I'm using doesn't) support the passing in of constructor parameters other than those that are dependency injections themselves, passing in an extant NH ISession isn't possible; but I do want all objects in the UOW to share the same ISession.
I solve this by having a controlling repository class that manages access to the ISession on a per-thread basis:
public static ISession Session
{
get
{
lock (_lockObject)
{
// if a cached session exists, we'll use it
if (PersistenceFrameworkContext.Current.Items.ContainsKey(SESSION_KEY))
{
return (ISession)PersistenceFrameworkContext.Current.Items[NHibernateRepository.SESSION_KEY];
}
else
{
// must create a new session - note we're not caching the new session here... that's the job of
// BeginUnitOfWork().
return _factory.OpenSession(new NHibernateInterceptor());
}
}
}
}
In this example, PersistenceFrameworkContext.Current.Items accesses an IList<object> that is stored either ThreadStatic if not in a Web context, or within HttpContext.Current.Items if it is in a Web context (to avoid thread-pool problems). The first call to the property instantiates the ISession from the stored factory instance, subsequent calls just retrieve it from storage. The locking will slow things down slightly but not as much as just locking an appdomain-scoped static ISession instance.
I then have BeginUnitOfWork and EndUnitOfWork methods to take care of the UOW - I have specifically disallowed nested UOWs because frankly they were a pain to manage.
public void BeginUnitOfWork()
{
lock (_lockObject)
{
if (PersistenceFrameworkContext.Current.Items.ContainsKey(SESSION_KEY))
EndUnitOfWork();
ISession session = Session;
PersistenceFrameworkContext.Current.Items.Add(SESSION_KEY, session);
}
}
public void EndUnitOfWork()
{
lock (_lockObject)
{
if (PersistenceFrameworkContext.Current.Items.ContainsKey(SESSION_KEY))
{
ISession session = (ISession)PersistenceFrameworkContext.Current.Items[SESSION_KEY];
PersistenceFrameworkContext.Current.Items.Remove(SESSION_KEY);
session.Flush();
session.Dispose();
}
}
}
Finally, a pair of methods provide access to the domain-type-specific repositories:
public IRepository<T> For<T>()
where T : PersistentObject<T>
{
return Container.Resolve<IRepository<T>>();
}
public TRepository For<T, TRepository>()
where T : PersistentObject<T>
where TRepository : IRepository<T>
{
return Container.Resolve<TRepository>();
}
(Here, PersistentObject<T> is a base class providing ID and Equals support.)
Access to a given repository is thus in the pattern
NHibernateRepository.For<MyDomainType>().Save();
This is then facaded over such that you can use
MyDomainType.Repository.Save();
Where a given type has a specialised repository (ie needs more than it can get from IRepository<T>) then I create an interface deriving from IRepository<T>, an extending implementation inheriting from my IRepository<T> implementation, and in the domain type itself I override the static Repository property using new
new public static IUserRepository Repository
{
get
{
return MyApplication.Repository.For<User, IUserRepository>();
}
}
(MyApplication [which is called something less noddy in the real product] is a facade class which takes care of supplying the Repository instance via Unity so you have no dependency on the specific NHibernate repository implementation within your domain classes.)
This gives me full pluggability via Unity for the repository implementation, easy access to the repository in code without jumping through hoops, and transparent, per-thread ISession management.
There's lots more code than just what's above (and I've simplified the example code a great deal), but you get the general idea.
MyApplication.Repository.BeginUnitOfWork();
User user = User.Repository.FindByEmail("wibble#wobble.com");
user.FirstName = "Joe"; // change something
user.LastName = "Bloggs";
// you *can* call User.Repository.Save(user), but you don't need to, because...
MyApplication.Repository.EndUnitOfWork();
// ...causes session flush which saves the changes automatically
In my Web app, I have session-per-request, so BeginUnitOfWork and EndUnitOfWork get called in BeginRequest and EndRequest respectively.
I have a pretty similar structure to yours, and here's how I solve your question:
1) To specify my container on each method, I have a separate class ("SessionManager") which I then invoke via a static property. By doing so, here's an example using my Save implementation:
private static ISession NHibernateSession
{
get { return SessionManager.Instance.GetSession(); }
}
public T Save(T entity)
{
using (var transaction = NHibernateSession.BeginTransaction())
{
ValidateEntityValues(entity);
NHibernateSession.Save(entity);
transaction.Commit();
}
return entity;
}
2) My container is not created on each ASPX page. I instantiate all of my NHibernate goodness on the global.asax page.
** A few more things spring up **
3) You don't need to have a helper to instantiate the Load. You might as well use Get instead of Load. More information # Difference between Load and Get.
4) Using your current code, you would have to repeat pretty much the same code for each domain object you need (StoredWillRepository, PersonRepository, CategoryRepository, etc..?), which seems like a drag. You could very well use a generic class to operate over NHibernate, like:
public class Dao<T> : IDao<T>
{
public T SaveOrUpdate(T entity)
{
using (var transaction = NHibernateSession.BeginTransaction())
{
NHibernateSession.SaveOrUpdate(entity);
transaction.Commit();
}
return entity;
}
}
In my implementation, I could then use something like:
Service<StoredWill>.Instance.SaveOrUpdate(will);
Technically, the answer to my question is to use the overload of container.Resolve which allows you to specify the constructor argument as an anonymous type:
IUnitOfWork unitOfWork = [Code to get unit of work];
_storedWillRepository = container.Resolve<IStoredWillRepository>(new { unitOfWork = unitOfWork });
But let's face it, the answers provided by everyone else have been much more informative.

Resources