internal static LogicalChannel Register(Activity activity,
                                                ChannelToken endpoint,
                                                Type contractType)
        {
            if (activity == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
            }
            if (endpoint == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
            }
            if (contractType == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType");
            }

            LogicalChannel logicalChannel = GetLogicalChannel(activity, endpoint, contractType);

            if (logicalChannel == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                          new InvalidOperationException(SR2.GetString(SR2.Error_FailedToRegisterChannel, endpoint.Name)));
            }

            return(logicalChannel);
        }
Example #2
0
        public static void SetContext(Activity activity,
                                      string endpointName,
                                      string ownerActivityName,
                                      Type contractType,
                                      IDictionary <string, string> context)
        {
            if (activity == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
            }
            if (string.IsNullOrEmpty(endpointName))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("endpointName",
                                                                             SR2.GetString(SR2.Error_ArgumentValueNullOrEmptyString));
            }
            if (contractType == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType");
            }

            LogicalChannel logicalChannel = ChannelToken.GetLogicalChannel(activity, endpointName, ownerActivityName, contractType);

            if (logicalChannel != null)
            {
                if (context != null)
                {
                    logicalChannel.Context = context;
                }
                else
                {
                    logicalChannel.Context = ContextMessageProperty.Empty.Context;
                }
            }
        }
