Storing a Dictionary with polymorphic values in mongoDB using C# - c#

Let us say we have a key with values which are polymorphic in their sense. Consider the next sample project:
public class ToBeSerialized
{
[BsonId]
public ObjectId MongoId;
public IDictionary<string, BaseType> Dictionary;
}
public abstract class BaseType
{
}
public class Type1 : BaseType
{
public string Value1;
}
public class Type2:BaseType
{
public string Value1;
public string Value2;
}
internal class Program
{
public static void Main()
{
var objectToSave = new ToBeSerialized
{
MongoId = ObjectId.GenerateNewId(),
Dictionary = new Dictionary<string, BaseType>
{
{"OdEd1", new Type1 {Value1="value1"}},
{
"OdEd2",
new Type1 {Value1="value1"}
}
}
};
string connectionString = "mongodb://localhost/Serialization";
var mgsb = new MongoUrlBuilder(connectionString);
var MongoServer = MongoDB.Driver.MongoServer.Create(mgsb.ToMongoUrl());
var MongoDatabase = MongoServer.GetDatabase(mgsb.DatabaseName);
MongoCollection<ToBeSerialized> mongoCollection = MongoDatabase.GetCollection<ToBeSerialized>("Dictionary");
mongoCollection.Save(objectToSave);
ToBeSerialized received = mongoCollection.FindOne();
}
}
Sometimes when I try to deserialize it, I get deserialization errors like "Unknown discriminator value 'The name of concrete type'". What am I doing wrong? If every value stores a _t why cannot it map it correctly?

Driver should know about all discriminators to deserialize any class without errors. There are two ways to do it:
1.Register it globally during app start:
BsonClassMap.RegisterClassMap<Type1>();
BsonClassMap.RegisterClassMap<Type2>();
2.Or though the BsonKnownTypes attibute:
[BsonKnownTypes(typeof(Type1), typeof(Type2)]
public class BaseType
{
}
If you will use #1 or #2 your deserialization will work correctly.

You have to register which types inherit from BaseClass before attempting to deserialize them. This will happen automatically if you serialize first, which is probably why the error occurs only sometimes.
You can register derived types using an attribute:
[BsonDiscriminator(Required = true)]
[BsonKnownTypes(typeof(DerivedType1), typeof(DerivedType2))]
public class BaseClass { ... }
public class DerivedType1 : BaseClass { ... }

Related

Deserializing inherited classes

I want to send parameter-settings from a backendapplication to the frontend. I also need to be able to have different type of parameters (Portnumbers, folders, static strings and such).
So I've designed a baseclass, Parameter as such:
public abstract class Parameter
{
public abstract bool isValid();
}
Let's say that we have two types of folder parameters:
public abstract class Folder : Parameter
{
public string folderName { get; set; }
protected Folder(string folderName)
{
this.folderName = folderName;
}
}
public class ReadWriteFolder : Folder
{
public ReadWriteFolder(string folderName) : base(folderName)
{
}
public override bool isValid()
{
return isReadable() && isWritable();
}
}
public class ReadFolder : Folder
{
public ReadFolder(string folderName) : base(folderName)
{
}
public override bool isValid()
{
return isReadable();
}
}
This is used from a WebAPI, so this is my controller:
public Dictionary<String, Parameter> Get()
{
Dictionary<String, Parameter> dictionary = new Dictionary<String, Parameter>();
dictionary.Add("TemporaryFiles", new ReadWriteFolder("C:\\temp\\"));
dictionary.Add("AnotherTemporaryFiles", new ReadWriteFolder("D:\\temp\\"));
return dictionary;
}
This yields the following JSON-serialisation:
{"TemporaryFiles":{"folderName":"C:\\temp\\"},"AnotherTemporaryFiles":{"folderName":"D:\\temp\\"}} which seems reasonable.
My question is this: How can I deserialize this back into the original types? Or change the serialization into something that is more easy to deserialize?
What are you using for serialization? If it's JSON.Net (which many here would suggest!), there's a number of realted questions:
how to deserialize JSON into IEnumerable with Newtonsoft JSON.NET
But the crux is the type name handling, which will decorate the elements with the type information to be able to deserialize them:
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
};
string strJson = JsonConvert.SerializeObject(dictionary, settings);
And then you should be able to deserialize directly.
var returnDictionary = JsonConvert.DeserializeObject<Dictionary<String, Parameter>>(strJson, settings)

