SerializationBinder.BindToName Not Working

Nov 24, 2011 at 7:57 PM

I've created isolated projects specifically with the code from the blog post ( http://james.newtonking.com/archive/2011/11/19/json-net-4-0-release-4-bug-fixes.aspx ) as well as the unit test code that is checked in. I've created both isolated tests in Mono .Net 4 as well as MS .Net 4 (VS2010) environment and I do not get the expected behavior of class names serialized correctly. I expected  "$type": "Customer" and "$type": "Purchase".

Here is the single file for the console program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Reflection;
using System.Diagnostics;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Converters;

using Corp.Models;


namespace Corp.Models
{
    public class Customer
    {
        public string Name { get; set; }
    }

    public class Purchase
    {
        public string ProductName { get; set; }
        public decimal Price { get; set; }
        public int Quantity { get; set; }
    }
}


namespace Corp
{
    public class TypeNameSerializationBinder : SerializationBinder
    {
        public string TypeFormat { get; private set; }

        public TypeNameSerializationBinder(string typeFormat)
        {
            TypeFormat = typeFormat;
        }

        public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
        {
            Debug.WriteLine("Never called");
            assemblyName = null;
            typeName = serializedType.Name;
        }

        public override Type BindToType(string assemblyName, string typeName)
        {
            Debug.WriteLine("Called");

            string resolvedTypeName = string.Format(TypeFormat, typeName);

            return Type.GetType(resolvedTypeName, true);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Debug.WriteLine(Assembly.GetAssembly(typeof(Newtonsoft.Json.JsonSerializer)).FullName);
            doit1();
        }

        public static void doit1()
        {
            Corp.TypeNameSerializationBinder binder = new Corp.TypeNameSerializationBinder("Corp.Models.{0}, JsonSerializationTest");

            IList<object> values = new List<object>
			        {
			          new Customer
			            {
			              Name = "Caroline Customer"
			            },
			          new Purchase
			            {
			              ProductName = "Elbow Grease",
			              Price = 5.99m,
			              Quantity = 1
			            }
			        };

            string json = JsonConvert.SerializeObject(values, Formatting.Indented, new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Auto,
                Binder = binder
            });

            Debug.WriteLine(json);
        }
    }
}

To which the output is:

Newtonsoft.Json, Version=4.0.4.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
'JsonSerializationTest.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.ComponentModel.DataAnnotations\v4.0_4.0.0.0__31bf3856ad364e35\System.ComponentModel.DataAnnotations.dll'
'JsonSerializationTest.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Runtime.Serialization\v4.0_4.0.0.0__b77a5c561934e089\System.Runtime.Serialization.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
[
  {
    "$type": "Corp.Models.Customer, JsonSerializationTest",
    "Name": "Caroline Customer"
  },
  {
    "$type": "Corp.Models.Purchase, JsonSerializationTest",
    "ProductName": "Elbow Grease",
    "Price": 5.99,
    "Quantity": 1
  }
]

Nov 24, 2011 at 8:41 PM

#shame

The distribution confused me. Was using the 3.5 assembly.

Aug 7, 2014 at 11:59 AM
Edited Aug 7, 2014 at 1:55 PM
I see this is an old post, but I have the same problem, I think: BindToName is never called it seems (breakpoints arent blocking), but BindToType is called.

I am running the 4.5 assembly all over.

Can you perhaps enlighten me as to why its not called? The code I am using looks the same as yours, almost identical.

I have posted on SO about this:
http://stackoverflow.com/questions/25180555/json-net-and-typenameserializationbinder-bindtotype-is-never-called