Multitenancy, help understand concept of WorkContext - asp.net-mvc

While trying to understand how a multitenant environment works, I've came up to the concept of WorkContext.
Introduction:
In a multitenant environment Tenants are Clients which share similar functionality, and run under a single instance of a ROOT application. In order to be able to add tenant specific functionality I came across a conclusion that Dependency Injection is the right solution for my case.
Each tenant should have it's own IoC Container, in order to be able to Resolve its dependencies at runtime.
But when trying to implement the theory I have some troubles with the wrapping out all tenant specific data.
While digging the internet it seems that there must exist some sort of a TenantContext. So each tenant has it's own isolated Context.
The problem is that I don't understand the true LifeCycle of such a Context.
Question 1:
What is the lifecycle diagram of a tenant specific WorkContext, Where should I store it, When it should be created/disposed ?
NOTE: If the question 1 is provided, there is no need to answer the above one.
Suddenly I've found Orchard Project which seems to be a true masterpiece. Inside Orchard, the Context i'm talking about is called WorkContext.
I'm trying to understand the concept of WorkContext in Orchard Project. As far as I understand, here are some thoughts about WorkContext:
The WorkContext is a per-request lifetimeobject.
It is stored in HttpContext.Items (also there is a thread static implementation..).
It wraps the tenant IoC scope (ShellContext -> ShellContainer).
It is accessed through IWorkContextAccessor.
What I don't understand is:
Question 2:
Why do we need to include IWorkContextAccessor instance in route's DataTokens like this: routeData.DataTokens["IWorkContextAccessor"] = _workContextAccessor; ? Is this really necessary?

Kind of big question :-).
Firstly, WorkContext is more or less an abstraction of the HTTP context. A WorkContext lives as long as its work context scope lives (see IWorkContextAccessor that you can use to create work context scopes) so actually you can have multiple work contexts per request and you can have a work context independently of a request too (this happens in background tasks).
Such work contexts are thus externally managed contexts and thus somehow have to "travel" along with their scope until the latter is terminated: in Orchard the WC is either carried in the HTTP Context or in a thread static field (what is not good enough and should be changed).
Thus basically a work context scope is the lowest dependency scope commonly used. It also has a parent, the shell's scope: this is the shell context (or more precisely, its lifetime scope). You can access a shell's (what is most of the time equal to a tenant) context through IOrchardHost.GetShellContext(). Work context scopes are actually created from the shell context's lifetime scope.
This also has a parent BTW that is the application-wide HostContainer.
Most of the time you don't have to manage the WC yourself since the ambient WC around requests and background tasks are managed for you.
Regarding your second question: I'm not entirely sure about this but AFAIK passing the WCA to the routeData just serves as a workaround to be able to access it (and thus, Orchard services) from strange places like HTML helpers and attributes that are not resolved through the DI container.
Edit: also added this to the Dojo Library, redacted and improved: http://orcharddojo.net/orchard-resources/Library/Wiki/WorkContext

Related

Autofac InstancePerRequest scope - reuse the scope instance to other places

I am using Autofac as a dependency injection container in my project. I would like to make use of InstancePerRequest scope as I don't want those objects to outlive a request.
Below is the code I am using in the gateway class where I know each of my request will pass through it.
using (var scope = _container.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag))
{
var service = scope.Resolve<MyTestService>();
...
}
Now in my code I locate several other classes where I need to resolve the MyTestService which at the moment is causing an exception with a message No scope with a Tag matching 'AutofacWebRequest'. The exception is because I am calling the resolve on a container instance, whereas I should call resolve on the same scope instance, as shown above.
Can someone please help me to know how do I access the same scope instance at those places in my code? I can't keep calling the BeingLifetimeScope in all the classes.
Unfortunately I'm stuck on a phone and my house is being remodeled so I have no computer access. As such you'll get a shorter answer with no code but it should unstick you.
You say you've read the docs, so you should know:
When you create a scope in those using blocks it's not the same as the current request scope.
If your service is used inside an existing request then you should just be injecting what the service needs right into the constructor, not doing service location with a scope.
If your service is not used inside an existing request then you're on your own to figure out how to mimic a request around your service. There's no fixed way to deal with that since it's app specific.
If the whole point in needing a request scope is to get dependencies registered per request to resolve outside a request then you should switch to instance per lifetime scope.
If you must - and it's an anti-pattern, but if you must - you can put a constructor parameter in your service that is an ILifetimeScope. That will get the current scope injected.
It's not really possible from your question to tell why you need the scope. I'm guessing there may be better ways to do what you're trying to do but being stuck on my phone I can't really expand on the million possibilities and ways to work around doing what you say you need to do. In future questions consider explaining more about the context - why your service needs to pass through a "gateway" and why you're in the situation and not just injecting constructor parameters and letting Autofac integration do the heavy lifting.
Regardless, this should get you unstuck. If not, you'll need to clarify your question with additional context and maybe someone else can hop in.

