diff --git a/src/Nancy.Serialization.JsonNet.Tests/ModelBindingFixture.cs b/src/Nancy.Serialization.JsonNet.Tests/ModelBindingFixture.cs index cb640aa..d9e6158 100644 --- a/src/Nancy.Serialization.JsonNet.Tests/ModelBindingFixture.cs +++ b/src/Nancy.Serialization.JsonNet.Tests/ModelBindingFixture.cs @@ -52,6 +52,67 @@ public void when_binding_to_a_collection() // Then Assert.Equal(2, int.Parse(result.Body.AsString())); + } + + [Fact] + public void Should_BindTo_Existing_Instance_Using_Body_Serializer() + { + //Given + var module = new ConfigurableNancyModule(c => c.Post("/instance", (_, m) => + { + var model = new Stuff() { Id = 1 }; + m.BindTo(model); + return model; + })); + + var bootstrapper = new TestBootstrapper(config => config.Module(module)); + + var postmodel = new Stuff { Name = "Marsellus Wallace" }; + + var browser = new Browser(bootstrapper); + + //When + var result = browser.Post("/instance", with => + { + with.JsonBody(postmodel, new JsonNetSerializer()); + with.Accept("application/json"); + }); + + var resultModel = result.Body.DeserializeJson(); + + //Then + Assert.Equal("Marsellus Wallace", resultModel.Name); + Assert.Equal(1, resultModel.Id); + } + + [Fact] + public void Should_BindTo_Existing_Instance_Using_Body_Serializer_And_BlackList() + { + //Given + var module = new ConfigurableNancyModule(c => c.Post("/instance", (_, m) => + { + var model = new Stuff() { Id = 1 }; + m.BindTo(model, new[]{"LastName"}); + return model; + })); + + var bootstrapper = new TestBootstrapper(config => config.Module(module)); + + var postmodel = new Stuff { Name = "Marsellus Wallace", LastName = "Smith"}; + + var browser = new Browser(bootstrapper); + + //When + var result = browser.Post("/instance", with => + { + with.JsonBody(postmodel, new JsonNetSerializer()); + with.Accept("application/json"); + }); + + var resultModel = result.Body.DeserializeJson(); + + //Then + Assert.Null(resultModel.LastName); } } public class TestBootstrapper : ConfigurableBootstrapper @@ -80,7 +141,11 @@ public Stuff() { } - public int Id { get; set; } + public int Id { get; set; } + + public string Name { get; set; } + + public string LastName { get; set; } public Stuff(int id) { diff --git a/src/Nancy.Serialization.JsonNet/JsonNetBodyDeserializer.cs b/src/Nancy.Serialization.JsonNet/JsonNetBodyDeserializer.cs index ebd3009..da9429d 100644 --- a/src/Nancy.Serialization.JsonNet/JsonNetBodyDeserializer.cs +++ b/src/Nancy.Serialization.JsonNet/JsonNetBodyDeserializer.cs @@ -50,9 +50,39 @@ public bool CanDeserialize(string contentType, BindingContext context) /// Model instance public object Deserialize(string contentType, Stream bodyStream, BindingContext context) { - var deserializedObject = + var deserializedObject = this.serializer.Deserialize(new StreamReader(bodyStream), context.DestinationType); - + + if (!context.DestinationType.IsCollection()) + { + var existingInstance = false; + foreach (var property in context.ValidModelProperties) + { + var existingValue = property.GetValue(context.Model, null); + + if (!IsDefaultValue(existingValue, property.PropertyType)) + { + existingInstance = true; + break; + } + } + + if (existingInstance) + { + foreach (var property in context.ValidModelProperties) + { + var existingValue = property.GetValue(context.Model, null); + + if (IsDefaultValue(existingValue, property.PropertyType)) + { + CopyPropertyValue(property, deserializedObject, context.Model); + } + } + + return context.Model; + } + } + if (context.DestinationType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Except(context.ValidModelProperties).Any()) { return CreateObjectWithBlacklistExcluded(context, deserializedObject); @@ -97,5 +127,12 @@ private static void CopyPropertyValue(PropertyInfo property, object sourceObject { property.SetValue(destinationObject, property.GetValue(sourceObject, null), null); } + + private static bool IsDefaultValue(object existingValue, Type propertyType) + { + return propertyType.IsValueType + ? Equals(existingValue, Activator.CreateInstance(propertyType)) + : existingValue == null; + } } } \ No newline at end of file