JSON Serialization sometimes includes type, sometimes not

In our program, we have a Dictionary

public Dictionary<string, object> GlobalState { get; set; }

in which we Add GlobalState.Add("__REFS__", new Dictionary<string, ActionInstanceReference>());

Where ActionInstanceReference is a custom type with a few simple properties (all strings).

public class ActionInstanceReference
{
    public string Type { get; set; }
    public string Id { get; set; }
    public string Url { get; set; }
    public string PrettyPrint { get; set; }
}

Looking at what the serialized output is:

"__REFS__": {
    "aaa": {
      "__type": "MasterProcessServer.ServiceModel.Interfaces.ActionInstanceReference, MasterProcessServer.ServiceModel",
      "type": "Message",
      "prettyPrint": "Message to MDK 2892"
    },
    "bbb": {
      "type": "Message",
      "prettyPrint": "Message to MDK 612"
    },
    "ccc": {
      "type": "Message",
      "prettyPrint": "Message to MDK 0"
    },
    "ddd": {
      "type": "Form",
      "id": "7400",
      "url": "xxxxx",
      "prettyPrint": "Book exit conversation"
    }
}

Here we can see that the last one, ddd includes all the properties. Some others don’t have all, because they are NULL, which is OK. But why does aaa include __type and not the others?

Our JSConfig is:

 JsConfig.Init(new ServiceStack.Text.Config
 {
     DateHandler = DateHandler.ISO8601,
     AlwaysUseUtc = false,
     TextCase = TextCase.CamelCase,
     ExcludeDefaultValues = false,        
     IncludeNullValues = false
 });

Now we’re suddenly getting error ActionInstanceReference is not an allowed Runtime Type. Whitelist Type with [Serializable] ...., which we can do, but why does it suddenly happen now, and only sporadically?

If you’re using it an unknown type like a object or interface or abstract class than that’s an open place holder that opens your APIs into allowing deserialization of any type which opens a security vulnerability that you need to lock down by specifying which are “known safe Types” that are allowed to be deserialized, see:

https://docs.servicestack.net/json-format#runtime-type-whitelist

Yes, but do you know why the same object sometimes include __type and sometimes not?

It uses heuristics to output it when it thinks its needed, you can try force it to exclude it with:

 JsConfig.Init(new ServiceStack.Text.Config
 {
     ExcludeTypeInfo = true
 });

You can also convert it to an object dictionary obj.ToObjectDictionary() and include that in your object property instead of the type so it doesn’t try to add type info to preserve the type.