Refactoring large application for ObjectFactory.GetInstance to use nested containers

I have a large application which uses the old way of getting instances using ObjectFactory.GetInstance().
Now I want to move to application to the more correct way of injecting dependencies using constructor injection. However, it is almost impossible to convert all code at once (some static classes use ObjectFactory.GetInstance, other services do not have constructors with all dependencies, ...).
I was wondering if there is a way of replacing ObjectFactory.GetInstance calls with an replacement that uses the current nested container, e.g. replacing all ObjectFactory.GetInstance with Ioc.GetCurrentNestedContainer().GetInstance, to get it quickly up an running.
But how would I could I implement Ioc.GetCurrentNestedContainer to return the currently active nested container?
I can not inject IContainer in all these classes (some are static or have no corresponding
constructor), so they can not use constructor injection (yet).
DI is used in MVC, WCF, and Task based scenarios in this application.
Whilst I can't talk about WCF and task based scenarios, I can offer my recommendation for MVC (having spent time looking the options to a similar problem myself.
The solution to I've come across and ultimately settled for after seeing recommendations by StructureMap's creator, is to have a HttpContext bound nested container created on each request and stored within HttpContext.Items. From here you can reference the container by casting the instance stored within HttpContext.Items to an IContainer.
Infact, this is the same solution used within the StructureMap.MVC5 nuget package.
With this solution in mind, there's nothing to stop you replacing the ObjectFactory with with your own factory that returns the nested container from HttpContext.Items.
Update:
If HttpContext isn't available to you then the only other options I'm aware of is to create your own instance of the object factory that creates a new container and stores it in a Lazy<T> as suggested here and on the StructureMap's Google Groups page here.
I was going to suggest possiblity posting this question on the StructureMap Google Groups, but I see you've already done that. As an avid StructureMap user I'm keen to see what other suggestions arise from your post so I will be watching closely.

Replacement for Dependency Injection Container in Rails