Implement a dictionary of classes for a pseudo class factory

I´m trying to buld a class factory like that:
public class Toyota() {};
public class Bmw() {};
public class Mercedes() {};
public class BrandFactory
{
private Dictionary<string, object> _Brands = new Dictionary<string, object> {
{"Toyota", Toyota},
{"Bmw", Bmw},
{"Mercedes", Mercedes}
}
public object GetBrand(string brandName)
{
return = BusinessManagers[brandName].Invoke;
}
}
This is the idea, but it´s not working - I can´t even compile the above code as the Dictionary cannot associate an 'object' with the function. I tried Func<> as well, but in that case it requires a previous type.
So, here are my questions:
Is that a correct way to implement this 'pseudo factory' ? The code came from the example at example code
If so, what needs to be fixed in the above code ?
The reason I´m asking that is because I need to create a new object based on a string that is received from a cliente application using Ajax. Like:
AjaxCall -> String Containing Object Name -> Object Inoke -> Method Call -> Send result back to client
The Method Call is a standard for all implementation of Brand.
Please can someone help me with that ?
Thanks.
You have a several options here. If you end up using a Dictionary, I recommend making it case-insensitive and taking care to avoid KeyNotFoundExceptions.
public class CaseInsensitiveStringComparer : IComparer<string>
{
public int Compare(string x, string y)
{
return string.Compare(x, y, ignoreCase: true);
}
}
The first option is to use Dictionary<string, Func<object>>.
private IDictionary<string, Func<object>> _Brands
= new Dictionary<string, Func<object>> (new CaseInsensitiveStringComparer())
{
{"Toyota", () => new Toyota() },
{"BMW", () => new Bmw() },
{"Mercedes", () => Mercedes() }
};
public object GetBrand(string brandName)
{
Func<object> func;
return _Brands.TryGetValue(brandName, out func)
? func() // invoking the delegate creates the instance of the brand object
: null; // brandName was not in the dictionary
}
Second option is to use Activator. You can use a Dictionary<string,Type>, but it may not be necessary if your type name matches the string (see notes below).
public object GetBrand(string brandName)
{
Type type;
return _Brands.TryGetValue(brandName, out type)
? Activator.CreateInstance(type) // activator invokes a parameterless constructor
: null; // brandName was not in the dictionary
}
// vs.
return Activator.CreateInstance(null, brandName).Unwrap();
// Case sensitivity would be an issue here.
// Security could be an issue here.
// Creating objects based directly off of user input means any class
// from any referenced assembly could be created if a hacker can learn
// out the namespaces and class names.
Third option is to use an IoC container to do the resolution. This gives you some flexibility with lifetime management.
The second approach currently assumes a parameterless constructor, wherease the first and third would allow for disparate constructor signatures.
In all cases, the result is simply object, which gives this approach limited utility. If all of these "brand" classes could share a common interface, then you could use IBrand or whatever in your Dictionary and as the return type.
I'm checking for bad data (values not in the Dictionary) and returning null; you could choose to throw an Exception if that makes more sense for your use case.*
You do not need a Dictionary at all:
public class DynamicFactory<T>
{
public static T Create(string className)
{
Type t = typeof(T);
return (T)Activator.CreateInstance(
t.Assembly.FullName,
t.Namespace + "." + className
).Unwrap();
}
}
namespace Brands
{
public class CarBrand { }
// The brands should be in the same namespace and assembly with CarBrand
// and should inherit from CarBrand
public class Toyota : CarBrand { };
public class Bmw : CarBrand { };
public class Mercedes : CarBrand { };
public class Titanic { } // this one is not CarBrand
class BrandFactory: DynamicFactory<CarBrand> { }
// Below are unit tests using NUnit
namespace BrandFactorySpecification
{
static class Create
{
[TestCase("Toyota", Result = typeof(Toyota))]
[TestCase("Bmw", Result = typeof(Bmw))]
[TestCase("Mercedes", Result = typeof(Mercedes))]
[TestCase("Titanic", ExpectedException = typeof(InvalidCastException))]
[TestCase("unknown", ExpectedException = typeof(TypeLoadException))]
[TestCase("String", ExpectedException = typeof(TypeLoadException))]
[TestCase("System.String", ExpectedException = typeof(TypeLoadException))]
[TestCase("ACarBrandFromAnotherNamespace",
ExpectedException = typeof(TypeLoadException))]
[TestCase("AnotherNamespace.ACarBrandFromAnotherNamespace",
ExpectedException = typeof(TypeLoadException))]
//
public static Type ShouldReturnCorrectType(string brandName)
{
return BrandFactory.Create(brandName).GetType();
}
[Test]
public static void ForTitanic()
{
DynamicFactory<Titanic>.Create("Titanic")
.ShouldBeType(typeof(Titanic));
}
}
namespace AnotherNamespace
{
public class ACarBrandFromAnotherNamespace : CarBrand { };
}
}
}
Update: the code was improved in the following ways:
The security problem, mentioned in the comments was fixed
flexibility improved
A new generic class DynamicFactory<T> now can be reused elsewhere
Brands can be located in other namespace and assembly then BrandFactory
Unit tests were added to serve as examples of usage and specification (using NUnit required for them)
That's not at all how a factory works. First of all you need a superclass that can be the parent of your car models:
public class CarModel() {};
public class Toyota() : CarModel {};
public class Bmw() : CarModel {};
public class Mercedes() : CarModel {};
Now you can create a factory that returns the correct model:
public class BrandFactory
{
public T GetBrand<T>() where T : CarModel
{
return new T();
}
}
Now when you want to create a object its is simple:
var factory = new BrandFactory();
var bmw = factory.GetBrand<Bmw>();

