Hi,
I'm working on a custom chat bot command that retrieves the last BPA results. See repo here: SkylineCommunications/SLC-AS-ChatOps-BPA (github.com).
The script uses the following NuGet packages:
which results in the following DLL references when deploying the script on the agent:
The problem I'm facing is that the "AdaptiveCards" NuGet does not seem to be compatible with the latest NewtonSoft NuGet (13.0.2 in this case) which is (from what I understood) referenced in the "Skyline.DataMiner.Core.DataMinerSystem.Automation" NuGet. If I manually change the reference for the NewtonSoft NuGet to version 11.0.2 (C:\Skyline DataMiner\ProtocolScripts\DllImport\newtonsoft.json\11.0.2\lib\net45\Newtonsoft.Json.dll), then my command is working as expected.
Is there anyway to enforce the use of that specific NuGet version so I don't have to manually change this after deploying my script?
After a long investigation it turns out that it looks like the [JsonObject] on top of the AdaptiveTypedElement class is not being detected. The attribute defines that classes need to be serialized as object, even though as array might be more appropriate. Because the attribute is not detected, some classes are being serialized as array, which is causing the NotImplementedException.
This is related to how DataMiner is loading DLLs into memory. What happens is the following:
- When the AdaptiveCards DLL is loaded, it uses the attributes from Newtonsoft11, specifically the AdaptiveTypedElement with Newtonsoft11.JsonObjectAttribute.
- Newtonsoft13 is used for serialization and looks for the NewtonSoft13.JsonObjectAttribute above classes. Since this attribute is not available (because the AdaptiveCards dll relies on the older version, Newtonsoft11), Newtonsoft13 behaves as if this attribute does not exist. Serialization continues as if theJsonObjectAttribute is not specified above the AdaptiveTypedElement class.
As a workaround you can force to serialize as object instead of array, by using a custom resolver:
private static void Test()
{
var adaptiveCardBody = new List<AdaptiveElement>()
{
new AdaptiveContainer { new AdaptiveFactSet(), }
};var settings = new JsonSerializerSettings()
{
ContractResolver = new CustomContractResolver(),
};var json = JsonConvert.SerializeObject(adaptiveCardBody, settings);
}
}public class CustomContractResolver : DefaultContractResolver
{
public override JsonContract ResolveContract(Type objectType)
{
var contract = base.ResolveContract(objectType);if (typeof(AdaptiveCollectionElement).IsAssignableFrom(contract.UnderlyingType))
{
contract = CreateObjectContract(objectType);
}return contract;
}
}
Thanks Tom! Even though that indeed solves the issues with the serialization (exception no longer thrown). It does result in a different string which causes problems when it is being deserialized to show the AdaptiveCard in Teams.
We are in the progress of designing several POC’s that will change the architecture of how DataMiner loads up assemblies to address problems with assembly version conflicts and inconsistent behavior between a normal program/visual studio and the runtime of the code on a DataMiner.
Without going too deep into it. The root cause of most of these issues is the lack of bindingredirects in DataMiner for automationscripts and connectors. It’s that lack we’ll be looking to fix. We’ve got a few options but they all consist of running more than one SLScripting process or similar which will need good scaling tests.