From b1684411b865a2d336ced697371862b1b48c97f6 Mon Sep 17 00:00:00 2001 From: Jonathan Channon Date: Fri, 31 Jan 2014 12:22:23 +0000 Subject: [PATCH 1/2] tests for existing instances when using BindTo --- .../ModelBindingFixture.cs | 67 ++++++++++++++++++- .../JsonNetBodyDeserializer.cs | 38 ++++++++++- 2 files changed, 102 insertions(+), 3 deletions(-) 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..bd1b5fb 100644 --- a/src/Nancy.Serialization.JsonNet/JsonNetBodyDeserializer.cs +++ b/src/Nancy.Serialization.JsonNet/JsonNetBodyDeserializer.cs @@ -50,9 +50,36 @@ 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); - + + 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 +124,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 From d44f98927d04b0ac68aed1b708a2c611e4915cce Mon Sep 17 00:00:00 2001 From: Jonathan Channon Date: Fri, 31 Jan 2014 12:28:44 +0000 Subject: [PATCH 2/2] added check for collection type --- .../JsonNetBodyDeserializer.cs | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Nancy.Serialization.JsonNet/JsonNetBodyDeserializer.cs b/src/Nancy.Serialization.JsonNet/JsonNetBodyDeserializer.cs index bd1b5fb..da9429d 100644 --- a/src/Nancy.Serialization.JsonNet/JsonNetBodyDeserializer.cs +++ b/src/Nancy.Serialization.JsonNet/JsonNetBodyDeserializer.cs @@ -53,31 +53,34 @@ public object Deserialize(string contentType, Stream bodyStream, BindingContext var deserializedObject = this.serializer.Deserialize(new StreamReader(bodyStream), context.DestinationType); - 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) + 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)) + if (!IsDefaultValue(existingValue, property.PropertyType)) { - CopyPropertyValue(property, deserializedObject, context.Model); + existingInstance = true; + break; } } - return context.Model; + 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())