Skip to content
This repository was archived by the owner on Apr 26, 2020. It is now read-only.

JsonSerializer to check for existing instances when BindTo used #6

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 66 additions & 1 deletion src/Nancy.Serialization.JsonNet.Tests/ModelBindingFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Stuff>();

//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<Stuff>();

//Then
Assert.Null(resultModel.LastName);
}
}
public class TestBootstrapper : ConfigurableBootstrapper
Expand Down Expand Up @@ -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)
{
Expand Down
41 changes: 39 additions & 2 deletions src/Nancy.Serialization.JsonNet/JsonNetBodyDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,39 @@ public bool CanDeserialize(string contentType, BindingContext context)
/// <returns>Model instance</returns>
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);
Expand Down Expand Up @@ -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;
}
}
}