WCF Workflow Service: ForEach<>: Iterating over an Input Array to create an Output Array
-
2012年4月13日 20:22
Hi
I am creating a very simple WCF Workflow Service, call it BookInventory.xamlx
Within Workflow Designer, I want to create a WCF Workflow Service that processes an array of BookSearch and returns an array of BookInfo which is a result of each BookSearch proccessed by a "Code Activity" ProcessBook (In BookSearch, Out BookInfo).
The ReceiveRequest is receiving (Input) an array: BookSearch[]
The SendResponse is returning (Output) an array: BookInfo[]
Between ReceiveRequest and SendResponse is a Sequence, and within its body a ForEach<BookSearch>.
Each itme wtihin BookSearch[] will be iterated over using ForEach<BookSearch> , and I want to build up the result array BookInfo[] with search results of each processed item.
I have created a "Code Activity" ProcessBook that is within the Body of ForEach<BookSearch> which inputs a BookSearch and outputs a BookInfo.
Question: It is not clear to me how to complete the bodies of the Sequence and ForEach<BookSearch> on how to incrementally build up the resulting array BookInfo[]?
I have noticed that WCF Workflow Service has Variables but not Arguments (why)?
Thanks
Jeff in Seattle
Thanks
Jeff in Seattle
- 已编辑 jeff00seattle_2 2012年4月17日 15:32
全部回复
-
2012年4月15日 18:12
Hi Jeff,
in order to build the resulting array, you must initialize it before the Foreach<BookSearch> activity, and after completing the ProcessBook Code activity you must add an activity of type "AddToCollection<T>" to add the result to the collection you want to return.
About accepting arguments if you think it makes sense for xamlx not accept them, after all a client application will be consuming a service, not invoking a workflow! Why would you want arguments? You can always send a soap header to the xamlx if you want to send always some "common request" information.
Hope this helps.
-
2012年4月15日 19:02
Thanks for your reply
Using Workflow Designer: How would initialize the resulting BookInfo[] array, using the Assign component or as a Variable of the Sequence component?
Thanks
Jeff in Seattle
Thanks
Jeff in Seattle -
2012年4月15日 20:15It depends on the scope of your variable... if you only want to use it inside the sequence component or not. I believe you want to use it outside the sequence component to retrieve your results back to the client application, so, as I mentioned on my last post, you should assign the BookInfo[] before the Foreach activity (using the assign component).
-
2012年4月16日 2:09
It seems to go fine except when my WF design gets to AddToCollection<>
The declared variables are:
<p1:Sequence.Variables> <p1:Variable x:TypeArguments="CorrelationHandle" Name="handle" /> <p1:Variable x:TypeArguments="b:BookSearch[]" Name="searches" /> <p1:Variable x:TypeArguments="b:BookInfo" Name="result" /> <p1:Variable x:TypeArguments="b:BookInfo[]" Name="results" /> <p1:Variable x:TypeArguments="x:Int32" Name="count" /> </p1:Sequence.Variables>The WCF Workflow Receive is defined as:
<Receive x:Name="__ReferenceID0" CanCreateInstance="True" DisplayName="ReceiveRequest" sap:VirtualizedContainerService.HintSize="287,90" OperationName="LookupBooks3" ServiceContractName="p:IBookInventory"> <Receive.CorrelationInitializers> <RequestReplyCorrelationInitializer CorrelationHandle="[handle]" /> </Receive.CorrelationInitializers> <ReceiveParametersContent> <p1:OutArgument x:TypeArguments="b:BookSearch[]" x:Key="Searches">[searches]</p1:OutArgument> </ReceiveParametersContent> </Receive>I get the count of the number of BookSearch[]:
<p1:Assign sap:VirtualizedContainerService.HintSize="287,58"> <p1:Assign.To> <p1:OutArgument x:TypeArguments="x:Int32">[count]</p1:OutArgument> </p1:Assign.To> <p1:Assign.Value> <p1:InArgument x:TypeArguments="x:Int32">[searches.Length]</p1:InArgument> </p1:Assign.Value> </p1:Assign>Then I create a result array:
<p1:Assign sap:VirtualizedContainerService.HintSize="287,58"> <p1:Assign.To> <p1:OutArgument x:TypeArguments="b:BookInfo[]">[results]</p1:OutArgument> </p1:Assign.To> <p1:Assign.Value> <p1:InArgument x:TypeArguments="b:BookInfo[]">[New BookInfo(count) {}]</p1:InArgument> </p1:Assign.Value> </p1:Assign>Then I apply the search to the ForEach<> loop, but it breaks with the AddToCollection<> :
<p1:ForEach x:TypeArguments="b:BookSearch" DisplayName="ForEach<BookSearch>" sap:VirtualizedContainerService.HintSize="287,314" Values="[searches]"> <p1:ActivityAction x:TypeArguments="b:BookSearch"> <p1:ActivityAction.Argument> <p1:DelegateInArgument x:TypeArguments="b:BookSearch" Name="item" /> </p1:ActivityAction.Argument> <p1:Sequence sap:VirtualizedContainerService.HintSize="257,208"> <sap:WorkflowViewStateService.ViewState> <scg3:Dictionary x:TypeArguments="x:String, x:Object"> <x:Boolean x:Key="IsExpanded">True</x:Boolean> </scg3:Dictionary> </sap:WorkflowViewStateService.ViewState> <b:PerformLookup4 sap:VirtualizedContainerService.HintSize="200,22" Result="[result]" Search="[item]" /> <p1:AddToCollection x:TypeArguments="b:BookInfo" Collection="[results]" DisplayName="AddToCollection<BookInfo>" sap:VirtualizedContainerService.HintSize="200,22" Item="[result]" /> </p1:Sequence> </p1:ActivityAction> </p1:ForEach>Did I declare the [results] used by AddToCollection<> incorrectly? It runs fine (with no results) without the AddToCollection<> within Sequence within the ForEach<> body.
Here is the error log:
The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs. Server stack trace: at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter) at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at IBookInventory.LookupBooks3(BookSearch[] Searches) at BookInventoryClient.LookupBooks3(BookSearch[] Searches)
Thanks
Jeff in Seattle -
2012年4月16日 7:34版主
Hi,
Could you please provide a sample project for us download or send it to me at: liangliang(dot)tang(at)hotmail.com. It will be convenience for us to reproduce this issue. Thanks.
Leo Tang [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help. -
2012年4月16日 10:03
It seems ok to me, but do you have any extra loggin/tracing applications?
With the error description you've posted you won't get the real error! Are you using AppFabric since this is a xamlx?
Can you check the tracked events for this service when this exception happens? It really helps you (and us:)
-
2012年4月16日 16:53
Hi Leo Tang
Sent you my WCF Workflow VS2010 solution. Tell me if you have any issues.
Thank you
Thanks
Jeff in Seattle -
2012年4月16日 18:46
Okay, I progressed further on my problem
I am calling my WCF Workflow Service with the ForEach<> using a Workflow Console Application.
The Workflow Console App's call to the WCF Workflow Service is wrapped with a TryCatch Workflow design component, and it is catching: "Exception: Collection was of a fixed size"
The WCF Workflow Service's pseudo code initialization of collection BookInfo[] results was performed by:
ReceiveRequest: In: BookSearch[] searches Assign: count = searches.Length Assign: results = BookInfo(count) {} ForEach<item> of searches { result = LookupBook(item) AddToCollection<result> to results }How am I initializing the collection "results" incorrectly, because AddToCollection<> is upset?
Thanks
Thanks
Jeff in Seattle- 已编辑 jeff00seattle_2 2012年4月16日 19:10
-
2012年4月17日 15:09
I found the problem, do not use AddToCollection<> when the referred collection is an array.
However, now I have a new problem: The sent response is returning an array whereby the last item is null.
Here is the WCF Workflow Service's pseudo code:
- Create a results array that is the same size as the searches array (BookSearch[])
- Iterate over the searches array, lookup book info, then add book_info into results array (BookInfo[]).
Assign: count = searches.Length Assign: results = BookInfo(count) {} Assign: i = 0 ForEach<item> of searches { result = LookupBook(item) Assign: results(i) = result Assign: i = i + 1 }For example: I am sending in an array of BookSearch (searches) of size 3, but response out is a BookInfo (results) array of size 4 whereby the last element in this array is null.
Where is the extra BookInfo (of value null) coming from?
Thanks
Jeff in Seattle- 已编辑 jeff00seattle_2 2012年4月17日 15:13
-
2012年4月18日 3:48版主
Hi,
When declaring an array in Visual Basic Expression, it is different with C#
"New BookInfo(count) {}" means the BookInfo contains "count+1" elements, the indexes of the elements range from 0 through "count"
http://msdn.microsoft.com/en-us/library/wak0wfyt.aspx
Leo Tang [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.- 已编辑 LeoTangModerator 2012年4月18日 3:49
- 已标记为答案 jeff00seattle_2 2012年4月19日 6:26
-
2012年4月18日 4:10
Thanks Leo Tang
To avoid this confusion again with VB expressions, is there an expected future release of Workflow to accept C# expressions?
Thanks
Jeff in Seattle -
2012年4月18日 7:15版主
Hi,
WF4.5 has support for C# expression. Thanks.
Leo Tang [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help. -
2012年4月19日 6:29
Thanks Leo Tang
I am not a VB programmer, but why would a programming language provide such a confusing array construction.
I appreciate your assistance in this topic.
Thanks
Jeff in Seattle