How to create the correct inherited class based on what is stored in the database

What Utility or Pattern can be used to solve this Issue? I don't know what can be used to assist with this. Can we use some type of pattern?
If you have the following abstract class:
abstract class Foo
{
function void Something()
{
// Get the media type
}
}
And the following classes that derive from that class:
class Foo1 : Foo
{
public string MyId {get;set}
public string MyFile {get;set}
public TxtFile MyTextFile {get;set}
function void myFooFunction()
{
// Save File to Txt
}
}
class Foo2 : Foo
{
public string MyId {get;set}
public string MyFile {get;set}
public XMLFile MyXMLFile {get;set}
function MyOtherFunction()
{
// Save to XML
}
}
Then in Linq (or Similar) within the repository you do something like this:
var a = (from e in db.myTable
where e.myFileType == "XML"
Select e);
Then we have to map this to the correct object. Like this:
Foo newFoo = FooFactory.CreateFooFor(a.myFileType.ToString())
newFoo.MyId = a.id;
newFoo.MyFile = a.myfile;
newFoo.MyXMLFile = a.xml;
The Factory certainly helps, but how do you do this for multiple "FileTypes" like txt for example? The Fields wouldn't match up!
Do I have to write more code that does the same thing??
I feel like there has to be something that can do this.
First, if myFooFunction and MyOtherFunction are both used to save, you can use the strategy pattern and just define and abstract Save() method to implement in derived classes. You might also look at the Template Method pattern.
Although this isn't exactly a pattern, you might also want to apply the "Pull Up Field" refactoring here and put the MyId and MyFile properties in the parent class.
For creation...
The Builder pattern is similar to the factory, but allows for more complex object creation. I don't know how well it fits this simplified example, but it might fit what you are actually trying to do in your real code. Probably not. I just mention it first because it is the closest to factory in my mind.
There are also the Mapper Pattern and the Data Mapper Pattern. You might encapsulate the mapping in an object and have the factory return a mapper:
FooMapper mapper = FooMapperFactory.CreateFooMapperFor(a.myFileType);
Foo newFoo = mapper.CreateFoo(a);
I believe you could solve your problem using generics. I took the liberty of changing around some code. Would this work?
public abstract class Foo
{
public abstract void Save();
public void Something()
{
// Get the media type
}
}
public class FooText : Foo
{
public string MyId { get; set; }
public string MyFile { get; set; }
public string MyTextFile { get; set; }
public override void Save()
{
// Save File to Txt
}
}
public class FooXml : Foo
{
public string MyId { get; set; }
public string MyFile { get; set; }
public string MyXMLFile { get; set; }
public override void Save()
{
// Save to XML
}
}
public class FooFactory<T> where T : Foo, new()
{
public static T CreateFoo()
{
return new T();
}
}
If you consider using reflection on the data that's returned from the database, or perhaps the Adapter pattern you can set up a dynamic way to map fields to each other. Using reflection (the following is pseudo logic as reflection is kind of messy code to provide):
Get a list of PropertyInfo objects for all public properties from the target type
Get a list of PropertyInfo objects for all public properties from the database type
Compare their names/types to create the mapping
Assign values from the database type, using reflection, to the target type
Something like this will do the trick:
public void AssignAndMapTypes<DatabaseType, TargetType>(DatabaseType db, ref TargetType target)
{
var dbType = db.GetType();
var dbTypeProperties = dbType.GetProperties(System.Reflection.BindingFlags.Public);
var targetType = target.GetType();
var targetTypeProperties = targetType.GetProperties(System.Reflection.BindingFlags.Public);
foreach (var prop in targetTypeProperties)
{
var matchingProp = dbTypeProperties.Where(e => { return (string.Compare(e.Name, prop.Name, true) == 0) && (e.PropertyType == prop.PropertyType) }).FirstOrDefault();
if(matchingProp != null)
{
prop.SetValue(target, matchingProp.GetValue(db, null), null);
}
}
}

