Example #1
0
        object IOperationInvoker.Invoke(object instance, object[] inputs, out object[] outputs)
        {
            outputs = new object[0];
            object  retVal  = null;
            Invoker invoker = null;

            // set incoming objects in the CallContext
            LCC.SetDataContract(OperationContext.Current.IncomingMessageHeaders, this._callContextActors);
            LogicalWorkflowContext lwc = LCC.LogicalWorkflowContext;

            // check the workflowId
            Guid workflowInstanceId = lwc.GetAndClearWorkflowId();
            bool bGetWorkflowById   = !workflowInstanceId.Equals(Guid.Empty);

            // options for workflow type
            if (this._workflowType == null)
            {
                string endpointUri = string.Concat(instance.GetType().FullName, ".", this._description.SyncMethod.Name);
                this._workflowType = RemotingServices.GetServerTypeForUri(endpointUri);
            }
            if (!bGetWorkflowById && this._workflowType == null)
            {
                // throw exception or perform some pre-processing
                retVal = this._innerOperationInvoker.Invoke(instance, inputs, out outputs);

                // done (no workflow invoked)
                return(retVal);
            }

            // create message operation
            MethodMessage message = new MethodMessage(this._description.SyncMethod, inputs, null);

            // workflow invoker options (statefull or stateless)
            if (bGetWorkflowById)
            {
                invoker = WorkflowInvoker.Create(workflowInstanceId);
            }
            else
            {
                invoker = WorkflowInvoker.Create(this._workflowType, lwc.WorkflowInitData);
            }

            // send message to the workflow queue
            invoker.SendMessage(message);

            // response
            if (!this._description.IsOneWay)
            {
                invoker.WaitForResponse(this.ResponseTime);
                retVal = invoker.GetResponse <object>();
            }

            // done
            return(retVal);
        }
        /// <summary>
        ///
        /// </summary>
        public void ProcessMessage(IMessage requestMessage, ITransportHeaders requestHeaders, Stream requestStream,
                                   out ITransportHeaders responseHeaders, out Stream responseStream)
        {
            object returnValue = null;

            responseHeaders = null;
            responseStream  = new MemoryStream();
            IMessage           responseMsg = null;
            IMethodCallMessage mcm         = requestMessage as IMethodCallMessage;
            BinaryFormatter    bf          = new BinaryFormatter();

            try
            {
                if (_endpoint.StartsWith(WorkflowDefaults.WorkflowLocalhost))
                {
                    #region Invoke local Workflow
                    LogicalWorkflowContext lwc = LCC.LogicalWorkflowContext;
                    Guid workflowInstanceId    = lwc.GetAndClearWorkflowId();
                    bool bGetWorkflowById      = !workflowInstanceId.Equals(Guid.Empty);

                    // create workflow
                    Invoker invoker = null;
                    if (bGetWorkflowById)
                    {
                        invoker = WorkflowInvoker.Create(workflowInstanceId);
                    }
                    else
                    {
                        string endpoint     = _endpoint.Replace(WorkflowDefaults.WorkflowLocalhost, "").Trim('/');
                        Type   workflowType = RemotingServices.GetServerTypeForUri(endpoint);
                        invoker = WorkflowInvoker.Create(workflowType, lwc.WorkflowInitData);
                    }

                    // send remoting message
                    invoker.SendMessage(mcm);

                    // handle response
                    if (RemotingServices.IsOneWay(mcm.MethodBase) == false)
                    {
                        invoker.WaitForResponse(_Sender.TimeOut);
                        returnValue = invoker.GetResponse <object>();
                    }
                    #endregion
                }
                else if (_endpoint.StartsWith(WorkflowDefaults.WorkflowByWCF))
                {
                    #region Invoke remote Workflow by WCF
                    try
                    {
                        string endpoint = _endpoint.Replace(WorkflowDefaults.WorkflowByWCF, "").Trim('/');
                        using (ChannelFactory2 factory = new ChannelFactory2(Type.GetType(mcm.TypeName), endpoint))
                        {
                            object tp = factory.CreateChannel();

                            using (OperationContextScope scope = new OperationContextScope(tp as IContextChannel))
                            {
                                // CallContext over the loosely coupled contract (LogicalWorkflowContext and Unknown)
                                object lwc = LCC.GetLogicalWorkflowContext;
                                if (lwc != null)
                                {
                                    MessageHeader header = MessageHeader.CreateHeader("LogicalWorkflowContext", "RKiss.WorkflowRemoting", lwc, false, "WorkflowRemoting");
                                    OperationContext.Current.OutgoingMessageHeaders.Add(header);
                                }
                                if (!string.IsNullOrEmpty(Sender.CallContextActor))
                                {
                                    IDictionaryEnumerator enumerator = LCC.GetDataContract().GetEnumerator();
                                    while (enumerator.MoveNext())
                                    {
                                        // skip it
                                        if (enumerator.Value is LogicalWorkflowContext)
                                        {
                                            continue;
                                        }

                                        DataContractAttribute dca    = enumerator.Key as DataContractAttribute;
                                        MessageHeader         header = MessageHeader.CreateHeader(dca.Name, dca.Namespace, enumerator.Value, false, Sender.CallContextActor);
                                        OperationContext.Current.OutgoingMessageHeaders.Add(header);
                                    }
                                }

                                // action
                                returnValue = factory.InvokeMethod(mcm.MethodName, mcm.Args);
                            }
                            factory.Close();
                        }
                    }
                    catch (TargetInvocationException ex)
                    {
                        throw ex.InnerException;
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    #endregion
                }
                else
                {
                    throw new InvalidOperationException("No supported schema");
                }

                // return value
                responseMsg = (IMessage) new ReturnMessage(returnValue, null, 0, null, mcm);
            }
            catch (System.ServiceModel.FaultException fe)
            {
                Exception ex = new Exception(fe.Message);
                ex.GetType().InvokeMember("_stackTraceString", BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Instance, null, ex, new object[] { fe.ToString() });
                responseMsg = new ReturnMessage(ex, mcm);
            }
            catch (Exception ex)
            {
                responseMsg = new ReturnMessage(ex, mcm);
            }
            finally
            {
                #region serialize IMessage response to return back
                bf.Serialize(responseStream, responseMsg);
                responseStream.Position = 0;
                responseHeaders         = requestHeaders;
                #endregion
            }
        }
        /// <summary>
        ///
        /// </summary>
        public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream,
                                               out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
        {
            // scope state
            ServerProcessing servproc = ServerProcessing.Complete;

            responseMsg     = null;
            responseHeaders = null;
            responseStream  = new MemoryStream();
            IMethodCallMessage mcm = null;
            BinaryFormatter    bf  = new BinaryFormatter();

            try
            {
                //Are we in the business?
                if (_Next != null)
                {
                    if (requestMsg == null && requestStream != null)
                    {
                        // we are supporting only binary formatter
                        requestMsg = (IMessage)bf.Deserialize(requestStream);
                        requestStream.Close();
                    }

                    mcm = requestMsg as IMethodCallMessage;
                    if (mcm == null)
                    {
                        throw new NullReferenceException("IMethodCallMessage after deserialization");
                    }

                    // LogicalCallContext
                    LCC.CopyFrom(mcm);
                    LogicalWorkflowContext lwc = LCC.LogicalWorkflowContext;
                    Guid workflowInstanceId    = lwc.GetAndClearWorkflowId();
                    bool bGetWorkflowById      = !workflowInstanceId.Equals(Guid.Empty);

                    // create workflow
                    Invoker invoker = null;
                    if (bGetWorkflowById)
                    {
                        invoker = WorkflowInvoker.Create(workflowInstanceId);
                    }
                    else
                    {
                        string endpoint = mcm.Uri;
                        if (string.IsNullOrEmpty(endpoint))
                        {
                            endpoint = requestHeaders["__RequestUri"] as string;
                        }
                        if (string.IsNullOrEmpty(endpoint))
                        {
                            throw new NullReferenceException("Internal error - missing endpoint");
                        }

                        // create workflow instance
                        Type workflowType = RemotingServices.GetServerTypeForUri(endpoint.TrimStart('/'));
                        invoker = WorkflowInvoker.Create(workflowType, lwc.WorkflowInitData);
                    }

                    // send remoting message to the workflow
                    invoker.SendMessage(mcm);

                    // handle response
                    if (!RemotingServices.IsOneWay(mcm.MethodBase))
                    {
                        // wait for response
                        invoker.WaitForResponse(_Provider.TimeOut);
                        object response = invoker.GetResponse <object>();

                        // return message back to the caller (Note that this version is not allow to change a CallContext!!)
                        responseMsg = (IMessage) new ReturnMessage(response, null, 0, null, mcm);
                    }
                }
                else
                {
                    throw new RemotingException("Internal error in the channel stack");
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex);
                responseMsg = (IMessage) new ReturnMessage(ex, mcm);
            }
            finally
            {
                responseHeaders = requestHeaders;
                if (responseMsg != null)
                {
                    // serialize response to the wire transport
                    bf.Serialize(responseStream, responseMsg);
                    responseStream.Position = 0;
                }
            }
            return(servproc);
        }