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>()); }
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); }