What happened to my call?

You may already be aware that you can use the Call.StateChanged event to find out when a call that is handled by your UCMA application becomes established, or terminates, or goes through some other state change. Your UCMA applications probably have event handlers very much like the following: [csharp] void OnCallStateChanged(object sender, CallStateChangedEventArgs e) { _logger.Log("Call state changed from {0} to {1}.", e.PreviousState, e.State); } [/csharp]

What you may not know is that there are two other properties in the event arguments that can give you clues to what caused the state transition, and help answer burning questions like "Why did my call disconnect?" or "Where did the call go?" or "What happened to all my socks?" (Actually, maybe forget that last one.)

The first of these properties is TransitionReason. You can look at this property to get more details on why a call is changing state. For instance, if a call is terminating, you can see whether it was hung up by your application (TerminatedLocally) or by the remote party (TerminatedRemotely), or hung up automatically because a transfer occurred (CallTransferred) or because the call was replaced in a supervised transfer (CallReplaced). If a call goes to Establishing state, you can see whether it has been forwarded (DeflectedToAnotherDestination) or sent to a team or delegate (DeflectedToTeam, DeflectedToDelegate). It's almost like a subcategory of call states.

The second property in the event arguments that can be interesting is the MessageData property. This property gives you visibility to the contents of the SIP message that produced the change in the state of the call. Sometimes this will have helpful diagnostic information or will give you other useful context as to why a call ended or was transferred or what happened when it began.

Give it a try using an event handler like this one:

[csharp] void OnCallStateChanged(object sender, CallStateChangedEventArgs e) { Console.WriteLine("Call state changed from {0} to {1} because {2}.",  e.PreviousState, e.State, e.TransitionReason); foreach (SignalingHeader header in e.MessageData.SignalingHeaders) { Console.WriteLine("{0}: {1}", header.Name, header.GetValue()); } } [/csharp]

You can establish or accept a call, and then try different actions and see how they're reflected in the information you get. Some of the details these properties give you access to can be enormously helpful.