MVC3 tool using Entity Framework caching issues with Ninject - asp.net-mvc

I've got a new MVC 3 application which is showing some issues when modifying data manually in the Database.
The tool is still in development and once in a while I want to change my user's teamId. When I do so, I have to kill the Web development Server and run it again otherwise the queries don't pick the new teamId.
Same thing when I publish the tool to IIS, if I ever modify something on the database, I need to either copy over the 'bin' folder again or stop the application and re-run it.
When I modify data from the application itself, I have no problems.
This is how my Ninject looks like:
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel kernel = new StandardKernel(new TrackerServices());
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
return (IController)kernel.Get(controllerType);
}
private class TrackerServices : NinjectModule
{
public override void Load()
{
var context = new TrackerEntities();
Bind<IUserRepository>().To<UserRepository>().WithConstructorArgument("context", context);
}
}
}
My Interface:
public interface IUserRepository : IRepository<User>
{
User GetByName(string name);
}
my Implementation:
public User GetByName(string login)
{
var userLogin = _misc.GetUsername(login);
return _context.Users.Where(x => x.Login == userLogin).Single();
}
And my Index Action
public ActionResult Index()
{
var teamid = (int)_users.GetByName("myName").TeamId;
This has never happened before, but this tool is the first one I'm using with Ninject. I'm wondering if there's a relation between my problem and using a repository?

There are two issues that are combining to create this problem:
The way you've created your context is causing it to effectively be a singleton.
Entity Framework will not automatically check for a new version of an entity which the context is already tracking.
To solve this, I would recommend that you recreate your repository once per request (there won't be a significant performance hit for this, as it's fairly lightweight), by using this binding:
Bind<IUserRepository>().To<UserRepository>().InRequestScope();
Ninject should be able to create your TrackerEntities context automatically, but if not (or if you want to make it clear), you can use the following binding:
Bind<TrackerEntities>().ToSelf().InRequestScope(); (The InRequestScope is not really required here, as the default transient scope should be okay).
You could also go down the road of forcing a refresh of the entity (using ObjectContext.Refresh()), but that's probably not a great idea because you'd have to do it explicitly for each entity.

Related

How to handle authentication in multi-tenant MVC 5 app

I am trying to build a multi-tenant mvc 5 site that uses a single database and differentiates the tenants by schema in Sql Server.
I started with the default Mvc 5 template and updated the ApplicationDBContext that is provided to take a string specifying the schema to use for that tenant like so.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
private string _tenantSchema;
public ApplicationDbContext(string tenantSchema)
: base("Dev", throwIfV1Schema: false)
{
_tenantSchema = tenantSchema;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema(_tenantSchema);
base.OnModelCreating(modelBuilder);
}
public static ApplicationDbContext Create(string tenantSchema)
{
return new ApplicationDbContext(tenantSchema);
}
}
And then in the App_Start\IdentityConfig.cs I updated the Create Method of the ApplicationUserClass to use the first part of the Request.Host value to use as the tenantSchema like so
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var tenantSchema = context.Request.Host.Value.Split('.')[0];
var ctx = new ApplicationDbContext(tenantSchema);
var userStore = new UserStore<ApplicationUser>(ctx);
var manager = new ApplicationUserManager(userStore);
so if I were to log into site1.mysite.dev it would authenticate against the tables in the site1 schema is sql server.
When I start the site and access it using the site1 sub domain it correctly uses the site1 Schema to authenticate me. But then if I change url in the browser address bar and log in again it still validates against the site1 schema.
How can I configure the app to use to correct schema to check authentication for each request?
While the code you've shown should sort of work (but it's hard to tell since you left out other key parts, such as Startup.Auth), I would not do it in this way. I would instead change your ApplicationDbContext.Create method to this:
public static ApplicationDbContext Create(
IdentityFactoryOptions<ApplicationDbContext> options, IOwinContext context)
{
var tenantSchema = context.Request.Host.Value.Split('.')[0];
return new ApplicationDbContext(tenantSchema);
}
I would then alter my Startup.Auth as such:
app.CreatePerOwinContext<ApplicationDbContext>(ApplicationDbContext.Create); <---
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
And leave everything else the default. Specifically:
public static ApplicationUserManager Create(
IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(
new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
....
However, your real problem is most likely that your model builder is cached in the app domain the first time it is created. This is referenced in the documentation here:
http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext.onmodelcreating(v=vs.113).aspx
Typically, this method is called only once when the first instance of a derived context is created. The model for that context is then cached and is for all further instances of the context in the app domain. This caching can be disabled by setting the ModelCaching property on the given ModelBuidler, but note that this can seriously degrade performance. More control over caching is provided through use of the DbModelBuilder and DbContextFactory classes directly.
There is actually a nice discussion on this very topic relating to EF and multi-tenant usage (way too long to elaborate here) over at the EF codeplex site:
https://entityframework.codeplex.com/discussions/462765

Unit of work + repository + service layer with dependency injection

I am designing a web application and a windows service and want to use the unit of work + repository layer in conjunction with a service layer, and I am having some trouble putting it all together so that the client apps control the transaction of data with the unit of work.
The unit of work has a collection of all repositories enrolled in the transaction along with commit and rollback operations
public interface IUnitOfWork : IDisposable
{
IRepository<T> Repository<T>() where T : class;
void Commit();
void Rollback();
}
The generic repository has operations that will be performed on the data layer for a particular model (table)
public interface IRepository<T> where T : class
{
IEnumerable<T> Get(Expression<Func<T, bool>> filter = null, IList<Expression<Func<T, object>>> includedProperties = null, IList<ISortCriteria<T>> sortCriterias = null);
PaginatedList<T> GetPaged(Expression<Func<T, bool>> filter = null, IList<Expression<Func<T, object>>> includedProperties = null, PagingOptions<T> pagingOptions = null);
T Find(Expression<Func<T, bool>> filter, IList<Expression<Func<T, object>>> includedProperties = null);
void Add(T t);
void Remove(T t);
void Remove(Expression<Func<T, bool>> filter);
}
The concrete implementation of the unit of work uses entity framework under the hood (DbContext) to save the changes to the database, and a new instance of the DbContext class is created per unit of work
public class UnitOfWork : IUnitOfWork
{
private IDictionary<Type, object> _repositories;
private DataContext _dbContext;
private bool _disposed;
public UnitOfWork()
{
_repositories = new Dictionary<Type, object>();
_dbContext = new DataContext();
_disposed = false;
}
The repositories in the unit of work are created upon access if they don't exist in the current unit of work instance. The repository takes the DbContext as a constructor parameter so it can effectively work in the current unit of work
public class Repository<T> : IRepository<T> where T : class
{
private readonly DataContext _dbContext;
private readonly DbSet<T> _dbSet;
#region Ctor
public Repository(DataContext dbContext)
{
_dbContext = dbContext;
_dbSet = _dbContext.Set<T>();
}
#endregion
I also have a service classes that encapsulate business workflow logic and take their dependencies in the constructor.
public class PortfolioRequestService : IPortfolioRequestService
{
private IUnitOfWork _unitOfWork;
private IPortfolioRequestFileParser _fileParser;
private IConfigurationService _configurationService;
private IDocumentStorageService _documentStorageService;
#region Private Constants
private const string PORTFOLIO_REQUEST_VALID_FILE_TYPES = "PortfolioRequestValidFileTypes";
#endregion
#region Ctors
public PortfolioRequestService(IUnitOfWork unitOfWork, IPortfolioRequestFileParser fileParser, IConfigurationService configurationService, IDocumentStorageService documentStorageService)
{
if (unitOfWork == null)
{
throw new ArgumentNullException("unitOfWork");
}
if (fileParser == null)
{
throw new ArgumentNullException("fileParser");
}
if (configurationService == null)
{
throw new ArgumentNullException("configurationService");
}
if (documentStorageService == null)
{
throw new ArgumentNullException("configurationService");
}
_unitOfWork = unitOfWork;
_fileParser = fileParser;
_configurationService = configurationService;
_documentStorageService = documentStorageService;
}
#endregion
The web application is an ASP.NET MVC app, the controller gets its dependencies injected
in the constructor as well. In this case the unit of work and service class are injected. The action performs an operation exposed by the service, such as creating a record in the repository and saving a file to a file server using a DocumentStorageService, and then the unit of work is committed in the controller action.
public class PortfolioRequestCollectionController : BaseController
{
IUnitOfWork _unitOfWork;
IPortfolioRequestService _portfolioRequestService;
IUserService _userService;
#region Ctors
public PortfolioRequestCollectionController(IUnitOfWork unitOfWork, IPortfolioRequestService portfolioRequestService, IUserService userService)
{
_unitOfWork = unitOfWork;
_portfolioRequestService = portfolioRequestService;
_userService = userService;
}
#endregion
[HttpPost]
[ValidateAntiForgeryToken]
[HasPermissionAttribute(PermissionId.ManagePortfolioRequest)]
public ActionResult Create(CreateViewModel viewModel)
{
if (ModelState.IsValid)
{
// validate file exists
if (viewModel.File != null && viewModel.File.ContentLength > 0)
{
// TODO: ggomez - also add to CreatePortfolioRequestCollection method
// see if file upload input control can be restricted to excel and csv
// add additional info below control
if (_portfolioRequestService.ValidatePortfolioRequestFileType(viewModel.File.FileName))
{
try
{
// create new PortfolioRequestCollection instance
_portfolioRequestService.CreatePortfolioRequestCollection(viewModel.File.FileName, viewModel.File.InputStream, viewModel.ReasonId, PortfolioRequestCollectionSourceId.InternalWebsiteUpload, viewModel.ReviewAllRequestsBeforeRelease, _userService.GetUserName());
_unitOfWork.Commit();
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
return View(viewModel);
}
return RedirectToAction("Index", null, null, "The portfolio construction request was successfully submitted!", null);
}
else
{
ModelState.AddModelError("File", "Only Excel and CSV formats are allowed");
}
}
else
{
ModelState.AddModelError("File", "A file with portfolio construction requests is required");
}
}
IEnumerable<PortfolioRequestCollectionReason> portfolioRequestCollectionReasons = _unitOfWork.Repository<PortfolioRequestCollectionReason>().Get();
viewModel.Init(portfolioRequestCollectionReasons);
return View(viewModel);
}
On the web application I am using Unity DI container to inject the same instance of the unit of work per http request to all callers, so the controller class gets a new instance and then the service class that uses the unit of work gets the same instance as the controller. This way the service adds some records to the repository which is enrolled in a unit of work and can be committed by the client code in the controller.
One question regarding the code and architecture described above. How can I get rid of the unit of work dependency at the service classes? Ideally I don't want the service class to have an instance of the unit of work because I don't want the service to commit the transaction, I just would like the service to have a reference to the repository it needs to work with, and let the controller (client code) commit the operation when it see fits.
On to the windows service application, I would like to be able to get a set of records with a single unit of work, say all records in pending status. Then I would like to loop through all those records and query the database to get each one individually and then check the status for each one during each loop because the status might have changed from the time I queried all to the time I want to operate on a single one. The problem I have right now is that my current architecture doesn't allow me to have multiple unit of works for the same instance of the service.
public class ProcessPortfolioRequestsJob : JobBase
{
IPortfolioRequestService _portfolioRequestService;
public ProcessPortfolioRequestsJob(IPortfolioRequestService portfolioRequestService)
{
_portfolioRequestService = portfolioRequestService;
}
The Job class above takes a service in the constructor as a dependency and again is resolved by Unity. The service instance that gets resolved and injected depends on a unit of work. I would like to perform two get operations on the service class but because I am operating under the same instance of unit of work, I can't achieve that.
For all of you gurus out there, do you have any suggestions on how I can re-architect my application, unit of work + repository + service classes to achieve the goals above?
I intended to use the unit of work + repository patterns to enable testability on my service classes, but I am open to other design patterns that will make my code maintainable and testable at the same time while keeping separation of concerns.
Update 1
Adding the DataContext class that inheris from EF's DbContext where I declared my EF DbSets and configurations.
public class DataContext : DbContext
{
public DataContext()
: base("name=ArchSample")
{
Database.SetInitializer<DataContext>(new MigrateDatabaseToLatestVersion<DataContext, Configuration>());
base.Configuration.ProxyCreationEnabled = false;
}
public DbSet<PortfolioRequestCollection> PortfolioRequestCollections { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Configurations.Add(new PortfolioRequestCollectionConfiguration());
base.OnModelCreating(modelBuilder);
}
}
If your purpose for using Unit of Work (UoW) was for testability, you took the wrong path. Unit of work does nothing for testability. Its main purposes is to provide atomic transactions to disparate data sources, provide UoW functionality to a data layer that doesn't already provide it, or to wrap an existing UoW in a way that makes it more easily replaceable... something which you've nullified by using the generic repository (this tightly couples it to Entity Framework anyways).
I suggest you get rid of the Unit of Work completely. Entity Framework is already a UoW. Even Microsoft has changed their mind and no longer recommend UoW with EF.
So, if you get rid of UoW, then you can just use repositories to wrap your EF queries. I don't suggest using a generic repository, as this leaks your data layer implementation all over your code (something your UoW was already doing), but rather create Concrete repoTsitories (these can use generic repositories internally if you like, but the generic repository should not leak outside of your repository).
This means your service layer takes the specific concrete repository it needs. For instance, IPortfolioRepository. Then you have a PortfolioRepository class that inherits from IPortfolioRepository which takes your EF DbContext as a parameter that gets injected by your Depndency Injection (DI) framework. If you configure your DI container to instance your EF context on a "PerRequest" basis, then you can pass the same instance to all your repositories. You can have a Commit method on your repository that calls SavesChanges, but it will save changes to all changes, not just to that repository.
As far as Testability goes, you have two choices. You can either mock the concrete repositories, or you can use the built-in mocking capabilities of EF6.
I have been through that hell hole myself and here's what I have done:
Ditch the UoW completely. EF's DBContext is a UoW basically. No point in re-inventing the wheel.
Per MSDN:
DbContext Class
Represents a combination of the Unit-Of-Work and Repository patterns
and enables you to query a database and group together changes that
will then be written back to the store as a unit.
Service layer + Repo layer seemed like a good choice. However, repos are always a leaky abstraction and espcially when DBContext's DbSet are the equivalent of repositories.
Then when the need for a Windows service arises, things become muddied further with another layer now. Throw async or background processing in the mix, and things quickly start leaking.
If you ask my 2 cents, I would say go with the service layer + EF, one wrapping business logic, the other one wrapping UOW/Repository pattern.
Alternatively, and for Windows Services especially, I'm finding that moving to a command-query based approach works better.
Not only it helps testability, it also helps in asynchronous tasks where I don't have to worry about keeping the DBContext alive even after the request has ended (DBContext is now tied with the command handler and stays alive as long as the async command stays alive).
Now if you've recently ended up digesting all those facts about UOW/Repository pattern, then surely, just even reading about Command-Query pattern will make your mind hurt. I have been down that path but trust me, its worth the time to at least look into it and giving it a try.
These posts may help:
Meanwhile... on the query side of my architecture
Meanwhile... on the command side of my architecture
If you're brave enough (after digesting thru CQRS), then take a look at MediatR which implements the Mediator pattern (which basically wraps up command-query with notifications) and allows to work via pub-sub. The pub-sub model suits nicely in the Windows Service and services layer.

Identity 2.0.0 in MVC5 architecture advice

I'm trying to integrate the recently released ASP.NET Identity 2.0.0 into a 3-layer MVC application. I'm not sure I'm going in the correct direction. I can see two approaches to take.
In the first approach, I've gone with integrating Identity into each logical layer. Having some technical issues integrating but still developing.
In the second approach, go with a a self-contained encapsulated assembly dedicated for security.
I've gone with approach 1 at the moment, but questioning it all. Also, any other approaches to take?
Approach 1
Web
Startup.cs
/App_Start/Startup.Auth
/Controllers/Account
/Controllers/Manage
/Controllers/RolesAdmin
/Controllers/UserAdmin
/ViewModels
/Views
Business Logic
/Service/AccountService
/Service/ApplicationRoleManager
/Service/ApplicationUserManager
/Service/EmailService
/Service/SmsService
/Service/SignInHelper
Data
ApplicationDbContext
ApplicationUser
So, I've simply taken Identity and plugged it into each layer I see that fits.
I've put most of the log in the Business Logic layer, as it doesn't belong in the Web and there no 'real' database code for it to belong in the Data layer.
Side-issue: I'm a bit uncomfortable that in the Web/App_Start/Startup.Auth, I have to instantiate the Busness Logic object to call
app.CreatePerOwinContext(ApplicationDbContext.Create);
in the Data layer. I've yet to think about this more. This is another issue (but I see it is related to the architecture I've chosen).
Approach 2
Creating an assembly purely for Security which contains no layers, i.e. simply plug in Identity 2.0.0 into this one assembly. And my application can reference this. It goes against the layers though. But it encapsulates security. Given security objects can (or should) be resident throughout the application lifetime, this doesn't seem like a bad idea at all. Haven't thought about about scalability though.
I have taken approach 1, and when creating the context I have a helper class that I attempt to get the context from HttpContext.Current.["DbActiveContext"] and use it if it exists, if not create then new one, and use a single context for the entire application. So you do not end up with one context for aspnet idenity and another one for the rest of the app. It looks like you are trying to use a repository pattern in the first approach, if that is the case, then your model for your identity should be in the DB layer, and for full repository pattern, you should be using dependency injection when creating your objects, by doing so, you will not have a dependency until the object is created at run time.
namespace Data.Common
{
public class ConnectionHelper : IConnectionHelper
{
private ApplicationDbContext _context;
public ApplicationDbContext Context
{
get
{
if (_context == null && HttpContext.Current.Items["DbActiveContext"] != null)
{
_context = (ApplicationDbContext)HttpContext.Current.Items["DbActiveContext"];
}
else if (_context == null && HttpContext.Current.Items["DbActiveContext"] == null)
{
_context = new ApplicationDbContext();
HttpContext.Current.Items.Add("DbActiveContext", _context);
}
return _context;
}
set { _context = value; }
}
}
}
Also if you want to use the usermanager in the service layer with DI you can do something like:
public UserController()
: this(
new ApplicationUserManager(new UserStore<ApplicationUser>(new ConnectionHelper().Context)),
new UserService())
{
}
With the UserService signature like:
public class UserService
{
private readonly IRepository<ApplicationUser> _user;
private readonly UserManager<ApplicationUser> _userManager;
public UserService(IRepository<ApplicationUser> user,
UserManager<ApplicationUser> userManager)
{
_user = user;
_userManager = userManager;
}
public UserService()
: this(
new Repository<ApplicationUser>(new ConnectionHelper()),
new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ConnectionHelper().Context)))
{
}
I hope this helps you!

How to set up Ninject DI to create Hyprlinkr RouteLinker instances

I have an MVC4 Web API project and I making use of Mark Seemann's Hyprlinkr component to generate Uris to linked resources. (Customer -> Addresses for example).
I have already followed Mark's guide on Dependency injection with Web API (changing appropriately for Ninject) bit I can't quite work out what I should do to inject a IResourceLinker into my controllers.
Following Mark's guide my IHttpControllerActivator.Create create method looks like this:
IHttpController IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
var controller = (IHttpController) _kernel.GetService(controllerType);
request.RegisterForDispose(new Release(() => _kernel.Release(controller)));
return controller;
}
It is in this method that the Hyprlinkr readme suggests to create the RouteLinker. Unfortunately I'm not sure how to register this with Ninject.
I can't just bind like below, as this results in multiple bindings:
_kernel.Bind<IResourceLinker>()
.ToMethod(context => new RouteLinker(request))
.InRequestScope();
I've got rebind working like this:
_kernel.Rebind<IResourceLinker>()
.ToMethod(context => new RouteLinker(request))
.InRequestScope();
But I'm concerned that changing the ninject binding graph is potentially a bad thing to do on every request.
What is the best way to achieve this?
Update following the request from Paige Cook
I'm using rebind here:
IHttpController IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
_kernel.Rebind<IResourceLinker>()
.ToMethod(context => new RouteLinker(request))
.InRequestScope();
var controller = (IHttpController) _kernel.GetService(controllerType);
request.RegisterForDispose(new Release(() => _kernel.Release(controller)));
return controller;
}
IHttpControllerActivator.Create is called on every request. The rest of the bindings are made in the standard way, by standard I mean in the class generated by using the Ninject.MVC3 nuget package.
My controller looks like this:
public class CustomerController : ApiController
{
private readonly ICustomerService _customerService;
private readonly IResourceLinker _linker;
public CustomerController(ICustomerService customerService, IResourceLinker linker)
{
_customerService = customerService;
_linker = linker;
}
public CustomerModel GetCustomer(string id)
{
Customer customer = _customerService.GetCustomer(id);
if (customer == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return
new CustomerModel
{
UserName = customer.UserName,
Firstname = customer.Firstname,
DefaultAddress = _linker.GetUri<AddressController>(c => c.Get(customer.DefaultAddressId)),
};
}
}
Register a delegate Function to give you the linker
_kernel.Bind<Func<HttpRequestMessage, IResourceLinker>>()
.ToMethod(context => (request) => new RouteLinker(request));
Inject the delegate
readonly Func<HttpRequestMessage, IResourceLinker> _getResourceLinker;
public controller(Func<HttpRequestMessage, IResourceLinker> getResourceLinker) {
_getResourceLinker = getResourceLinker;
}
Use in your actions
public async Task<Thingy> Get() {
var linker = _getResourceLinker(Request);
linker.GetUri( ... )
}
If you only need to use RouteLinker from ApiController derivates, you don't really need to go through all the DI hoops.
You can just create it within the Controller like this:
var linker = new RouteLinker(this.Request);
IMO, using DI with RouteLinker first becomes valuable when you need a RouteLinker further down the stack - but then again, I also only use RouteLinker as a Concrete Dependency...
Thanks for adding the code sample. Based on what you have posted, you are running into your Bind/Rebind issue because you are issuing the _kernel.Bind<IResourceLinker> in the IHttpControllerActivtor.Create method every time.
You need to move the _kernel.Bind<IResourceLinker> to be registered the same way your are registering the rest of your bindings in the
...standard way, by standard I mean in the class generated by using the Ninject.MVC3 nuget package.
There should not be any need for the IResourceLinker to be binded multiple times, and this is why you are getting multiple instances, because the binding is firing every time a controller is created by the IHttpControllerActivator.
Update:
Sorry that I missed the need for an HttpRequestMessage as a constructor argument, I would go with Anthony Johnson's answer on this one.

What is the scope of my Ninject injected ObjectContext in my custom MembershipProvider (using Request scope)?

I use Entity Framework 4 and ASP.NET MVC 3. I made a custom membership provider and use Ninject to inject an EFAccountRepository into it (Bound IAccountRepository to EFAccountRepository).
This account repository has an ObjectContext injected into it. I also use this repository (and others) in my controllers. For this reason when I bound IContext to my ObjectContext, I set the scope to "per request" so the ObjectContext only lives in one request and is shared between the repositories.
I am sometimes get the following error when trying to log in:"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."
I wonder how often the membership provider gets instantiated. I injected the repository into the membership provider by marking the repository property with [Inject] and calling Kernel.Inject in the Application_Start function in the global.asax file.
If the provider gets instantiated more than once I would have to inject again I suppose. However, I don't get a null pointer exception, so I don't think that's it.
Update 1
Here's some code:
MyNinjectModule.cs
public override void Load()
{
Bind<IMyContext>().To<MyObjectContext>().InRequestScope();
// put bindings here
Bind<IAccountRepository>().To<EFAccountRepository>
}
Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var kernel = new StandardKernel(new MyNinjectModule());
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel));
kernel.Inject(Membership.Provider);
}
MyMembershipProvider.cs
[Inject]
public IAccountRepository accountRepository { get; set; }
public override bool ValidateUser(string username, string password)
{
// I get the exception here.
return (from a in accountRepository.Accounts
where a.UserName == username
&& a.Password == password
select true).SingleOrDefault();
}
EFAccountRepository.cs
private readonly IMyContext context;
public EFAccountRepository(IMyContext context)
{
this.context = context;
}
public IQueryable<Account> Accounts
{
get { return context.Accounts; }
}
MyObjectContext.cs
public class MyObjectContext : ObjectContext, IMyContext
{
public IObjectSet<Account> Accounts { get; private set; }
public FlorenceObjectContext()
: this("name=DomainModelContainer")
{
}
public FlorenceObjectContext(string connectionString)
: base(connectionString, "DomainModelContainer")
{
Accounts = CreateObjectSet<Account>();
}
}
PS: I'm always open to comments on my code in general ;).
The exception says that you are incorrectly handling disposing of your context. Somewhere you call context.Dispose (or have context in using) but after that you want to use context again which is not possible because context is already disposed. If you are using per request context you must dispose context only once at the end of request processing (when you are sure that no code will use the context).
You didn't specify a scope for your EFAccountRepository binding so it defaults to .InTransientScope(). This means a new instance of the object will be created each time you resolve the IAccountRepository [refer to https://github.com/ninject/ninject/wiki/Object-Scopes ].
Also, transient scope objects
are automatically garbage collected as soon as there are no references to them [Ninject doesn't cache them]
are not automatically disposed by anyone
In contrast, you bound MyObjectContext to IObjectContext .InRequestScope(). This means it will be reused when you are in the same HTTP request handling operation.
Also, a request scope object
won't be garbage collected until your http request is done
might be automatically disposed once the HTTP request is done, if it's IDisposable. [Not sure precisely when, but from other questions I have seen I suspect it depends on the version of Ninject]
Now, ObjectContext is IDisposable, so it seems reasonable to conclude that
an object reference to the IObjectContext exists, and you are using the IObjectContext outside of the HTTP request which it was created in.
Ninject has automatically disposed of it, since the HTTP request has completed.
In order to solve the issue, you need to figure out why your object context object reference is surviving so long, and consider either eliminating the long-livedness... or removing its dependency on short-lived (request-scoped) objects.
[note clearly the question already has an accepted answer, but I think the accepted answer was kind of hard to understand.]

Resources