Castle Windsor LifestylePerWebRequest - Only seems to resolve on the first web request for ISession - asp.net-mvc-3

I'm setting up my MVC project so that I resolve my ISession's on a PerWebRequest basis.
Here's what I have so far:
In my Castle Windsor Setup I register my ISession using a factory method:
Component.For<ISession>().UsingFactoryMethod(ctx => MsSql2008SessionFactory.OpenSession()).LifestylePerWebRequest()
In my Global.asax Application_Start() I Bind my ISession to NHibernate's CurrentSessionContext each time a request begins:
BeginRequest += delegate{
CurrentSessionContext.Bind(
MsSql2008SessionFactory.OpenSession());
};
EndRequest += delegate{
var session = MsSql2008SessionFactory
.SessionFactory
.GetCurrentSession();
if (session != null)
{
session.Dispose();
}
CurrentSessionContext
.Unbind(MsSql2008SessionFactory
.SessionFactory);
};
The first time I make a request to a page everything works fine.
The second time I make a request to a page I get an exception stating:
Session is closed! Object name: 'ISession'.
What am I not doing correctly?

This is how I do things may work for you. I use Fluent Nhibernate just in case some of the config doesn't jive.
public interface INHibernateSessionFactoryHelper
{
ISessionFactory CreateSessionFactory();
}
public class NhibernateSessionFactoryHelper
{
private static readonly string ConnectionString =
ConfigurationManager.ConnectionStrings["SqlConnectionString"].ToString();
public static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.ProxyFactoryFactory("NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate")
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<EntityMap>())
.Database(
MsSqlConfiguration.MsSql2008.ConnectionString(ConnectionString).AdoNetBatchSize(1000))
.Cache(
c =>
c.ProviderClass<SysCacheProvider>().UseSecondLevelCache().UseQueryCache().UseMinimalPuts())
.ExposeConfiguration(c => c.SetProperty(Environment.GenerateStatistics, "true")
.SetProperty(Environment.SessionFactoryName, "My Session Factory")
.SetProperty(Environment.CurrentSessionContextClass, "web"))
.Diagnostics(d => d.Enable().OutputToFile(#"c:\temp\diags.txt"))
.BuildSessionFactory();
}
}
Then my Windsor installer looks like this
public class NHibernateInstaller:IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ISessionFactory>().Instance(NhibernateSessionFactoryHelper.CreateSessionFactory()));
container.Register(Component.For<ISessionManager>().ImplementedBy<SessionManager>().LifestylePerWebRequest());
}
}
I have omitted the code for the SessionManager I use. Let me know if you would like it
UPDTAE: Here is the code I use for managing sessions and transactions( I found pieces of this scattered about the Internet but it all worked well without too much modification. ISessionManager is wired up per my previous example and injected in to the constuctor of my Services.
public interface ISessionManager : IDisposable
{
ISession Session { get; set; }
ISession GetSession();
}
public class SessionManager : ISessionManager
{
private readonly ISessionFactory _sessionFactory;
private TransactionScope _scope;
public SessionManager(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
#region ISessionManager Members
public ISession Session { get; set; }
public ISession GetSession()
{
if (Session == null)
{
Session = _sessionFactory.OpenSession();
if (!CurrentSessionContext.HasBind(_sessionFactory))
{
_scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions {IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted});
Session.BeginTransaction(IsolationLevel.ReadCommitted);
CurrentSessionContext.Bind(Session);
}
}
Session = _sessionFactory.GetCurrentSession();
Session.FlushMode = FlushMode.Never;
return Session;
}
public void Dispose()
{
if (CurrentSessionContext.HasBind(_sessionFactory))
{
CurrentSessionContext.Unbind(_sessionFactory);
}
try
{
Session.Transaction.Commit();
_scope.Complete();
_scope.Dispose();
Session.Flush();
}
catch (Exception)
{
if (Session.Transaction != null && Session.Transaction.IsActive)
{
Session.Transaction.Rollback();
}
throw;
}
finally
{
Session.Close();
Session.Dispose();
}
}
#endregion
}
Example Constructor:
private readonly ISessionManager _sessionManager;
private readonly ISession _session;
public UserService(ISessionManager sessionManager)
{
_sessionManager = sessionManager;
_session = sessionManager.GetSession();
}

The answer to this turned out to be quite simple.
The repository that I was injecting my ISession into had a Singleton lifestyle.
This meant that the ISession that had been injected on the first request was also being used for the subsiquent requests (because my repository class was only being created at the start of the application) and was thus already disposed.

Related

how to fix Error No DataBase Provider when Everything is okay

When I want to Insert A New Object into the db bellow Error Occured:
No database provider has been configured for this DbContext
Services:
private IConfiguration config;
public Startup(IConfiguration config) => this.config = config;
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFrameworkSqlServer().AddDbContext<DataContext>(options => options.UseSqlServer(config["ConnectionStrings:MainConnection"]));
services.AddMvc();
}
DataContext:
public class DataContext:DbContext
{
public DataContext() { }
public DataContext(DbContextOptions<DataContext> options) : base(options) { }
public DbSet<Request> Request { get; set; }
public DbSet<AdminAccept> AdminAccept { get; set; }
public DbSet<Payment> Payment { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
base.OnConfiguring(builder);
}
}
Insert command :
public async Task <int> SaveToStorageAsync()
{
using (DataContext context=new DataContext())
{
context.Request.Add(this);
return await context.SaveChangesAsync();
}
}
however migrations and database created succefully
I solved it finally.
everything is okay but use of using expression cause an error.(I wonder why)
to solving it first of all I removed a using and declare a DataContext as parameter:
public async Task<int> SaveToStorageAsync(DataContext context)
{
context.Request.Add(this);
return await context.SaveChangesAsync();
}
after it initiate constructor in the main controller :
DataContext context;
public HomeController(DataContext context)
{
this.context = context;
}
and finally call function by sending context as a parameter.
hopped you used in your scenarios and good luck
Since you register the DataContext with the constructor receiving a DbContextOptions<DataContext> option.You also need to pass that when you create a DataContext
var optionsBuilder = new DbContextOptionsBuilder<DataContext >();
optionsBuilder.UseSqlServer("Your connection string");
using (DataContext context = new DataContext (optionsBuilder.Options))
{
context.Request.Add(this);
return await context.SaveChangesAsync();
}
I suggest that you could use dbContext by DI in controller which is a more recommended way in asp.net core:
public class StudentsController : Controller
{
private readonly DataContext _context;
public StudentsController(DataContext context)
{
_context = context;
}
public async Task <int> SaveToStorageAsync()
{
_context.Request.Add(this);
return await context.SaveChangesAsync();
}
}
The two ways are included in below link:
https://learn.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext#configuring-dbcontextoptions