Example #3
0
        protected internal override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            TypedOperationInfo serviceOperationInfo = this.ServiceOperationInfo;

            if (serviceOperationInfo == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                          new InvalidOperationException(SR2.GetString(SR2.Error_ServiceOperationInfoNotSpecified, this.Name)));
            }

            MethodInfo methodInfo = serviceOperationInfo.GetMethodInfo(executionContext);

            if (methodInfo == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                          new InvalidOperationException(SR2.GetString(SR2.Error_MethodInfoNotAvailable, this.Name)));
            }

            ChannelToken channelToken = this.ChannelToken;

            LogicalChannel logicalChannel = ChannelToken.Register(this, channelToken, serviceOperationInfo.ContractType);

            if (!logicalChannel.Initialized)
            {
                logicalChannel.Initialize(channelToken.EndpointName, this.CustomAddress);
            }

            using (ChannelManagerService.ChannelTicket leasedChannel = ChannelManagerService.Take(executionContext, this.WorkflowInstanceId, logicalChannel))
            {
                using (OperationContextScope scope = new OperationContextScope((IContextChannel)leasedChannel.Channel))
                {
                    EventHandler <SendActivityEventArgs>[] invocationList = this.GetInvocationList <EventHandler <SendActivityEventArgs> >(SendActivity.BeforeSendEvent);
                    if (invocationList != null && invocationList.Length > 0)
                    {
                        base.RaiseGenericEvent(SendActivity.BeforeSendEvent, this, new SendActivityEventArgs(this));
                    }

                    SendOperationInfoHelper            helper   = this.OperationHelper;
                    WorkflowParameterBindingCollection bindings = this.ParameterBindings;

                    object[] parameters  = helper.GetInputs(this, bindings);
                    object   returnValue = null;

                    bool isSessionless  = ChannelManagerHelpers.IsSessionlessContract(logicalChannel.ContractType);
                    bool hasContext     = (logicalChannel.Context != null && logicalChannel.Context.Count > 0);
                    bool fatalException = false;

                    if (!isSessionless && hasContext)
                    {
                        ChannelManagerService.ApplyLogicalChannelContext(logicalChannel);
                    }

                    try
                    {
                        returnValue = this.InvokeOperation(methodInfo, leasedChannel.Channel, parameters);
                    }
                    catch (Exception exception)
                    {
                        if (Fx.IsFatal(exception))
                        {
                            fatalException = true;
                        }
                        throw;
                    }
                    finally
                    {
                        if (!fatalException &&
                            !hasContext && !isSessionless && !helper.IsOneWay)
                        {
                            ChannelManagerService.UpdateLogicalChannelContext(logicalChannel);
                        }
                    }

                    helper.PopulateOutputs(this, bindings, parameters, returnValue);

                    invocationList = this.GetInvocationList <EventHandler <SendActivityEventArgs> >(SendActivity.AfterResponseEvent);
                    if (invocationList != null && invocationList.Length > 0)
                    {
                        base.RaiseGenericEvent(SendActivity.AfterResponseEvent, this, new SendActivityEventArgs(this));
                    }
                }
            }

            return(ActivityExecutionStatus.Closed);
        }
        internal PooledChannelTicket TakeChannel(Guid workflowId, LogicalChannel logicalChannel)
        {
            if (this.closed)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_CannotProvideChannel_ServiceStopped, logicalChannel.ConfigurationName, logicalChannel.CustomAddress)));
            }

            if (workflowId == Guid.Empty)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("workflowId",
                    SR2.GetString(SR2.Error_Cache_InvalidWorkflowId));
            }

            if (logicalChannel == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("logicalChannel");
            }

            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "ChannelManagerService: get channel for workflow instance {0}, logical channel {1}", new object[] { workflowId, logicalChannel.InstanceId });

            string endpointName = logicalChannel.ConfigurationName;
            Type contractType = logicalChannel.ContractType;
            string customAddress = logicalChannel.CustomAddress;

            ChannelPoolKey channelKey;
            ChannelManager.PooledChannel channel = this.channelManager.TakeChannel(endpointName, contractType, customAddress, out channelKey);
            if (channel == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_CannotProvideChannel, logicalChannel.ConfigurationName, logicalChannel.CustomAddress)));
            }

            PooledChannelTicket pooledChannel = new PooledChannelTicket(this, channel, channelKey, workflowId, logicalChannel.InstanceId);
            return pooledChannel;
        }
        internal static void UpdateLogicalChannelContext(LogicalChannel logicalChannel)
        {
            Fx.Assert(OperationContext.Current != null, "Can be called from valid OperationContextScope");

            WorkflowTrace.Host.TraceEvent(TraceEventType.Verbose, 0,
                "ChannelManagerService: updating context associated with logical channel {0}",
                logicalChannel.InstanceId);

            ContextMessageProperty contextMessageProperty;
            MessageProperties properties = OperationContext.Current.IncomingMessageProperties;

            if (properties != null && ContextMessageProperty.TryGet(properties, out contextMessageProperty))
            {
                logicalChannel.Context = contextMessageProperty.Context;
            }
        }
        internal static ChannelTicket Take(ActivityExecutionContext executionContext, Guid workflowId, LogicalChannel logicalChannel)
        {
            if (executionContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
            }

            if (workflowId == Guid.Empty)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("workflowId",
                    SR2.GetString(SR2.Error_Cache_InvalidWorkflowId));
            }

            if (logicalChannel == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("logicalChannel");
            }

            ChannelManagerService channelManager = executionContext.GetService<ChannelManagerService>();

            ChannelTicket channel;
            if (channelManager != null)
            {
                channel = channelManager.TakeChannel(workflowId, logicalChannel);
            }
            else
            {
                channel = ChannelManagerService.CreateTransientChannel(logicalChannel);
            }

            return channel;
        }
        internal static TransientChannelTicket CreateTransientChannel(LogicalChannel logicalChannel)
        {
            DiagnosticUtility.DebugAssert(logicalChannel != null, "logical channel cannot be null");

            ChannelFactory factory = null;
            IChannel channel = null;
            bool channelOpened = false;

            try
            {
                factory = ChannelManagerHelpers.CreateChannelFactory(logicalChannel.ConfigurationName, logicalChannel.ContractType);
                channel = ChannelManagerHelpers.CreateChannel(logicalChannel.ContractType, factory, logicalChannel.CustomAddress);
                channelOpened = true;
            }
            finally
            {
                if (!channelOpened)
                {
                    if (channel != null)
                    {
                        ChannelManagerHelpers.CloseCommunicationObject(channel);
                    }
                    if (factory != null)
                    {
                        ChannelManagerHelpers.CloseCommunicationObject(factory);
                    }
                }
            }

            return new TransientChannelTicket(channel, factory);
        }
        internal static void ApplyLogicalChannelContext(LogicalChannel logicalChannel)
        {
            Fx.Assert(OperationContext.Current != null, "Can be called within a valid OperationContext Scope");

            WorkflowTrace.Host.TraceEvent(TraceEventType.Verbose, 0,
                "ChannelManagerService: updating context associated with logical channel {0}",
                logicalChannel.InstanceId);

            if (logicalChannel.Context != null)
            {
                new ContextMessageProperty(logicalChannel.Context).AddOrReplaceInMessageProperties(OperationContext.Current.OutgoingMessageProperties);
            }
        }
        internal static LogicalChannel GetLogicalChannel(Activity activity,
            string name,
            string ownerActivityName,
            Type contractType)
        {
            if (activity == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
            }
            if (string.IsNullOrEmpty(name))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("name",
                    SR2.GetString(SR2.Error_ArgumentValueNullOrEmptyString));
            }
            if (contractType == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType");
            }

            Activity contextActivity = activity.ContextActivity;
            Activity owner = null;

            if (contextActivity == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_ContextOwnerActivityMissing)));
            }

            if (string.IsNullOrEmpty(ownerActivityName))
            {
                owner = contextActivity.RootActivity;
            }
            else
            {
                while (contextActivity != null)
                {
                    owner = contextActivity.GetActivityByName(ownerActivityName, true);
                    if (owner != null)
                    {
                        break;
                    }

                    contextActivity = contextActivity.Parent;
                    if (contextActivity != null)
                    {
                        contextActivity = contextActivity.ContextActivity;
                    }
                }
            }

            if (owner == null && !string.IsNullOrEmpty(ownerActivityName))
            {
                owner = Helpers.ParseActivityForBind(activity, ownerActivityName);
            }

            if (owner == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(SR2.GetString(SR2.Error_ContextOwnerActivityMissing)));
            }

            LogicalChannel logicalChannel = null;

            LogicalChannelCollection collection =
                owner.GetValue(LogicalChannelCollection.LogicalChannelCollectionProperty) as LogicalChannelCollection;
            if (collection == null)
            {
                collection = new LogicalChannelCollection();
                owner.SetValue(LogicalChannelCollection.LogicalChannelCollectionProperty, collection);

                logicalChannel = new LogicalChannel(name, contractType);
                collection.Add(logicalChannel);
            }
            else if (!collection.Contains(name))
            {
                logicalChannel = new LogicalChannel(name, contractType);
                collection.Add(logicalChannel);
            }
            else
            {
                logicalChannel = collection[name];
            }

            if (logicalChannel.ContractType != contractType)
            {
                logicalChannel = null;
            }

            return logicalChannel;
        }
        internal static LogicalChannel GetLogicalChannel(Activity activity,
                                                         string name,
                                                         string ownerActivityName,
                                                         Type contractType)
        {
            if (activity == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
            }
            if (string.IsNullOrEmpty(name))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("name",
                                                                             SR2.GetString(SR2.Error_ArgumentValueNullOrEmptyString));
            }
            if (contractType == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType");
            }

            Activity contextActivity = activity.ContextActivity;
            Activity owner           = null;

            if (contextActivity == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                          new InvalidOperationException(SR2.GetString(SR2.Error_ContextOwnerActivityMissing)));
            }

            if (string.IsNullOrEmpty(ownerActivityName))
            {
                owner = contextActivity.RootActivity;
            }
            else
            {
                while (contextActivity != null)
                {
                    owner = contextActivity.GetActivityByName(ownerActivityName, true);
                    if (owner != null)
                    {
                        break;
                    }

                    contextActivity = contextActivity.Parent;
                    if (contextActivity != null)
                    {
                        contextActivity = contextActivity.ContextActivity;
                    }
                }
            }

            if (owner == null && !string.IsNullOrEmpty(ownerActivityName))
            {
                owner = Helpers.ParseActivityForBind(activity, ownerActivityName);
            }

            if (owner == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                          new InvalidOperationException(SR2.GetString(SR2.Error_ContextOwnerActivityMissing)));
            }

            LogicalChannel logicalChannel = null;

            LogicalChannelCollection collection =
                owner.GetValue(LogicalChannelCollection.LogicalChannelCollectionProperty) as LogicalChannelCollection;

            if (collection == null)
            {
                collection = new LogicalChannelCollection();
                owner.SetValue(LogicalChannelCollection.LogicalChannelCollectionProperty, collection);

                logicalChannel = new LogicalChannel(name, contractType);
                collection.Add(logicalChannel);
            }
            else if (!collection.Contains(name))
            {
                logicalChannel = new LogicalChannel(name, contractType);
                collection.Add(logicalChannel);
            }
            else
            {
                logicalChannel = collection[name];
            }

            if (logicalChannel.ContractType != contractType)
            {
                logicalChannel = null;
            }

            return(logicalChannel);
        }