diff --git a/build/dependencies.props b/build/dependencies.props
index b32b5bbbc4..e879aaa8d1 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -9,7 +9,7 @@
3.0.0-alpha1-10549
2.0.9
2.1.3
- 2.2.0-preview2-26905-02
+ 2.2.0-preview3-26927-02
15.6.1
4.9.0
2.0.3
diff --git a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs
index a988afa300..6cb4d7450c 100644
--- a/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs
+++ b/src/Microsoft.AspNetCore.JsonPatch/Internal/ObjectVisitor.cs
@@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using System.Collections;
using Microsoft.AspNetCore.JsonPatch.Adapters;
using Newtonsoft.Json.Serialization;
@@ -56,6 +55,13 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
adapter = null;
return false;
}
+
+ // If we hit a null on an interior segment then we need to stop traversing.
+ if (next == null)
+ {
+ adapter = null;
+ return false;
+ }
target = next;
adapter = SelectAdapter(target);
diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs
index 669c6d7af4..4672d9c97b 100644
--- a/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs
+++ b/test/Microsoft.AspNetCore.JsonPatch.Test/IntegrationTests/SimpleObjectIntegrationTest.cs
@@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Dynamic;
+using Microsoft.AspNetCore.JsonPatch.Exceptions;
using Xunit;
namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests
@@ -124,5 +126,30 @@ namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests
Assert.Equal(newGuid, targetObject.GuidValue);
}
+ // https://github.com/aspnet/AspNetCore/issues/3634
+ [Fact]
+ public void Regression_AspNetCore3634()
+ {
+ // Assert
+ var document = new JsonPatchDocument();
+ document.Move("/Object", "/Object/goodbye");
+
+ dynamic @object = new ExpandoObject();
+ @object.hello = "world";
+
+ var target = new Regression_AspNetCore3634_Object();
+ target.Object = @object;
+
+ // Act
+ var ex = Assert.Throws(() => document.ApplyTo(target));
+
+ // Assert
+ Assert.Equal("For operation 'move', the target location specified by path '/Object/goodbye' was not found.", ex.Message);
+ }
+
+ private class Regression_AspNetCore3634_Object
+ {
+ public dynamic Object { get; set; }
+ }
}
}
diff --git a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs
index cb299cf0dc..44f6fc81ae 100644
--- a/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs
+++ b/test/Microsoft.AspNetCore.JsonPatch.Test/Internal/ObjectVisitorTest.cs
@@ -205,6 +205,22 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
Assert.IsType(adapter);
}
+ [Fact]
+ public void Visit_NullInteriorTarget_ReturnsFalse()
+ {
+ // Arrange
+ var visitor = new ObjectVisitor(new ParsedPath("/States/0"), new DefaultContractResolver());
+
+ // Act
+ object target = new Class1() { States = null, };
+ var visitStatus = visitor.TryVisit(ref target, out var adapter, out var message);
+
+ // Assert
+ Assert.False(visitStatus);
+ Assert.Null(adapter);
+ Assert.Null(message);
+ }
+
[Fact]
public void Visit_NullTarget_ReturnsNullAdapter()
{