I was abused on Twitter by @josecgomez this weekend on this topic so posting here.
The question is how to iterate through different companies in a server process. The Client way is to use SessionMod.SetCompany(). Stand up a new Service, Call SetCompany, life is good.
When on the server side though, you can change the state of your current instance and get confused easily. To do this correctly means either making REST Calls with the new Company as a header or standing up a ServiceRenderer in a suppressed transaction which can lead to interesting side effects - that one is not worth the fragility. So we came up with this functionality that works well. I honestly have not tried this in a BPM but donât see why this would not work for these. We use this approach a LOT on the server - especially in administration features or processes that span companies.
The first thing to understand is that a Server Session is not a single instance but rather a .NET Stack of Session Instances. The âCallContext.Current.Sessionâ variable is just a pointer to the top of the Stack. In most cases, there is just a single Session instance in the CallContext stack. But when you need to iterate over Companies to process something the Session Stack get pushed and popped around. Thatâs where âTemporarySessionsâ comes in.
First thing -
Security
When standing up a new Temporary Session, all the standard checks are performed on the session variable for permission. That means the âParent Sessionâ must be able to change to the indicated company just as on the client or runtime security exceptions will occur.
Lifetime
The lifetime of a Temporary Sessions is only the span of one server method call (One CallContext to be more exact but one server method call in general use). If you start a temporary session with alternative session variables, those settings will be lost on the next server call. You need to change the Session on the client and make multiple method calls as has always been done to preserve new Session settings. NOTE: Only one TemporarySession at a time can be in effect. Trying to create a nested TemporarySession will throw a runtime exception.
Visibility
When starting a Temporary Session, it will appear as the session. The Session property in a ContextBound object or CallContext.Curent.Session will return the new temporary session. This means you can start the temporary session in a process and be confident that the temporary session variables will be used in any code downstream in some lib you were not even aware of being executed. The only way you can determine if the Session is the original parent or a temporary session is by referring to the âSession.IsTemporaryâ property.
Creating
There are a couple of ways to create the Temporary Session based on your needs.
Fluent API
The simplest is to take advantage of the TemporarySessionCreator. This is a factory object that uses a fluent API so a series of âSetâ methods can be chained together:
CallContext.TemporarySessionCreator
.SetCompanyID(âEpic03â)
.Set(âSomeSessionVariableâ, âSomeValueâ)
.Create();
Note the mandatory âCreateâ method that finishes the statement and starts the Temporary Session.
Disposable - PREFERRED!!!
The Temporary Session is disposable so can be used in a âusingâ:
using (CallContext.TemporarySessionCreator.SetCompanyID(companyID).Create()) {}
This allows for easy iteration of lists with proper disposal such as:
foreach (var companyID in companyList)
{
using (CallContext.TemporarySessionCreator.SetCompanyID(companyID).Create())
{
//Your Code Here
Debug.WriteLine("TemporarySession Current Company=" + Session.CompanyID);
}
}
Usage
Pretty much anything inside of the âCreateâ block can be executed and it looks like the Session is something other than what was used on the client - because it is. The âparentâ Sessionâ was pushed onto the stack and the new temp one is pointed at by everything. You need to be cautious if you try to do too much in the alternate session or you might loop around and get a second nesting - something forbidden due to the complexity of keep the recursion straight.
Support
To say this is advanced stuff goes without saying. Calling Support with this outside of SDK scenarios - you probably wonât find much help. It is pretty powerful for some scenarios where you donât want to recurse from the client though so have it in the toolbox with other tools that you can injury your foot if mishandled.