Last post Mar 05, 2012 05:36 AM by james-world
Mar 03, 2012 10:27 PM|alex.gadea|LINK
I have an API written in MVC that I am trying to move over to WebAPI and am running into a problem in how our repositories are injected into controllers. Each repository has a datacontext and a requestcontext injected into it that requires call specific
information such as the UserId and AccountId. With WebAPI, I use a DelegatingHandler to populate these values and then I store the values in Request.Properties to pass it around between different delegating handlers. The problem is that our existing architecture
using static factory methods that are called by Autofac to generate the approprate datacontext and requestcontext. These methods had used Thread.CurrentPrincipal to get the info that has been populated by an IHttpModule. I can not grok how I should get the
appropriate values into a datacontext and requestcontext that can then be injected into the repositories that are injected into the controllers.
For example, the AccountsController constructor looks like this:
public AccountsController(IAccountService accountService)
The AccountService constructor looks like this:
public AccountService(IDefaultDataContext dataContext, IRequestContext requestContext)
Autofac calls a static method that looks like the below:
public static IClientDataContext GetClientDataContext()
if (Thread.CurrentPrincipal is CustomPrincipal)
ObjectId clientid = ((CustomIdentity)((CustomPrincipal)Thread.CurrentPrincipal).Identity).AccountId;
if (clientid == ObjectId.Empty)
throw new ArgumentNullException("The client ID could not be retrieved while attempting to get a ClientDataContext.");
throw new ArgumentNullException("An attempt was made to set a ClientDataContext while the current principal was not set to a custom principal.");
So, any suggestions on the appropriate way to refactor these injections so that my repositories are populated with the appropriate values?
Mar 05, 2012 03:59 AM|james-world|LINK
Hmmm. For me the idea of a "context" implies that, as Don Box was always fond of saying, you should be able to "reach up into the context" from wherever you are. Calling them "contexts" makes it imho, grate slightly with the idea they need to be injected.
But with that idea in mind, you don't necessarily need to have fully populated the contexts before you inject them: You could have your static methods lazily create them on the current thread context using a ThreadStatic property to store a thread-specific
context instance. That way you can inject the references into your controllers up front and then have the delegating handlers update them before the repositories have acted. Consider using a Lazy<T> on a ThreadStatic property for your datacontext and requestcontext.
Not sure about how performance would be affected doing it this way, but it won't be insignificant. You'll also need to consider the ramifications of propagating the context if you are processing a single request on multiple threads.
Mar 05, 2012 05:36 AM|james-world|LINK
I had another idea that is much cleaner... I'm not sure how lifetime management works in Autofac, but if you create per-request instances of your IXXXContext classes then you can inject these into your repository AND also an ActionFilter. The filter will
have access to the request and can set the relevant context properties you need.