How to properly set up WebApi, EasyNetQ and Ninject?

This is what I have thus far. I'm stuck on the concept/where to implement the IBus injection/creation point (the publisher). I was trying to keep the publisher functionality all within the project and not create a separate service for it.
bus = RabbitHutch.CreateBus("host=localhost", x => x.Register<IEasyNetQLogger>(_ => logger));
This is my first pass at this so I'm open to suggestions and best practice advice :-)
Things left to do:
create a rabbitmq config file with proper settings defining queue name and ?
create a message handler that takes care of connection management that is?
create the publisher at app start up, dispose properly when ?
EasyNetQ Wrapper to replace EasyNetQ internal IoC, Ninject replacement:
public class NinjectContainerWrapper: IContainer, IDisposable
{
public NinjectContainerWrapper()
{
}
//ninject container/kernal? here
//private readonly ISomeNinjectInterface container;
public TService Resolve<TService>() where TService : class
{
throw new NotImplementedException();
}
public IServiceRegister Register<TService, TImplementation>()
where TService : class
where TImplementation : class, TService
{
throw new NotImplementedException();
}
public IServiceRegister Register<TService>(Func<EasyNetQ.IServiceProvider, TService> serviceCreator) where TService : class
{
throw new NotImplementedException();
}
public void Dispose()
{
throw new NotImplementedException();
}
}
NinjectWebCommon.cs
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IAppSettings>().To<AppSettings>();
kernel.Bind<IDmpeService>().To<DmpeService>();
kernel.Bind<IPublisher>().To<DmpePublisher>();
kernel.Bind<IEasyNetQLogger>().To<GdmEasyNetQLogger>();
kernel.Bind<ILoggingService>().ToMethod(x =>
{
var scope = x.Request.ParentRequest.Service.FullName;
var log = (ILoggingService)LogManager.GetLogger(scope, typeof(LoggingService));
return log;
});
}
the publisher class:
public class DmpePublisher: IPublisher
{
private readonly IEasyNetQLogger _logger;
private readonly IAppSettings _appSettings;
private readonly IBus bus = null;
public DmpePublisher(IEasyNetQLogger logger, IAppSettings appSettings)
{
this._logger = logger;
this._appSettings = appSettings;
// register our alternative container factory
RabbitHutch.SetContainerFactory(() =>
{
var ninjectContainer = new NinjectContainerWrapper();
// wrap it in our implementation of EasyNetQ.IContainer
//return new NinjectContainerWrapper(ninjectContainer);
});
bus = RabbitHutch.CreateBus("host=localhost", x => x.Register<IEasyNetQLogger>(_ => logger));
}
public void PublishMessage(Messages.IMessage message)
{
throw new NotImplementedException();
//log post
//_logger.InfoWrite("Publishing message: {0}", message);
}
}

