And the culprit is TryReadQueryAs method of UriExtensions that just instantiates a new JsonSerializer that doesn't use global serializer settings, defined in config.Formatters.JsonFormatter.SerializerSettings. One of the consequences of this, is that I can't bind derived classes to base classes, using JSON.NET TypeNameHandling. Please fix this ASAP.
For example:
I serialize an Employee, and since i set TypeNameHandling to auto, it will add $type="Employee" to the serialized json. Then when I send that json back to some method that expects class Person, it will bind it to person (Employee properties will not get bound) and will ignore the type, because the said method doesn't use global settings(where I set TypeNameHandling). And hence uses TypeNameHandling.None.
So solution is just use the global settings when you instatiate the serializer in TryReadQueryAs method
Comments: I am not sure if this is a problem with Web API. I have tried the following using the "Auto" setting of TypeNameHandling. Looks like this is an issue with Json.Net's serializer itself. Models: -------- ``` public class Person { public int Id { get; set; } public string Name { get; set; } } public class Employee : Person { public string DepartmentName { get; set; } } ``` Code: ------ ``` JsonSerializer ser = new JsonSerializer(); ser.TypeNameHandling = TypeNameHandling.Auto; StringWriter sw = new StringWriter(); ser.Serialize(new JsonTextWriter(sw), new Employee() { Id = 1, Name = "Scott", DepartmentName = "ASP.NET" }); Console.WriteLine(sw.ToString()); ``` Result1 (if using TypeNameHandling.Auto..note there is NO type info) ------------------------------------------ {"DepartmentName":"ASP.NET","Id":1,"Name":"Scott"} Result2 (if using TypeNameHandling.Objects..note there is type info) ----------------------------------------------------- {"$type":"Service.Employee, ConsoleApplication5","DepartmentName":"ASP.NET","Id":1,"Name":"Scott"} Following is the possible bug in Json.net related to this: -------------------------- http://json.codeplex.com/workitem/23891
For example:
I serialize an Employee, and since i set TypeNameHandling to auto, it will add $type="Employee" to the serialized json. Then when I send that json back to some method that expects class Person, it will bind it to person (Employee properties will not get bound) and will ignore the type, because the said method doesn't use global settings(where I set TypeNameHandling). And hence uses TypeNameHandling.None.
So solution is just use the global settings when you instatiate the serializer in TryReadQueryAs method
Comments: I am not sure if this is a problem with Web API. I have tried the following using the "Auto" setting of TypeNameHandling. Looks like this is an issue with Json.Net's serializer itself. Models: -------- ``` public class Person { public int Id { get; set; } public string Name { get; set; } } public class Employee : Person { public string DepartmentName { get; set; } } ``` Code: ------ ``` JsonSerializer ser = new JsonSerializer(); ser.TypeNameHandling = TypeNameHandling.Auto; StringWriter sw = new StringWriter(); ser.Serialize(new JsonTextWriter(sw), new Employee() { Id = 1, Name = "Scott", DepartmentName = "ASP.NET" }); Console.WriteLine(sw.ToString()); ``` Result1 (if using TypeNameHandling.Auto..note there is NO type info) ------------------------------------------ {"DepartmentName":"ASP.NET","Id":1,"Name":"Scott"} Result2 (if using TypeNameHandling.Objects..note there is type info) ----------------------------------------------------- {"$type":"Service.Employee, ConsoleApplication5","DepartmentName":"ASP.NET","Id":1,"Name":"Scott"} Following is the possible bug in Json.net related to this: -------------------------- http://json.codeplex.com/workitem/23891