I am using SimpleInjector
and want to create a UnitOfWork
Per WebRequest Using an UnitOfWorkFactory
.
I want to do this by using an ActionLiterAttribute
so that every web request will begin a new UnitOfWork
The only problem that I have is to pass the IUnitOfWorkFactory
to the ActionFilterAttribute
class.
There is a similar question about this online but there is a solution given using Ninject
, Unfortunately with SimpleInjection
there is no equivalent to Bind
a filter.
This is what I have done so far, not sure if it is correct.
I have created a SessionPerRequestActionFilter
public class SessionPerRequestActionFilter : ActionFilterAttribute
{
private readonly Func<IUnitOfWorkFactory> _unitOfWorkFactory;
private IUnitOfWork _unitOfWork;
public SessionPerRequestActionFilter(Func<IUnitOfWorkFactory> unitOfWorkFactoryProvider)
{
if (unitOfWorkFactoryProvider == null) throw new ArgumentNullException("_unitOfWorkFactory");
_unitOfWorkFactory = unitOfWorkFactoryProvider;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var unitOfWorkFactory = _unitOfWorkFactory.Invoke();
_unitOfWork = unitOfWorkFactory.BeginUnitOfWork();
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception == null)
_unitOfWork.Commit();
_unitOfWork.Dispose();
}
}
Then I added it to GlobalFilters
in my Global.ascx
page, but not happy with how I did it here. See my thoughts in the code snippet bellow.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); // <-- So First register all filters
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
#region Initialize SimpleInjector
var container = new Container();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.RegisterMvcIntegratedFilterProvider();
new AppHost(container).Init();
GlobalFilters.Filters.Add(new SessionPerRequestActionFilter(() => container.GetInstance<IUnitOfWorkFactory>())); // <-- Then in here I go and register the filter again.
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
#endregion
}
Surely there is a better way to do this? Is it perhaps more appropriate to use Property Injection
in SessionPerRequestActionFilter
?
Or is it perhaps better to remove this from the ActionFilter
and implement the UnitOfWork
in the BaseController
then injecting the factory into the controller?
I have seen so many examples online but not sure which one is the more modern approach.