Ninject Interception in WebAPI and parameterless constructor failing

I have an MVC4 site that uses both MVC and WebAPI in it. All was going well till I tried to change my classes to have a cross cutting AOP class that would help with caching data. I am now finding that when I call a method that does not have the InterceptAttribute on it, it will crash because Ninject didn't inject with a parameter, and it fails.
My BLL class looks like this:
public class FooBLL
{
#region Private Variables
private readonly IDAL _context;
#endregion
#region Constructor
public Foo(IDAL context)
{
_context = context;
}
#endregion
#region Public Methods
public List<Bar> GetAllBars()
{
return _context.GetAllBars();
}
public List<Bar> GetTwoBars()
{
return _context.GetTwoBars();
}
#endregion
}
My WebApi Controller looks like this:
public class FooController : ApiController
{
#region Private Variables
private readonly FooBLL _fooBll;
#endregion
#region Constructor
public FooController(FooBLL fooBll)
{
_fooBll = fooBll;
}
#endregion
#region Public Methods
#region Estimate Types
#region Get
public List<Bar> GetAllBars()
{
return _fooBll.GetAllBars();
}
public List<Bar> GetTwoBars()
{
return _fooBll.GetTwoBars();
}
#endregion
#endregion
#endregion
}
In my Website, I created the following Ninject classes for resolving the controllers:
public class NinjectRegistrations : NinjectModule
{
public override void Load()
{
Kernel.Bind<IDAL>().To<DAL>().InSingletonScope();
}
}
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(this.kernel.BeginBlock());
}
}
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
var disposable = this.resolver as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
this.resolver = null;
}
public object GetService(Type serviceType)
{
if (this.resolver == null)
{
throw new ObjectDisposedException("this", "This scope has already been disposed");
}
return this.resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (this.resolver == null)
{
throw new ObjectDisposedException("this", "This scope has already been disposed");
}
return this.resolver.GetAll(serviceType);
}
}
In Global.asax I then register this resolver:
NinjectHelper.Kernel = new StandardKernel(modules);
var ninjectResolver = new NinjectDependencyResolver(NinjectHelper.Kernel);
DependencyResolver.SetResolver(ninjectResolver); // MVC
GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; // Web API
//Register Filter Injector
GlobalConfiguration.Configuration.Services.Add(typeof(System.Web.Http.Filters.IFilterProvider), new NinjectWebApiFilterProvider(NinjectHelper.Kernel));
Things were fine till I added the attribute Cache using Ninject.Extensions.Interception.Attributes.InterceptAttribute.
The class now looks like this (note that I added a parameterless constructor and marked one of the methods as virtual, these are both required for the Interception to work):
public class FooBLL
{
#region Private Variables
private readonly IDAL _context;
#endregion
#region Constructor
public Foo(IDAL context)
{
_context = context;
}
public Foo()
{
}
#endregion
#region Public Methods
public List<Bar> GetAllBars()
{
return _context.GetAllBars();
}
[Cache(DefaultTimeoutMinutes = 20)]
public virtual List<Bar> GetTwoBars()
{
return _context.GetTwoBars();
}
#endregion
}
Now on the WebAPI controller, when I call GetToBars(the method with the Intercept Attribute), everything still works fine.
However, when I call GetAllBars(the method that doesn't have the Intercept Attribute), I fail with an exception that _context is null.
Any help would be greatly appreciated.
Ben

"The type IUnitOfWork does not have an accessible constructor" with Umbraco 6.1, UmbracoApiController (Web API) & Dependency Injection (Unity)

I am using Umbraco 6.1 with an UmbracoApiController which has a IUnitOfWork injected into it's constructor. To inject the dependencies, I am using Unity, like I have in the past with standard Web API projects. Normally, I set unity up in the Global.asax.cs. As Umbraco does not have this I have created my own UmbracoEvents handler, which inherits from IApplicationEventHandler, and has the methods:
OnApplicationInitialized
OnApplicationStarting
OnApplicationStarted
ConfigureApi
In the OnApplicationStarted method I set up my EF database, db initializer etc and call ConfigureApi to set up Unity. My OnApplication Started and ConfigureApi methods looks like this:
public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
_applicationContext = applicationContext;
_umbracoApplication = umbracoApplication;
_contentService = ApplicationContext.Current.Services.ContentService;
this.ConfigureApi(GlobalConfiguration.Configuration);
Database.SetInitializer(null);
PropertySearchContext db = new PropertySearchContext();
db.Database.Initialize(true);
}
private void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterType<PropertiesApiController>();
unity.RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager());
config.DependencyResolver = new IoCContainer(unity);
}
My Controller code:
public class PropertiesApiController : UmbracoApiController
{
private readonly IUnitOfWork _unitOfWork;
public PropertiesApiController(IUnitOfWork unitOfWork)
{
if(null == unitOfWork)
throw new ArgumentNullException();
_unitOfWork = unitOfWork;
}
public IEnumerable GetAllProperties()
{
return new[] {"Table", "Chair", "Desk", "Computer", "Beer fridge"};
}
}
My Scope Container/IoC Container code: (as per http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver)
public class ScopeContainer : IDependencyScope
{
protected IUnityContainer container;
public ScopeContainer(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
if (container.IsRegistered(serviceType))
{
return container.Resolve(serviceType);
}
else
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (container.IsRegistered(serviceType))
{
return container.ResolveAll(serviceType);
}
else
{
return new List<object>();
}
}
public void Dispose()
{
container.Dispose();
}
}
public class IoCContainer : ScopeContainer, IDependencyResolver
{
public IoCContainer(IUnityContainer container)
: base(container)
{
}
public IDependencyScope BeginScope()
{
var child = this.container.CreateChildContainer();
return new ScopeContainer(child);
}
}
My IUnitOfWork code:
public interface IUnitOfWork : IDisposable
{
GenericRepository<Office> OfficeRepository { get; }
GenericRepository<Property> PropertyRepository { get; }
void Save();
void Dispose(bool disposing);
void Dispose();
}
My UnitOfWork implementation:
public class UnitOfWork : IUnitOfWork
{
private readonly PropertySearchContext _context = new PropertySearchContext();
private GenericRepository<Office> _officeRepository;
private GenericRepository<Property> _propertyRepository;
public GenericRepository<Office> OfficeRepository
{
get
{
if (this._officeRepository == null)
{
this._officeRepository = new GenericRepository<Office>(_context);
}
return _officeRepository;
}
}
public GenericRepository<Property> PropertyRepository
{
get
{
if (this._propertyRepository == null)
{
this._propertyRepository = new GenericRepository<Property>(_context);
}
return _propertyRepository;
}
}
public void Save()
{
_context.SaveChanges();
}
private bool disposed = false;
public virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
I have used unity/DI with MVC4/WebAPI controllers and this implementation of UnitOfWork many times before without issue, so I'm thinking it's Umbraco specific.
I have also debugged the application and made sure that it hits OnApplicationStarted and that its parameters are not null.
The GetAllProperties method in the controller is just a test method to make sure it is all working fine, however, when I try and access this action I get the error:
"The type IUnitOfWork does not have an accessible constructor"
Does anyone have experience with using Umbraco 6.1 and it's UmbracoApiController with dependency injection/Unity?
Also, on an unrelated note, is there a way to return JSON instead of XML in the action? In Web API you would just define the formatter in the WebApi.config but there is none in Umbraco.
Thanks,
Justin
In case you haven't found a solution to your problem? Download this nuget package and right after building your unity container:
GlobalConfiguration.Configuration.DependencyResolver =
new Unity.WebApi.UnityDependencyResolver(Bootstrapper.Container);
Notice the namespace which is different than Unity.Mvc4.UnityDependencyResolver.

MVC3, Unity Framework and Per Session Lifetime Manager Issue

In a simple word I try to create Lifetime manager for Unity framework by using Http Session in my MVC3 project. My sample implementation of lifetime manager is:
public class UnityPerSessionLifetimeManager : LifetimeManager
{
private string sessionKey;
private HttpContext ctx;
public UnityPerSessionLifetimeManager(string sessionKey)
{
this.sessionKey = sessionKey;
this.ctx = HttpContext.Current;
}
public override object GetValue()
{
return this.ctx.Session[this.sessionKey];
}
public override void RemoveValue()
{
this.ctx.Items.Remove(this.sessionKey);
}
public override void SetValue(object newValue)
{
this.ctx.Session[this.sessionKey] = newValue;
}
}
In my global.asax.cs I replaced default controller factory with my own UnityControllerFactory
public class UnityControllerFactory : DefaultControllerFactory
{
private IUnityContainer container;
public UnityControllerFactory(IUnityContainer container)
{
this.container = container;
this.RegisterServices();
}
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
if (controllerType != null)
{
return this.container.Resolve(controllerType) as IController;
}
return null;
}
private void RegisterServices()
{
this.container.RegisterType<IMyType, MyImpl>(new UnityPerSessionLifetimeManager("SomeKey"));
}
}
}
I set breakpoints on each function of UnityPerSessionLifetimeManager class, I noticed that when controller factory tries to solve dependencies of my controller, the HttpContext.Session is actually null, so the code fails retrieve from session or save to session.
Any idea why session is null at this stage?
My mistake, I should change code of UnityPerSessionLifetimeManager class to be
public class UnityPerSessionLifetimeManager : LifetimeManager
{
private string sessionKey;
public UnityPerSessionLifetimeManager(string sessionKey)
{
this.sessionKey = sessionKey;
}
public override object GetValue()
{
return HttpContext.Current.Session[this.sessionKey];
}
public override void RemoveValue()
{
HttpContext.Current.Session.Remove(this.sessionKey);
}
public override void SetValue(object newValue)
{
HttpContext.Current.Session[this.sessionKey] = newValue;
}
}
because when the constructor was called to register type, session state is not ready yet and I already assigned http context of that time to a variable. But in later Get/Set functions session state is ready.

Resources