@@ -15,6 +15,9 @@ public class ForEachActionExecutor : DefaultBaseActionExecutor, IScopeActionExec
1515 private readonly ILogger < ForEachActionExecutor > _logger ;
1616 private readonly IExpressionEngine _expressionEngine ;
1717
18+ private JProperty [ ] _actionDescriptions ;
19+ private string _firstScopeActionName ;
20+
1821 private List < ValueContainer > _items ;
1922
2023 public ForEachActionExecutor (
@@ -35,7 +38,13 @@ public override Task<ActionResult> Execute()
3538 {
3639 _logger . LogInformation ( "Entered foreach..." ) ;
3740
38- var runOn = Json . SelectToken ( "$..foreach" ) . Value < string > ( ) ;
41+ if ( Json == null )
42+ {
43+ throw new PowerAutomateMockUpException ( $ "Json cannot be null - cannot execute { ActionName } .") ;
44+ }
45+
46+ var runOn = ( Json . SelectToken ( "$..foreach" ) ??
47+ throw new InvalidOperationException ( "Json must contain foreach token." ) ) . Value < string > ( ) ;
3948 var values = _expressionEngine . ParseToValueContainer ( runOn ) ;
4049
4150 if ( values . Type ( ) != ValueContainer . ValueType . Array )
@@ -44,42 +53,46 @@ public override Task<ActionResult> Execute()
4453 // TODO: Figure out what happens when you apply for each on non array values
4554 ActionStatus = ActionStatus . Failed
4655 } ) ;
47-
48- var valueList = values . GetValue < IEnumerable < ValueContainer > > ( ) . ToArray ( ) ;
49-
50- var firstScopeAction = SetupScope ( ) ;
5156
52- // TODO: Add scope relevant storage to store stuff like this, which cannot interfere with the state.
53- _state . AddOutputs ( $ "item_ { ActionName } " , valueList . First ( ) ) ;
54- _items = valueList . Skip ( 1 ) . ToList ( ) ;
57+ SetupForEach ( values ) ;
58+
59+ UpdateScopeAndSetItemValue ( ) ;
5560
56- return Task . FromResult ( new ActionResult { NextAction = firstScopeAction . Name } ) ;
61+ return Task . FromResult ( new ActionResult { NextAction = _firstScopeActionName } ) ;
5762 }
5863
59- private JProperty SetupScope ( )
64+ private void SetupForEach ( ValueContainer values )
6065 {
61- var scopeActionDescriptions = Json . SelectToken ( "$.actions" ) . OfType < JProperty > ( ) ;
62- var actionDescriptions = scopeActionDescriptions as JProperty [ ] ?? scopeActionDescriptions . ToArray ( ) ;
66+ var scopeActionDescriptions = ( Json . SelectToken ( "$.actions" ) ??
67+ throw new InvalidOperationException ( "Json must contain actions token." ) )
68+ . OfType < JProperty > ( ) ;
69+ _actionDescriptions = scopeActionDescriptions as JProperty [ ] ?? scopeActionDescriptions . ToArray ( ) ;
70+ _firstScopeActionName = _actionDescriptions . First ( ad =>
71+ ! ( ad . Value . SelectToken ( "$.runAfter" ) ??
72+ throw new InvalidOperationException ( "Json must contain runAfter token." ) ) . Any ( ) ) . Name ;
6373
64- _scopeDepthManager . Push ( ActionName , actionDescriptions , this ) ;
74+ // TODO: Add scope relevant storage to store stuff like this, which cannot interfere with the state.
75+ _items = values . GetValue < IEnumerable < ValueContainer > > ( ) . ToList ( ) ;
76+ }
77+
78+ private void UpdateScopeAndSetItemValue ( )
79+ {
80+ _scopeDepthManager . Push ( ActionName , _actionDescriptions , this ) ;
6581
66- var firstScopeAction = actionDescriptions . First ( ad => ! ad . Value . SelectToken ( "$.runAfter" ) . Any ( ) ) ;
67- return firstScopeAction ;
82+ _state . AddOutputs ( $ "item_ { ActionName } " , _items . First ( ) ) ;
83+ _items = _items . Skip ( 1 ) . ToList ( ) ;
6884 }
6985
86+
7087 public Task < ActionResult > ExitScope ( ActionStatus scopeStatus )
7188 {
7289 if ( _items . Count > 0 )
7390 {
7491 _logger . LogInformation ( "Continuing foreach." ) ;
7592
76- _state . AddOutputs ( $ "item_{ ActionName } ", _items . First ( ) ) ;
77-
78- _items = _items . Skip ( 1 ) . ToList ( ) ;
79-
80- var firstScopeAction = SetupScope ( ) ;
93+ UpdateScopeAndSetItemValue ( ) ;
8194
82- return Task . FromResult ( new ActionResult { NextAction = firstScopeAction . Name } ) ;
95+ return Task . FromResult ( new ActionResult { NextAction = _firstScopeActionName } ) ;
8396 }
8497 else
8598 {
0 commit comments