I have read dozens of articles about this and still have some questions.
How are services used in multiple parts of the system? For example, I have a permissions component that is used by several other classes during a request. Right now, I have made it a singleton. I have been using singletons as the entry point to portions of my domain (various services) that need to be reused during a request. This seems to be the only way I can access these services in different parts of the system without reinstantiating them or without throwing them in a global variable. In other systems, I would make it a normal class and set it's lifecycle to "request". The container would make sure that it is shared within the request and release it for garbage collection.
I have thought about using a service locator which stores services in Thread.current. But this feels like I'm getting desperate.
The main way I've seen that people accessing these dependencies is to wrap the dependency in a method:
class A
def some_dep
SomeService.instance
end
end
In tests, some_dep is overridden to return a mock or whatever. This seems like the best so far but still feels hackish.
My options for using services within a request seem to be:
1) Put them in a global variable / Thread.current.
2) Use a service locater.
3) Pass dependencies around manually (complete disaster).
4) Singleton.
Two questions:
1) What is the best approach for making services available to multiple parts of the system without reinstantiating?
2) What is the best approach for a class to manage those dependencies?
Note:
I understand that I can put reusable functionality into modules. IMO, however, modules are great for purposes of staying DRY but not for carrying state around the system (i.e. which tenant you're on in a multitenant application).

Should service layer have access to HttpContext?

I'm building an application that roughly follows the repository pattern with a service layer on top, similar to early versions of Conery's MVC Storefront.
I need to implement a page that returns all users except for the current user. I already have GetUsers() methods on the repository and service layers, so the question is where to apply the "except for the current user."
Should the service layer be aware of HttpContext, thus applying this rule? I am tempted to just pass in the current user (id) from the controller to this service method, but it seems cleaner if the service layer was HttpContext-aware and could do this on its own.
One obvious alternative is to apply this rule directly within the Controller, but I'm just not hot on that idea...
Edit - just to comment on the answers: I see the issues with the reverse dependency problem, something I was completely overlooking. I'm marking Mehrdad's as the answer due votes, but everyone has really provided a valuable response worth reading!
Absolutely not. My mindset in designing these kind of things is like this: I assume I need to write a Windows based app along with the Web application and try to minimize dependency on Web specific stuff. Passing HttpContext directly will increase coupling of your service layer to your Web UI layer which is not ideal.
The answer is, no.
Not only should the Service Layer have no dependency on the current Presentation Layer, in my opinion it should have no dependency on the current application. For instance, I would not use a custom AppContext class as JonoW suggested here.
Instead, pass the current user as a parameter to the GetAllUsersExceptForTheCurrentUser method.That way, the service can be used by any application that needs to process users, not only the current application.
You should not create a reverse dependency between your service layer and the web tier. Consider what happens when you want to extend your service layer to work with a forms-based application or windows service. Now you've got to work around the web dependency to get your same methods to work or duplicate some (perhaps, small, but still duplicate) code. You would be better served to extract the user's identifier into something useful in the context of the service layer and use that value with the service layer. Handling the filtering on the web site is also acceptable, though if you do it more than once it would need to be refactored into a common place and the service layer is the natural spot for it.
I find it good practice to build a custom AppContext class which contains my current user object (as well as other contextual data). This class has no references to System.Web. Any service methods that need to be context aware should have an AppContext parameter (e.g. for checking security rights, or getting the current user as in your case). Populate this object in the web-tier and keep it in session if you need to. This way your service layer knows nothing about System.Web.
No. Doing so will make your code harder to test and re-use.
I tend to build an infrastructure interface for this sort of thing (call it IAuthentication or something) and expose a CurrentUser property on it. Then I'd inject this into my service via its a constructor. i.e. public MyService(IAuthentication auth)
Finally you'd can build an HttpContext aware implementation of IAuthentication (say WebAuthentication).
Now when you create your service you create its dependencies as well:
var myService = new MyService(new WebAuthentication());
var otherUsers = myService.GetAllOtherUsers();
If you are using an IoC container the ugly dependency can even go away!

Where to instantiate Data Context (adapter, connection, session, etc) in MVC?

We are building an ASP.NET MVC site, and I'm struggling with where to define a connection to best enable unit testing (I use 'connection' generically - it could be a session, a connection, an adapter, or any other type of data context that can manage transactions and database operations).
Let's say we have 3 classes:
UserController
UserService
UserRepository
In the past, we'd do something like this within a method of the UserService:
Using (ISomeSession session = new SomeSession())
{
session.StartTransaction();
IUserRepository rep = new UserRepository(session);
rep.DoSomething();
rep.Save();
session.Commit();
}
However, it wasn't really possible to unit test this since the dependency on SomeSession wasn't injected. However, if we use D.I. to inject the dependency in the UserService, the session hangs around for the life of the UserService. If there are multiple services called from the UserController, each could have sessions just hanging around until the UserController is garbage collected.
Any thoughts on how to better manage this? Am I missing something obvious?
Edit
Sorry if I wasn't clear - I understand that I can use Dependency Injection with the Session/Data Context, but then it's being maintained over the life of the Service class. For any longer-running actions/methods (i.e. let's say the service is being called by a batch process), this could lead to a lot of open sessions for no reason other than adding testability.
As RichardOD correctly observed, you can't use live database connections for writing unit tests. If you are doing it, then you are integration testing.
I have separate implementations for my repository interface, one real repository, and one fake repository for unit testing. The fake repository works on a generic list instead of a real data context. I am using DI (with Ninject to make things more comfortable, but you can do it just as well by hand) to inject the correct repository.
There are only very few instances in which I am unit testing with real connections, but that's a unit test for my repository class, not for any controller, UI or Business layer objects.
Edit: With the comment you added, I think I now understand what you were actually asking for. Funny you'd ask something about that, since I worked on the very same subject last week :-)
I instantiate the data context inside a very thin wrapper and put the context inside the HttpContext.Current.Items dictionary. This way, the context is global, but only for the current request.
Still, your question's subject is highly misleading. You were asking "where to instantiate a data context for unit testing" and the answer is that you usually don't. My unit tests still operate on fake repositories.
The easiest way is to have a Connectionstring that you define in web.config for development and production. For Unittests you define it in app.config of your Testproject.

Resources