Using Web API to deserialize into class with abstract property

I'm attempting to write a set of classes to represent a particularly complex object, and in one of those classes, I have a property that is set as the base (abstract) class of three possible derived classes. I'm setting up an ASP.NET Web API to handle the serialization and deserialization, which means that, by default, it uses Json.NET for JSON. How can I get the Web API to properly deserialize JSON sent via POST or PUT into the proper derived class?
The class with the abstract member looks like this (I'm including the Xml decorators for clarity and because they work perfectly well for deserializing xml using the XmlSerializer)
[Serializable]
public class FormulaStructure {
[XmlElement("column", typeof(ColumnStructure))]
[XmlElement("function", typeof(FunctionStructure))]
[XmlElement("operand", typeof(OperandStructure))]
public AFormulaItemStructure FormulaItem;
}
The abstract class is pretty basic:
[Serializable]
public abstract class AFormulaItemStructure { }
And there are three derivatives of the abstract class:
[Serializable]
public class ColumnStructure: AFormulaItemStructure {
[XmlAttribute("type")]
public string Type;
[XmlAttribute("field")]
public string Field;
[XmlAttribute("display")]
public string Display;
}
[Serializable]
public class FunctionStructure: AFormulaItemStructure {
[XmlAttribute("type")]
public string Type;
[XmlAttribute("name")]
public string Name;
[XmlElement("parameters")]
public string Parameters;
}
[Serializable]
public class OperandStructure: AFormulaItemStructure {
[XmlAttribute("type")]
public string Type;
[XmlElement("left")]
public string Left;
[XmlElement("right")]
public string Right;
}
At present, using [DataContract] attributes, the Json.NET formatter fails to populate the derived class, leaving the property null.
Questions
Can I mix XmlSerializer attributes with DataContractSerializer attributes on the same class? I use the XmlSerializer because I use xml attributes in the xml I designed, but that can be changed if necessary since I am developing the xml schema myself.
What is the equivalent in Json.NET to [KnownType()] ? Json.NET doesn't appear to respect the DataContractSerializer version of KnownType. Will I need to roll my own JsonConverter to determine the proper type?
How would I decorate the classes so that DataContractSerializer or DataContractJsonSerializer will properly deserialize the objects in both Xml and Json? My goal is to put this into an ASP.NET Web API, so I want the flexibility to generate Xml or Json, as appropriate to the requested type. Is there an alternative formatter that I need to use to work with this complex class, if Json.NET won't work?
I need the ability to generate an object on the client side without necessarily including the .NET class names into the object.
Testing and Refinement
In my testing of the Web API, the default serialization sends down to the client:
{"FormulaItem":{"type":"int","field":"my_field","display":"My Field"}}
which is ideal for my purposes. Getting this to go back to the API and deserialize into the proper derived types, though, isn't working (it's generating null for the property).
Testing Tommy Grovnes answer below, the DataContractSerializer he used for testing generates:
{"FormulaItem":{"__type":"column:#ExpressionStructureExperimentation.Models","display":"My Field","field":"my_field","type":"int"}}
which doesn't work for me, or for code maintainability (refactoring becomes a PITA if I hard-code the entire namespace into the JavaScript for generating these objects).
You can mix as mentioned already but I don't think you need to, haven't used WEB api myself but WCF Rest produces xml and json from DataContracts (without Xml.. tags), tag your classes like this:
[DataContract]
public class FormulaStructure
{
[DataMember]
public AFormulaItemStructure FormulaItem;
}
[DataContract]
[KnownType(typeof(ColumnStructure))]
[KnownType(typeof(FunctionStructure))]
[KnownType(typeof(OperandStructure))]
public abstract class AFormulaItemStructure { }
[DataContract(Name="column")]
public class ColumnStructure : AFormulaItemStructure
{
[DataMember(Name="type")]
public string Type;
[DataMember(Name = "field")]
public string Field;
[DataMember(Name = "display")]
public string Display;
}
[DataContract(Name="function")]
public class FunctionStructure : AFormulaItemStructure
{
[DataMember(Name = "type")]
public string Type;
[DataMember(Name = "name")]
public string Name;
[DataMember(Name = "parameters")]
public string Parameters;
}
[DataContract(Name = "operand")]
public class OperandStructure : AFormulaItemStructure
{
[DataMember(Name = "type")]
public string Type;
[DataMember(Name = "left")]
public string Left;
[DataMember(Name = "right")]
public string Right;
}
If you need more control over the XML/JSON generated you might have to tweak this further. I used this code to test:
public static string Serialize(FormulaStructure structure)
{
using (MemoryStream memoryStream = new MemoryStream())
using (StreamReader reader = new StreamReader(memoryStream))
{
var serializer = new DataContractSerializer(typeof(FormulaStructure));
serializer.WriteObject(memoryStream, structure);
memoryStream.Position = 0;
return reader.ReadToEnd();
}
}
public static FormulaStructure Deserialize(string xml)
{
using (Stream stream = new MemoryStream())
{
byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
stream.Write(data, 0, data.Length);
stream.Position = 0;
var deserializer = new DataContractSerializer(typeof(FormulaStructure));
return (FormulaStructure)deserializer.ReadObject(stream);
}
}
After we ran into some issues much further down the line with my previous answer, I discovered the SerializationBinder class that JSON can use for serializing/deserializing namespaces.
Code First
I generated a class to inherit the SerializationBinder:
public class KnownTypesBinder : System.Runtime.Serialization.SerializationBinder {
public KnownTypesBinder() {
KnownTypes = new List<Type>();
AliasedTypes = new Dictionary<string, Type>();
}
public IList<Type> KnownTypes { get; set; }
public IDictionary<string, Type> AliasedTypes { get; set; }
public override Type BindToType(string assemblyName, string typeName) {
if (AliasedTypes.ContainsKey(typeName)) { return AliasedTypes[typeName]; }
var type = KnownTypes.SingleOrDefault(t => t.Name == typeName);
if (type == null) {
type = Type.GetType(Assembly.CreateQualifiedName(assemblyName, typeName));
if (type == null) {
throw new InvalidCastException("Unknown type encountered while deserializing JSON. This can happen if class names have changed but the database or the JavaScript references the old class name.");
}
}
return type;
}
public override void BindToName(Type serializedType, out string assemblyName, out string typeName) {
assemblyName = null;
typeName = serializedType.Name;
}
}
How it works
Let's say I have a set of classes defined thus:
public class Class1 {
public string Text { get; set; }
}
public class Class2 {
public int Value { get; set; }
}
public class MyClass {
public Class1 Text { get; set; }
public Class2 Value { get; set; }
}
Aliased Types
What this does is allows me to generate my own names for classes that will be serialized/deserialized. In my global.asax file, I apply the binder as such:
KnownTypesBinder binder = new KnownTypesBinder()
binder.AliasedTypes["Class1"] = typeof(Project1.Class1);
binder.AliasedTypes["WhateverStringIWant"] = typeof(Project1.Class2);
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.Binder = binder;
Now, whenever I serialize, say, MyClass as JSON, I get the following:
{
item: {
$type: "Project1.MyClass",
Text: {
$type: "Class1",
Text: "some value"
},
Value: {
$type: "WhateverStringIWant",
Value: 88
}
}
}
Known Types
I can also choose to strip off the assembly information and strictly use the class name by adding information to the KnownTypesBinder:
KnownTypesBinder binder = new KnownTypesBinder()
binder.KnownTypes.Add(typeof(Project1.Class1));
binder.KnownTypes.Add(typeof(Project1.Class1));
In the two examples given, Class1 is referenced the same way. However, if I refactor Class1 to, say, NewClass1, then this second example will start sending a different name. That may or may not be a big deal, depending on whether you are using the types or not.
Final Thoughts
The advantage of the AliasedTypes is that I can give it any string that I want, and it doesn't matter how much I refactor the code, the communication between the .NET and the JavaScript (or whatever consumer is out there) is unbroken.
Be careful not to mix AliasedTypes and KnownTypes that have the exact same class name, because the code is written that the AliasType will win out over KnownType. When the binder doesn't recognize a type (aliased or known), it will provide the full assembly name of the type.
In the end, I broke down and added the .NET class information to the module in string variables to make refactoring easier.
module.net = {};
module.net.classes = {};
module.net.classes['column'] = "ColumnStructure";
module.net.classes['function'] = "FunctionStructure";
module.net.classes['operand'] = "OperandStructure";
module.net.getAssembly = function (className) {
return "MyNamespace.Models." + module.net.classes[className] + ", MyAssembly";
}
and generated the JSON as
{
"FormulaItem": {
"$type": module.net.getAssembly('column'),
"type": "int",
"field": "my_field",
"display": "My Field"
}
}

