Esempio n. 1
0
        public static T RequestResponse <T>(Type workflowType, object request, Dictionary <string, object> namedArgumentValues, int timeoutInSec, string identity) where T : class
        {
            // create workflow invoker
            Invoker invoker = WorkflowInvoker.Create(workflowType, namedArgumentValues);

            // pass request object to the workflow
            invoker.RaiseRequestEvent(request, identity);

            // wait for response from workflow
            invoker.WaitForResponse(timeoutInSec);

            // response
            return(invoker.GetResponse <T>());
        }
Esempio n. 2
0
        public void SendMessage(IMethodMessage message)
        {
            // identity
            string identity = WorkflowInvoker.Identity();

            if (!string.IsNullOrEmpty(identity) && message.LogicalCallContext != null)
            {
                // workaround to create an IdentityContextData for LogicalCallContext
                Type   type = Type.GetType("System.Workflow.Activities.IdentityContextData, System.Workflow.Activities, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
                object identityContextData = Activator.CreateInstance(type, BindingFlags.CreateInstance | BindingFlags.ExactBinding | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new object[] { identity }, CultureInfo.CurrentCulture);
                message.LogicalCallContext.SetData("__identitycontext__", identityContextData);
            }

            // contract type
            Type contractType = Type.GetType(message.TypeName);

            if (contractType == null)
            {
                throw new TypeLoadException(message.TypeName);
            }

            // create queue name
            EventQueueName qn = new EventQueueName(contractType, message.MethodName);

            // enqueue item
            if (_bStateMachine)
            {
                if (_localservice.Scheduler != null)
                {
                    _localservice.Scheduler.RunWorkflow(_instance.InstanceId);
                }
                _instance.EnqueueItemOnIdle(qn, message, null, null);
            }
            else
            {
                _instance.EnqueueItem(qn, message, null, null);
            }
            if (_localservice.Scheduler != null)
            {
                _localservice.Scheduler.RunWorkflow(_instance.InstanceId);
            }
        }
        /// <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);
        }