--> Useful class : System.Runtime.Remoting.Messaging.CallContext - Impersonation Failure

Useful class : System.Runtime.Remoting.Messaging.CallContext

We had a scenario about a week ago where certain session metadata needs to be made available to an internal framework we're developing. This data doesn't neccesarily have anything to do with the domains participating in the processing of the request but at the same time needs to be available should it be required anywhere in the call chain. Something similiar to the session state used in ASP.NET was required.

The CallContext class in the System.Runtime.Remoting.Messaging namespace (defined in mscorlib) was more or less exactly what we were looking for.

CallContext is a specialized collection object similar to a Thread Local Storage for method calls, and provides data slots that are unique to each logical thread of execution. The slots are not shared across call contexts on other logical threads. Objects can be added to the CallContext as it travels down and back up the execution code path, and examined by various objects along the path.

For example, say you've got the following object that needs to be available for the duration of your call execution path :

public class SomeSessionData

{

      string someArbData = string.Empty;

      public SomeSessionData()

      {

      }

      public SomeSessionData(string someArbData)

      {

            this.someArbData = someArbData;

      }

     

public string SomeArbData

      {

            get

            {

                  return someArbData;

            }

            set

            {

                  someArbData = value;

            }

      }

}

Adding this to the CallContext is simple :

SomeSessionData data = new SomeSessionData("arbdata");

CallContext.SetData("myKey",data);

 

This data will now be available for the complete code execution path, anywhere down or up the call stack you can access this object again :

SomeSessionData data = (SomeSessionData)CallContext.GetData("myKey");

If the execution at any time cross into another appDomain there's 2 additional steps you need to take. When a call is remoted the current CallContext class generates a LogicalCallContext object that travels with the call to the remote location. To ensure that your object stored in the CallContext is transmitted to the remote location you need to implement the ILogicalThreadAffinative interface. This interface, similiar to INamingContainer is only a marker interface. Implementing this interface marks your object for propagation outside of your current AppDomain in the generated LogicalCallContext object. If you do not implement this interface your objects simply will not be transmitted for remote method calls.

All that's left to do to ensure that your CallContext is passed successfully to the remote location is to mark the data you want to store in CallContext as Serializable by adding the SerializableAttribute to your class. Also ensure that all the members in your object you're storing is also marked as Serializable. The modified version of SomeSessionData class declaration is shown below :

[Serializable]

public class SomeSessionData : ILogicalThreadAffinative

{

      .

.

.

}

Now whether your call stays local or calls into another AppDomain or remoted class you'll still have access to the stored context information. All calls made on CallContext is static and and they operate on the callcontext for the current thread only!

Filed under:

Comments

# KevinT said:

This is really useful to know, thanks!

You should turn it into a short article for sadev :-)

Regards
KevinT

Thursday, April 08, 2004 9:45 AM
# TrackBack said:
Friday, July 30, 2004 3:25 PM
# TrackBack said:
Friday, July 30, 2004 3:54 PM
# Living .NET... said:

Many a times, it would be necessary to share some common information/data between methods that form a

Saturday, September 09, 2006 5:47 PM