I'm working with Microsoft WebAPI using the Json.NET serializer and I'm trying to use controller parameter binding to instantiate a Castle DictionaryAdapter as the deserialized object from JSON. (This will allow us to detect whether certain properties are being set to null in the JSON or if they are defaulting to null because they are not in the JSON without having to abandon the built-in parsing and binding mechanism.)
But it's not working because the new object disappears between creation and being passed to the controller.
The controller is declared with an interface parameter:
public interface IMessageModel
{
string Message { get; set; }
}
.
.
.
public HttpResponseMessage Patch(IMessageModel model)
I want the deserializer to instantiate a Castle DictionaryAdapter in that implements IMessageModel.
To do this, I created a subclass of CustomCreationConverter which is constructed with a DictionaryAdapterFactory and which overrides the Create() method to return the dynamic Castle object:
public class MessageModelConverter
: CustomCreationConverter<IMessageModel>
{
private DictionaryAdapterFactory m_adapterFactory;
public MessageModelConverter(DictionaryAdapterFactory adapterFactory)
{
m_adapterFactory = adapterFactory;
}
public override IMessageModel Create(Type objectType)
{
IMessageModel model = m_adapterFactory
.GetAdapter<IMessageModel>(new Hashtable());
return model;
}
}
Then I add a formatter to the HttpConfiguration object something like this:
DictionaryAdapterFactory adapterFactory = new DictionaryAdapterFactory();
config.Formatters.JsonFormatter.SerializerSettings.Converters
.Add(new MessageModelConverter(adapterFactory));
Stepping through with the debugger, I can confirm that the MessageModelConverter is used and that Create() is called and creates and returns a Castle proxy for the model that implements IMessageModel. However, when the controller is called, the model parameter is null. Somehow the instantiated class is disappearing between creation in the converter and use in the controller.
Yet if I change Create to use a concrete class that implements IMessageModel, everything works fine, and the model shows up at the controller:
public class MessageModel : IMessageModel
{
public string Message { get; set; }
}
.
.
.
public override IMessageModel Create(Type objectType)
{
IMessageModel model = new MessageModel();
return model;
}
Alternatively, I can declare a wrapper that implements IMessageModel and delegates all calls to another interface object, something like this:
public class MessageModelWrapper : IMessageModel
{
public IMessageModel ContainedModel;
public MessageModelWrapper(IMessageModel containedModel)
{
ContainedModel = containedModel;
}
public string Message
{
get { return ContainedModel.Message; }
set { ContainedModel.Message = value; }
}
}
Then I implement Create() like this:
public override IMessageModel Create(Type objectType)
{
IMessageModel model = m_adapterFactory
.GetAdapter<IMessageModel>(new Hashtable());
model = new MessageModelWrapper(model);
return model;
}
That allows me to smuggle in the Castle DictionaryAdapter, and it works just fine too. The model wrapper arrives in the controller and I can extract the dictionary adapter proxy.
But when I create and return the Castle DictionaryAdapter directly, the controller still just gets a null.
Any idea why WebAPI hates the Castle DictionaryAdapter?