I've been working with Durable Functions and Task Orchestration (Fan-out/Fan-in pattern) in .NET 6 for a while now, and object casting works fine with ActivityTriggers. However when upgrading to .NET 8 (isolated workers) it seems that object casting from ActivityTriggers only works with strings. This means I'm doing a lot of unnecessary serializing / deserializing when passing objects around. Is there a better way of doing this without extra serialization step? The sample below results in the error "The JSON value could not be converted..."
var jobTypeName = "OrderImport";
[Function($"{jobTypeName}-Trigger")]
public async Task Trigger([OrchestrationTrigger] TaskOrchestrationContext context)
{
var functionName = $"{jobTypeName}-Trigger";
var content = context.GetInput<string>();
var (request, traceBundle) = Initialize(content, InitFunctionName(functionName, context));
try
{
// Failure occurs here with Error "The JSON value could not be converted to System.Collections.Generic.List`1[Mindwire.Domain.Models.OrderRequestModel]"
var processingGroups = await context.CallActivityAsync<List<OrderRequestModel>>($"{jobTypeName}-InitActivity", content);
// .NET v8.0 Revision which corrects the issue.
// var initActivityResult = await context.CallActivityAsync<string>($"{jobTypeName}-InitActivity", content);
// var processingGroups = JsonConvert.DeserializeObject<List<OrderRequestModel>>(initActivityResult);
var itemCount = processingGroups.Count();
var parallelTasks = new Task[itemCount];
for (int i = 0; i < itemCount; i++)
{
processingGroups[i].Iterator = i + 1;
parallelTasks[i] = context.CallActivityAsync($"{jobTypeName}-Activity", processingGroups[i]);
}
await Task.WhenAll(parallelTasks);
await FinalizeDurableOrchestration(context, request, true);
logger.LogInformation($"{functionName} completed");
}
catch (Exception ex)
{
logger.LogError($"{functionName} Error: [{ex.Message}]");
await FinalizeDurableOrchestration(context, request, false, ex.Message);
throw;
}
}
[Function($"{jobTypeName}-InitActivity")]
public async Task<List<OrderRequestModel>> InitActivity([ActivityTrigger] string content)
{
var functionName = $"{jobTypeName}-InitActivity";
var (request, traceBundle) = Initialize(content, functionName);
return myService.ParseOrder(request);
// .NET v8.0 Revision which corrects the issue.
// var result = myService.ParseOrder(request);
// return JsonConvert.SerializeObject(result);
}
Answered by comment from phil, with the solution here: Is a parameterless constructor now always required by System.Text.Json?
For my needs I began using the [JsonConstructor]
decorator on my related constructors (as the previous question suggests).
[JsonConstructor]
public MyClass()
{
}