Azure-functions-durable-extension: Input from Orchestrator to Another Not Deserializing

Created on 12 Oct 2017  路  4Comments  路  Source: Azure/azure-functions-durable-extension

I have a simple object that I'm passing in the arguments from one orchestrator function to another using the DurableOrchestrationContext.CallSubOrchestratorAsync method. The argument is wrapped in an array in the input, which is understandable given the input accepts a params array, however I can't deserialize the input as an array of my type. I can't deserialize it as an object array either. I can deserialize it as a string or an object only. The string representation won't deserialize using Newtonsoft. I have to jump through some hoops to get the object to deserialize correctly:

var argsObj = context.GetInput<object>();
var args = JsonConvert.DeserializeObject<MyArgsType[]>((string)argsObj)[0];

I've tried simplifying the object to having just a single string property, and it still won't deserialize without the above work-around.

bug

Most helpful comment

Thanks, I think I found the issue. It looks like we're serializing the input to the sub-orchestration twice. Our unit tests didn't catch this because we didn't test this API using complex types.

It's a simple fix, and we'll include this in the next update (at which point you'll need to remove your workaround). Thanks again for reporting this!

FYI @tohling

All 4 comments

Thanks for opening this issue. Can you share a code snippet which shows an example of how you're passing data to CallSubOrchestratorAsync? I'll see if I can reproduce it.

In the below example, _ComplexType_ has the DataContract attribute applied to it. _MyArgsType_ does not. I have tried doing so, but that didn't seem to make any difference. Let me know if you need anything else.

```
[DataContract]
public class ComplexType
{
public ComplexType(){}

    public ComplexType(int id)
    {
          ID = id;
    }

    [DataMember]
    public int ExtraSpace { get; set; }
    [DataMember]
    public string Logo { get; set; }
    [DataMember]
    public string WidgetID { get; set; }
    [DataMember]
    public string DynamicHtml { get; set; }
    [DataMember]
    public ComplexType2 ComplexType2 { get; set; }
    [DataMember]
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public IEnumerable<int> IDs { get; set; }
    [DataMember]
    public bool TitleUnderline { get; set; }
    [DataMember]
    public VerticalAlignmentEnum TitleVerticalAlign { get; set; }
    [DataMember]
    public string TitleHorizontalAlign { get; set; }
    [DataMember]
    public int FontSize { get; set; }
    [DataMember]
    public string FontColor { get; set; }
    [DataMember]
    public string FontName { get; set; }
    [DataMember]
    public string BackgroundColor { get; set; }
    [DataMember]
    public int Height { get; set; }
    [DataMember]
    public int Width { get; set; }
    [DataMember]
    public int ImageHeight { get; set; }
    [DataMember]
    public int ImageWidth { get; set; }
    [DataMember]
    public string ImagePlacement { get; set; }
    [DataMember]
    [JsonConverter(typeof(StringEnumConverter))]
    public ImageFormatTypeEnum ImageFormat { get; set; }
    [DataMember]
    [JsonConverter(typeof(StringEnumConverter))]
    public ContentRatingEnum ContentRating { get; set; }
    [DataMember]
    public int ArticleCount { get; set; }
    [JsonIgnore]
    public Enum EnumValue { get; set; }
    [DataMember(IsRequired = true)]
    public bool AutoAssign { get; set; }
    [DataMember]
    public bool IsActive { get; set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public int ContainerID { get; set; }
    [DataMember]
    public int AccountID { get; set; }
    [DataMember]
    public int CompanyID { get; set; }
    [DataMember]
    public int ID { get; set; }
    [DataMember]
    public DateTime CreatedOn { get; set; }
    [DataMember]
    public DateTime UpdatedOn { get; set; }

}

var data = new[] { new ComplexType(1), new ComplexType(2) };
var args = new MyArgsType { CallbackFunctionName = "Callback", Data = data};
await context.CallSubOrchestratorAsync("RegisterCallback", args);

Thanks, I think I found the issue. It looks like we're serializing the input to the sub-orchestration twice. Our unit tests didn't catch this because we didn't test this API using complex types.

It's a simple fix, and we'll include this in the next update (at which point you'll need to remove your workaround). Thanks again for reporting this!

FYI @tohling

This is now fixed in the dev branch and will be included in our next release.

Was this page helpful?
0 / 5 - 0 ratings