Search code examples
c#nancy

NancyFx - Partial BindTo


I am trying to implement a sort of partial update with NancyFx.

I have a class named Resource like this:

public class Resource
{
    public int Id { get; set; }
    public decimal SomeValue { get; set; }
    public bool Enabled { get; set; }
    public DateTime CreationDate { get; set; }
}

My current resource instance contains the following values:

{
    "Id" : 123,
    "SomeValue" : 6,
    "Enabled" : true,
    "CreationDate" : "2015-08-01T13:00:00"
}

I want my PUT method to receive a JSON representing only some of the properties of Resource, e.g.:

{
    "Id": 123,
    "SomeValue" : 54.34
}

Then, I would do a BindTo(myCurrentResourceInstance) and the result would be:

{
    "Id" : 123,
    "SomeValue" : 54.34,
    "Enabled" : true,
    "CreationDate" : "2015-08-01T13:00:00"
}

However, I am getting this:

{
    "Id" : 123,
    "SomeValue" : 54.34,
    "Enabled" : false,
    "CreationDate" : "0001-01-01T00:00:00"
}

The properties contained in the JSON overwrite properly those in the current instance, but the BindTo() method is also changing the properties I haven't specified in the JSON. I would like to overwrite only properties specified in the JSON; the others should remain untouched.

BindTo() receives a BindingConfig as parameter, which has a Overwrite property (https://github.com/NancyFx/Nancy/wiki/Model-binding). When this property is true, it causes BindTo() to overwrite all properties; when it is false, none is overwritten.

Is there some way to accomplish what I want?

Thanks


Solution

  • Since you want to prevent the current value getting overriden by the default ones when not specified in JSON, you can blacklist the undefined ones with :

    BindTo<TModel>(this INancyModule module, TModel instance, params string[] blacklistedProperties)` extension method
    

    Having this, we can extract the property list via reflection and exclude the one defined on the JSON, and pass it to that method :

    var definedProperties = JsonConvert
        .DeserializeObject<JObject>(json)
        .Properties()
        .Select(p => p.Name);
    var allProperties = typeof(Resource)
        .GetProperties(BindingFlags.Public | BindingFlags.Instance)
        .Select(p => p.Name);
    
    module.BindTo(myCurrentResourceInstance, allProperties.Except(definedProperties));
    

    I looked at the Nancy's source on github and I couldn't find anything that exposed the JSON property list, and their serializer is also internal. So, you will have to include another library to do the parsing(I used Newtonsoft.Json).

    I hope that you have access to the your json somehow to retrieve the property list. Since I was not able to find that on the INancyModule, but I guess you do have access to it from higher up.