I’m working on an ASP.NET MVC 4 application + NHibernate/Fluent NHibernate + Ninject application.
I’ve created a separate module to resolve the dependencies of ISession and ISessionFactory s below,
public class RepositoryModule: NinjectModule
{
public override void Load()
{
Bind<ISessionFactory>()
.ToMethod(e => Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("DbConnString")))
.Cache(c => c.UseQueryCache().ProviderClass<HashtableCacheProvider>())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Post>())
.BuildConfiguration()
.BuildSessionFactory())
.InSingletonScope();
Bind<ISession>()
.ToMethod((ctx) => ctx.Kernel.Get<ISessionFactory>().OpenSession())
.InRequestScope();
}
}
I’ve a repository class BlogRepository that implements IBlogRepository.
public class BlogRepository : IBlogRepository
{
private readonly ISession _session;
public BlogRepository(ISession session)
{
_session = session;
}
public IList<Post> Posts(int pageNo, int pageSize)
{
var query = _session.Query<Post>()
.Where(p => p.Published)
.OrderByDescending(p => p.PostedOn)
.Skip(pageNo * pageSize)
.Take(pageSize)
.Fetch(p => p.Category);
query.FetchMany(p => p.Tags).ToFuture();
return query.ToFuture().ToList();
}
// others
}
I need an instance of BlogRepository in a custom model binder.
I’ve tried something like this in the Global.asax.cs.
ModelBinders.Binders.Add(typeof(Post), new PostModelBinder(Kernel.Get<IBlogRepository>()));
At the first request everything works fine but from the second request I’m getting
session is closed error
. Any suggestions?
This is because
ModelBinderhas longer lifecycle than one request. As you can see you are registeringPostModelBinderusing thenewoperator. MVC application keeps reference to this binder and the binder has reference toIBlogRepository, whoseISessionwill be disposed at the end of the first request.You can solve this by using factory:
Instead of
IBlogRepositoryyou will inject factoryIBlogRepositoryFactoryobject, and then create newIBlogRepositoryon eachBindModelcall.To accomplish this, you can use Ninject factory extension.
Or by create own factory as described here in accepted answer: Inject a dependency into a custom model binder and using InRequestScope using Ninject