From 731e3a763347d42b094abc57931f1d543f047ddc Mon Sep 17 00:00:00 2001
From: Chris <66376200+crickman@users.noreply.github.com>
Date: Mon, 20 Oct 2025 19:45:07 -0700
Subject: [PATCH] .NET Workflows - Fix ability of ParseValue action to process
list/table types. (#1577)
* Initial plan
* Add test classes for extension methods
Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
* Fix test issues and document bug in ExpandoObjectExtensions
Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
* Address code review feedback - shorten Skip messages and add explanatory comments
Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
* Replace Fields.ToDictionary with GetField calls and fix ExpandoObjectExtensions bug
Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
* Update dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Extensions/DataValueExtensionsTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Extensions/DataValueExtensionsTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Remove unused using statement from DialogBaseExtensionsTests
Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
* Add proper WrapWithBot tests using AdaptiveDialog and OnActivity
Co-authored-by: crickman <66376200+crickman@users.noreply.github.com>
* Cleanup
* Better
* Better
* One more test
* Checkpoint
* Checkpoint
* Finally
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
dotnet/agent-framework-dotnet.slnx | 1 +
.../Extensions/FormulaValueExtensions.cs | 16 +
.../Extensions/JsonDocumentExtensions.cs | 302 ++++++++++++---
.../Extensions/ObjectExtensions.cs | 14 +-
.../Extensions/TypeExtensions.cs | 18 +
.../Kit/VariableType.cs | 62 ++-
.../DeclarativeWorkflowTest.cs | 2 +
.../Extensions/JsonDocumentExtensionsTests.cs | 355 ++++++++++++++++++
.../Extensions/TypeExtensionsTests.cs | 65 ++++
.../Kit/VariableTypeTests.cs | 166 ++++++++
.../ObjectModel/ParseValueExecutorTest.cs | 33 +-
.../ObjectModel/WorkflowActionExecutorTest.cs | 13 +
.../Workflows/CaseInsensitive.yaml | 29 ++
.../Workflows/ParseValueList.yaml | 17 +
workflow-samples/ParseValue.yaml | 39 ++
15 files changed, 1056 insertions(+), 76 deletions(-)
create mode 100644 dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/Extensions/TypeExtensions.cs
create mode 100644 dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Extensions/JsonDocumentExtensionsTests.cs
create mode 100644 dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Extensions/TypeExtensionsTests.cs
create mode 100644 dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Kit/VariableTypeTests.cs
create mode 100644 dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Workflows/CaseInsensitive.yaml
create mode 100644 dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Workflows/ParseValueList.yaml
create mode 100644 workflow-samples/ParseValue.yaml
diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx
index 9d3b86535c..eb73146202 100644
--- a/dotnet/agent-framework-dotnet.slnx
+++ b/dotnet/agent-framework-dotnet.slnx
@@ -94,6 +94,7 @@
+
diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/Extensions/FormulaValueExtensions.cs b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/Extensions/FormulaValueExtensions.cs
index e0425bfbec..108dca7682 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/Extensions/FormulaValueExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/Extensions/FormulaValueExtensions.cs
@@ -219,6 +219,22 @@ internal static class FormulaValueExtensions
elementType switch
{
null => FormulaValue.NewTable(RecordType.EmptySealed(), []),
+ _ when elementType == typeof(string) =>
+ FormulaValue.NewSingleColumnTable([.. value.OfType().Select(element => FormulaValue.New(element))]),
+ _ when elementType == typeof(bool) =>
+ FormulaValue.NewSingleColumnTable([.. value.OfType().Select(element => FormulaValue.New(element))]),
+ _ when elementType == typeof(int) =>
+ FormulaValue.NewSingleColumnTable([.. value.OfType().Select(element => FormulaValue.New(element))]),
+ _ when elementType == typeof(long) =>
+ FormulaValue.NewSingleColumnTable([.. value.OfType().Select(element => FormulaValue.New(element))]),
+ _ when elementType == typeof(decimal) =>
+ FormulaValue.NewSingleColumnTable([.. value.OfType().Select(element => FormulaValue.New(element))]),
+ _ when elementType == typeof(float) =>
+ FormulaValue.NewSingleColumnTable([.. value.OfType().Select(element => FormulaValue.New(element))]),
+ _ when elementType == typeof(DateTime) =>
+ FormulaValue.NewSingleColumnTable([.. value.OfType().Select(element => FormulaValue.New(element))]),
+ _ when elementType == typeof(TimeSpan) =>
+ FormulaValue.NewSingleColumnTable([.. value.OfType().Select(element => FormulaValue.New(element))]),
_ when elementType == typeof(ExpandoObject) =>
FormulaValue.NewTable(
value.ToTableType().ToRecord(),
diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/Extensions/JsonDocumentExtensions.cs b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/Extensions/JsonDocumentExtensions.cs
index af1931d6d2..d3a4ef9cbc 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/Extensions/JsonDocumentExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/Extensions/JsonDocumentExtensions.cs
@@ -1,99 +1,277 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
-using System.Collections.Frozen;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Text.Json;
using Microsoft.Agents.AI.Workflows.Declarative.Kit;
-using Microsoft.Bot.ObjectModel;
-using Microsoft.PowerFx.Types;
namespace Microsoft.Agents.AI.Workflows.Declarative.Extensions;
internal static class JsonDocumentExtensions
{
- public static FrozenDictionary ParseRecord(this JsonDocument jsonDocument, VariableType recordType) => jsonDocument.RootElement.ParseRecord(recordType);
-
- public static RecordValue ParseRecord(this JsonDocument jsonDocument, RecordDataType recordType) => jsonDocument.RootElement.ParseRecord(recordType);
-
- private static FrozenDictionary ParseRecord(this JsonElement currentElement, VariableType recordType)
+ public static List