Json.net serialize/deserialize derived types?

json.net (newtonsoft)
I am looking through the documentation but I can't find anything on this or the best way to do it.
public class Base
{
public string Name;
}
public class Derived : Base
{
public string Something;
}
JsonConvert.Deserialize<List<Base>>(text);
Now I have Derived objects in the serialized list. How do I deserialize the list and get back derived types?
You have to enable Type Name Handling and pass that to the (de)serializer as a settings parameter.
Base object1 = new Base() { Name = "Object1" };
Derived object2 = new Derived() { Something = "Some other thing" };
List<Base> inheritanceList = new List<Base>() { object1, object2 };
JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
string Serialized = JsonConvert.SerializeObject(inheritanceList, settings);
List<Base> deserializedList = JsonConvert.DeserializeObject<List<Base>>(Serialized, settings);
This will result in correct deserialization of derived classes. A drawback to it is that it will name all the objects you are using, as such it will name the list you are putting the objects in.
If you are storing the type in your text (as you should be in this scenario), you can use the JsonSerializerSettings.
See: how to deserialize JSON into IEnumerable<BaseType> with Newtonsoft JSON.NET
Be careful, though. Using anything other than TypeNameHandling = TypeNameHandling.None could open yourself up to a security vulnerability.
Since the question is so popular, it may be useful to add on what to do if you want to control the type property name and its value.
The long way is to write custom JsonConverters to handle (de)serialization by manually checking and setting the type property.
A simpler way is to use JsonSubTypes, which handles all the boilerplate via attributes:
[JsonConverter(typeof(JsonSubtypes), "Sound")]
[JsonSubtypes.KnownSubType(typeof(Dog), "Bark")]
[JsonSubtypes.KnownSubType(typeof(Cat), "Meow")]
public class Animal
{
public virtual string Sound { get; }
public string Color { get; set; }
}
public class Dog : Animal
{
public override string Sound { get; } = "Bark";
public string Breed { get; set; }
}
public class Cat : Animal
{
public override string Sound { get; } = "Meow";
public bool Declawed { get; set; }
}
Use this JsonKnownTypes, it's very similar way to use, it just add discriminator to json:
[JsonConverter(typeof(JsonKnownTypeConverter<BaseClass>))]
[JsonKnownType(typeof(Base), "base")]
[JsonKnownType(typeof(Derived), "derived")]
public class Base
{
public string Name;
}
public class Derived : Base
{
public string Something;
}
Now when you serialize object in json will be add "$type" with "base" and "derived" value and it will be use for deserialize
Serialized list example:
[
{"Name":"some name", "$type":"base"},
{"Name":"some name", "Something":"something", "$type":"derived"}
]
just add object in Serialize method
var jsonMessageBody = JsonSerializer.Serialize<object>(model);

Categories