Implement new Remove op & fix value.GetTypê issue in Add op
This commit is contained in:
parent
bf7e0f141e
commit
054b46c1cc
|
|
@ -161,7 +161,7 @@ namespace Microsoft.AspNet.JsonPatch.Adapters
|
||||||
{
|
{
|
||||||
// get the actual type
|
// get the actual type
|
||||||
var propertyValue = container.GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent);
|
var propertyValue = container.GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent);
|
||||||
var typeOfPathProperty = value.GetType();
|
var typeOfPathProperty = propertyValue.GetType();
|
||||||
|
|
||||||
if (!IsNonStringArray(typeOfPathProperty))
|
if (!IsNonStringArray(typeOfPathProperty))
|
||||||
{
|
{
|
||||||
|
|
@ -447,101 +447,240 @@ namespace Microsoft.AspNet.JsonPatch.Adapters
|
||||||
Remove(operation.path, objectToApplyTo, operation);
|
Remove(operation.path, objectToApplyTo, operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Remove is used by various operations (eg: remove, move, ...), yet through different operations;
|
/// Remove is used by various operations (eg: remove, move, ...), yet through different operations;
|
||||||
/// This method allows code reuse yet reporting the correct operation on error
|
/// This method allows code reuse yet reporting the correct operation on error. The return value
|
||||||
|
/// contains the type of the item that has been removed (and a bool possibly signifying an error)
|
||||||
|
/// This can be used by other methods, like replace, to ensure that we can pass in the correctly
|
||||||
|
/// typed value to whatever method follows.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void Remove(
|
private RemovedPropertyTypeResult Remove(string path, object objectToApplyTo, Operation operationToReport)
|
||||||
[NotNull] string path,
|
|
||||||
[NotNull] object objectToApplyTo,
|
|
||||||
[NotNull] Operation operationToReport)
|
|
||||||
{
|
{
|
||||||
var removeFromList = false;
|
// get path result
|
||||||
var positionAsInteger = -1;
|
var pathResult = GetActualPropertyPath(
|
||||||
var actualPathToProperty = path;
|
path,
|
||||||
|
objectToApplyTo,
|
||||||
|
operationToReport);
|
||||||
|
|
||||||
if (path.EndsWith("/-"))
|
if (pathResult == null)
|
||||||
{
|
{
|
||||||
removeFromList = true;
|
return new RemovedPropertyTypeResult(null, true);
|
||||||
actualPathToProperty = path.Substring(0, path.Length - 2);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
positionAsInteger = GetNumericEnd(path);
|
|
||||||
|
|
||||||
if (positionAsInteger > -1)
|
var removeFromList = pathResult.ExecuteAtEnd;
|
||||||
|
var positionAsInteger = pathResult.NumericEnd;
|
||||||
|
var actualPathToProperty = pathResult.PathToProperty;
|
||||||
|
|
||||||
|
var treeAnalysisResult = new ObjectTreeAnalysisResult(
|
||||||
|
objectToApplyTo,
|
||||||
|
actualPathToProperty,
|
||||||
|
ContractResolver);
|
||||||
|
|
||||||
|
if (!treeAnalysisResult.IsValidPathForRemove)
|
||||||
|
{
|
||||||
|
LogError(new JsonPatchError(
|
||||||
|
objectToApplyTo,
|
||||||
|
operationToReport,
|
||||||
|
Resources.FormatPropertyCannotBeRemoved(path)));
|
||||||
|
return new RemovedPropertyTypeResult(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (treeAnalysisResult.UseDynamicLogic)
|
||||||
|
{
|
||||||
|
// if it's not an array, we can remove the property from
|
||||||
|
// the dictionary. If it's an array, we need to check the position first.
|
||||||
|
if (removeFromList || positionAsInteger > -1)
|
||||||
{
|
{
|
||||||
actualPathToProperty = path.Substring(0,
|
var propertyValue = treeAnalysisResult.Container
|
||||||
path.IndexOf('/' + positionAsInteger.ToString()));
|
.GetValueForCaseInsensitiveKey(treeAnalysisResult.PropertyPathInParent);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var patchProperty = FindPropertyAndParent(objectToApplyTo, actualPathToProperty);
|
// we cannot continue when the value is null, because to be able to
|
||||||
|
// continue we need to be able to check if the array is a non-string array
|
||||||
|
if (propertyValue == null)
|
||||||
|
{
|
||||||
|
LogError(new JsonPatchError(
|
||||||
|
objectToApplyTo,
|
||||||
|
operationToReport,
|
||||||
|
Resources.FormatCannotDeterminePropertyType(path)));
|
||||||
|
return new RemovedPropertyTypeResult(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
// does the target location exist?
|
var typeOfPathProperty = propertyValue.GetType();
|
||||||
if (!CheckIfPropertyExists(patchProperty, objectToApplyTo, operationToReport, path))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the property, and remove it - in this case, for DTO's, that means setting
|
if (!IsNonStringArray(typeOfPathProperty))
|
||||||
// it to null or its default value; in case of an array, remove at provided index
|
{
|
||||||
// or at the end.
|
LogError(new JsonPatchError(
|
||||||
if (removeFromList || positionAsInteger > -1)
|
objectToApplyTo,
|
||||||
{
|
operationToReport,
|
||||||
// what if it's an array but there's no position??
|
Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path)));
|
||||||
if (IsNonStringArray(patchProperty.Property.PropertyType))
|
return new RemovedPropertyTypeResult(null, true);
|
||||||
{
|
}
|
||||||
// now, get the generic type of the IList<> from Property type.
|
|
||||||
var genericTypeOfArray = GetIListType(patchProperty.Property.PropertyType);
|
|
||||||
|
|
||||||
// get value (it can be cast, we just checked that)
|
// now, get the generic type of the enumerable (we'll return this type)
|
||||||
var array = (IList)patchProperty.Property.ValueProvider.GetValue(patchProperty.Parent);
|
var genericTypeOfArray = GetIListType(typeOfPathProperty);
|
||||||
|
|
||||||
|
// get the array
|
||||||
|
var array = (IList)treeAnalysisResult.Container.GetValueForCaseInsensitiveKey(
|
||||||
|
treeAnalysisResult.PropertyPathInParent);
|
||||||
|
|
||||||
|
if (array.Count == 0)
|
||||||
|
{
|
||||||
|
// if the array is empty, we should throw an error
|
||||||
|
LogError(new JsonPatchError(
|
||||||
|
objectToApplyTo,
|
||||||
|
operationToReport,
|
||||||
|
Resources.FormatInvalidIndexForArrayProperty(
|
||||||
|
operationToReport.op,
|
||||||
|
path)));
|
||||||
|
return new RemovedPropertyTypeResult(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (removeFromList)
|
if (removeFromList)
|
||||||
{
|
{
|
||||||
array.RemoveAt(array.Count - 1);
|
array.RemoveAt(array.Count - 1);
|
||||||
|
treeAnalysisResult.Container.SetValueForCaseInsensitiveKey(
|
||||||
|
treeAnalysisResult.PropertyPathInParent, array);
|
||||||
|
|
||||||
|
// return the type of the value that has been removed.
|
||||||
|
return new RemovedPropertyTypeResult(genericTypeOfArray, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (positionAsInteger < array.Count)
|
if (positionAsInteger >= array.Count)
|
||||||
{
|
|
||||||
array.RemoveAt(positionAsInteger);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
LogError(new JsonPatchError(
|
LogError(new JsonPatchError(
|
||||||
objectToApplyTo,
|
objectToApplyTo,
|
||||||
operationToReport,
|
operationToReport,
|
||||||
Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path)));
|
Resources.FormatInvalidIndexForArrayProperty(
|
||||||
|
operationToReport.op,
|
||||||
return;
|
path)));
|
||||||
|
return new RemovedPropertyTypeResult(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
array.RemoveAt(positionAsInteger);
|
||||||
|
treeAnalysisResult.Container.SetValueForCaseInsensitiveKey(
|
||||||
|
treeAnalysisResult.PropertyPathInParent, array);
|
||||||
|
|
||||||
|
// return the type of the value that has been removed.
|
||||||
|
return new RemovedPropertyTypeResult(genericTypeOfArray, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogError(new JsonPatchError(
|
// get the property
|
||||||
objectToApplyTo,
|
var getResult = treeAnalysisResult.Container.GetValueForCaseInsensitiveKey(
|
||||||
operationToReport,
|
treeAnalysisResult.PropertyPathInParent);
|
||||||
Resources.FormatInvalidPathForArrayProperty(operationToReport.op, path)));
|
|
||||||
|
|
||||||
return;
|
// remove the property
|
||||||
|
treeAnalysisResult.Container.RemoveValueForCaseInsensitiveKey(
|
||||||
|
treeAnalysisResult.PropertyPathInParent);
|
||||||
|
|
||||||
|
// value is not null, we can determine the type
|
||||||
|
if (getResult != null)
|
||||||
|
{
|
||||||
|
var actualType = getResult.GetType();
|
||||||
|
return new RemovedPropertyTypeResult(actualType, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new RemovedPropertyTypeResult(null, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// setting the value to "null" will use the default value in case of value types, and
|
// not dynamic
|
||||||
// null in case of reference types
|
var patchProperty = treeAnalysisResult.JsonPatchProperty;
|
||||||
object value = null;
|
|
||||||
|
|
||||||
if (patchProperty.Property.PropertyType.GetTypeInfo().IsValueType
|
if (removeFromList || positionAsInteger > -1)
|
||||||
&& Nullable.GetUnderlyingType(patchProperty.Property.PropertyType) == null)
|
|
||||||
{
|
{
|
||||||
value = Activator.CreateInstance(patchProperty.Property.PropertyType);
|
if (!IsNonStringArray(patchProperty.Property.PropertyType))
|
||||||
}
|
{
|
||||||
|
LogError(new JsonPatchError(
|
||||||
|
objectToApplyTo,
|
||||||
|
operationToReport,
|
||||||
|
Resources.FormatInvalidIndexForArrayProperty(operationToReport.op, path)));
|
||||||
|
return new RemovedPropertyTypeResult(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
patchProperty.Property.ValueProvider.SetValue(patchProperty.Parent, value);
|
// now, get the generic type of the IList<> from Property type.
|
||||||
|
var genericTypeOfArray = GetIListType(patchProperty.Property.PropertyType);
|
||||||
|
|
||||||
|
if (!patchProperty.Property.Readable)
|
||||||
|
{
|
||||||
|
LogError(new JsonPatchError(
|
||||||
|
objectToApplyTo,
|
||||||
|
operationToReport,
|
||||||
|
Resources.FormatCannotReadProperty(path)));
|
||||||
|
return new RemovedPropertyTypeResult(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
var array = (IList)patchProperty.Property.ValueProvider
|
||||||
|
.GetValue(patchProperty.Parent);
|
||||||
|
|
||||||
|
if (array.Count == 0)
|
||||||
|
{
|
||||||
|
// if the array is empty, we should throw an error
|
||||||
|
LogError(new JsonPatchError(
|
||||||
|
objectToApplyTo,
|
||||||
|
operationToReport,
|
||||||
|
Resources.FormatInvalidIndexForArrayProperty(
|
||||||
|
operationToReport.op,
|
||||||
|
path)));
|
||||||
|
return new RemovedPropertyTypeResult(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeFromList)
|
||||||
|
{
|
||||||
|
array.RemoveAt(array.Count - 1);
|
||||||
|
|
||||||
|
// return the type of the value that has been removed
|
||||||
|
return new RemovedPropertyTypeResult(genericTypeOfArray, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (positionAsInteger >= array.Count)
|
||||||
|
{
|
||||||
|
LogError(new JsonPatchError(
|
||||||
|
objectToApplyTo,
|
||||||
|
operationToReport,
|
||||||
|
Resources.FormatInvalidIndexForArrayProperty(
|
||||||
|
operationToReport.op,
|
||||||
|
path)));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
array.RemoveAt(positionAsInteger);
|
||||||
|
|
||||||
|
// return the type of the value that has been removed
|
||||||
|
return new RemovedPropertyTypeResult(genericTypeOfArray, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!patchProperty.Property.Writable)
|
||||||
|
{
|
||||||
|
LogError(new JsonPatchError(
|
||||||
|
objectToApplyTo,
|
||||||
|
operationToReport,
|
||||||
|
Resources.FormatCannotUpdateProperty(path)));
|
||||||
|
return new RemovedPropertyTypeResult(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setting the value to "null" will use the default value in case of value types, and
|
||||||
|
// null in case of reference types
|
||||||
|
object value = null;
|
||||||
|
|
||||||
|
if (patchProperty.Property.PropertyType.GetTypeInfo().IsValueType
|
||||||
|
&& Nullable.GetUnderlyingType(patchProperty.Property.PropertyType) == null)
|
||||||
|
{
|
||||||
|
value = Activator.CreateInstance(patchProperty.Property.PropertyType);
|
||||||
|
}
|
||||||
|
|
||||||
|
patchProperty.Property.ValueProvider.SetValue(patchProperty.Parent, value);
|
||||||
|
return new RemovedPropertyTypeResult(patchProperty.Property.PropertyType, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.JsonPatch.Helpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Return value for Remove operation. The combination tells us what to do next (if this operation
|
||||||
|
/// is called from inside another operation, eg: Replace, Copy.
|
||||||
|
///
|
||||||
|
/// Possible combo:
|
||||||
|
/// - ActualType contains type: operation succesfully completed, can continue when called from inside
|
||||||
|
/// another operation
|
||||||
|
/// - ActualType null and HasError true: operation not completed succesfully, should not be allowed to continue
|
||||||
|
/// - ActualType null and HasError false: operation completed succesfully, but we should not be allowed to
|
||||||
|
/// continue when called from inside another method as we could not verify the type of the removed property.
|
||||||
|
/// This happens when the value of an item in an ExpandoObject dictionary is null.
|
||||||
|
/// </summary>
|
||||||
|
internal class RemovedPropertyTypeResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the removed property (value)
|
||||||
|
/// </summary>
|
||||||
|
public Type ActualType { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HasError: true when an error occurred, the operation didn't complete succesfully
|
||||||
|
/// </summary>
|
||||||
|
public bool HasError { get; set; }
|
||||||
|
|
||||||
|
public RemovedPropertyTypeResult(Type actualType, bool hasError)
|
||||||
|
{
|
||||||
|
ActualType = actualType;
|
||||||
|
HasError = hasError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,22 @@ namespace Microsoft.AspNet.JsonPatch
|
||||||
private static readonly ResourceManager _resourceManager
|
private static readonly ResourceManager _resourceManager
|
||||||
= new ResourceManager("Microsoft.AspNet.JsonPatch.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
= new ResourceManager("Microsoft.AspNet.JsonPatch.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the property at path '{0}' could not be determined.
|
||||||
|
/// </summary>
|
||||||
|
internal static string CannotDeterminePropertyType
|
||||||
|
{
|
||||||
|
get { return GetString("CannotDeterminePropertyType"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the property at path '{0}' could not be determined.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatCannotDeterminePropertyType(object p0)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("CannotDeterminePropertyType"), p0);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The property at '{0}' could not be read.
|
/// The property at '{0}' could not be read.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -42,6 +58,22 @@ namespace Microsoft.AspNet.JsonPatch
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("CannotUpdateProperty"), p0);
|
return string.Format(CultureInfo.CurrentCulture, GetString("CannotUpdateProperty"), p0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key '{0}' was not found.
|
||||||
|
/// </summary>
|
||||||
|
internal static string DictionaryKeyNotFound
|
||||||
|
{
|
||||||
|
get { return GetString("DictionaryKeyNotFound"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The key '{0}' was not found.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatDictionaryKeyNotFound(object p0)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("DictionaryKeyNotFound"), p0);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For operation '{0}' on array property at path '{1}', the index is larger than the array size.
|
/// For operation '{0}' on array property at path '{1}', the index is larger than the array size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -58,23 +90,6 @@ namespace Microsoft.AspNet.JsonPatch
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidIndexForArrayProperty"), p0, p1);
|
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidIndexForArrayProperty"), p0, p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// For operation '{0}' on array property at path '{1}', the index is negative.
|
|
||||||
/// </summary>
|
|
||||||
internal static string NegativeIndexForArrayProperty
|
|
||||||
{
|
|
||||||
get { return GetString("NegativeIndexForArrayProperty"); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// For operation '{0}' on array property at path '{1}', the index is negative.
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatNegativeIndexForArrayProperty(object p0, object p1)
|
|
||||||
{
|
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("NegativeIndexForArrayProperty"), p0, p1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The type '{0}' was malformed and could not be parsed.
|
/// The type '{0}' was malformed and could not be parsed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -139,6 +154,22 @@ namespace Microsoft.AspNet.JsonPatch
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForProperty"), p0, p1);
|
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidValueForProperty"), p0, p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For operation '{0}' on array property at path '{1}', the index is negative.
|
||||||
|
/// </summary>
|
||||||
|
internal static string NegativeIndexForArrayProperty
|
||||||
|
{
|
||||||
|
get { return GetString("NegativeIndexForArrayProperty"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For operation '{0}' on array property at path '{1}', the index is negative.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatNegativeIndexForArrayProperty(object p0, object p1)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, GetString("NegativeIndexForArrayProperty"), p0, p1);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// '{0}' must be of type '{1}'.
|
/// '{0}' must be of type '{1}'.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -203,23 +234,6 @@ namespace Microsoft.AspNet.JsonPatch
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("PropertyDoesNotExist"), p0);
|
return string.Format(CultureInfo.CurrentCulture, GetString("PropertyDoesNotExist"), p0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The key '{0}' was not found.
|
|
||||||
/// </summary>
|
|
||||||
internal static string DictionaryKeyNotFound
|
|
||||||
{
|
|
||||||
get { return GetString("DictionaryKeyNotFound"); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The key '{0}' was not found.
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatDictionaryKeyNotFound(object p0)
|
|
||||||
{
|
|
||||||
return string.Format(CultureInfo.CurrentCulture, GetString("DictionaryKeyNotFound"), p0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The test operation is not supported.
|
/// The test operation is not supported.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,9 @@
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<data name="CannotDeterminePropertyType" xml:space="preserve">
|
||||||
|
<value>The type of the property at path '{0}' could not be determined.</value>
|
||||||
|
</data>
|
||||||
<data name="CannotReadProperty" xml:space="preserve">
|
<data name="CannotReadProperty" xml:space="preserve">
|
||||||
<value>The property at '{0}' could not be read.</value>
|
<value>The property at '{0}' could not be read.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,569 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Dynamic;
|
||||||
|
using Microsoft.AspNet.JsonPatch.Exceptions;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||||
|
{
|
||||||
|
public class AddOperationTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void AddNewPropertyShouldFailIfRootIsNotAnExpandoObject()
|
||||||
|
{
|
||||||
|
dynamic doc = new
|
||||||
|
{
|
||||||
|
Test = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("NewInt", 1);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The property at path '/NewInt' could not be added.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddNewProperty()
|
||||||
|
{
|
||||||
|
dynamic obj = new ExpandoObject();
|
||||||
|
obj.Test = 1;
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("NewInt", 1);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(obj);
|
||||||
|
|
||||||
|
Assert.Equal(1, obj.NewInt);
|
||||||
|
Assert.Equal(1, obj.Test);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddNewPropertyToNestedAnonymousObjectShouldFail()
|
||||||
|
{
|
||||||
|
dynamic doc = new
|
||||||
|
{
|
||||||
|
Test = 1,
|
||||||
|
nested = new { }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("Nested/NewInt", 1);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The property at path '/Nested/NewInt' could not be added.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddNewPropertyToTypedObjectShouldFail()
|
||||||
|
{
|
||||||
|
dynamic doc = new
|
||||||
|
{
|
||||||
|
Test = 1,
|
||||||
|
nested = new NestedDTO()
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("Nested/NewInt", 1);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The property at path '/Nested/NewInt' could not be added.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddToExistingPropertyOnNestedObject()
|
||||||
|
{
|
||||||
|
dynamic doc = new
|
||||||
|
{
|
||||||
|
Test = 1,
|
||||||
|
nested = new NestedDTO()
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("Nested/StringProperty", "A");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal("A", doc.nested.StringProperty);
|
||||||
|
Assert.Equal(1, doc.Test);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddNewPropertyToExpandoOject()
|
||||||
|
{
|
||||||
|
dynamic doc = new
|
||||||
|
{
|
||||||
|
Test = 1,
|
||||||
|
nested = new ExpandoObject()
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("Nested/NewInt", 1);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(1, doc.nested.NewInt);
|
||||||
|
Assert.Equal(1, doc.Test);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddNewPropertyToExpandoOjectInTypedObject()
|
||||||
|
{
|
||||||
|
var doc = new NestedDTO()
|
||||||
|
{
|
||||||
|
DynamicProperty = new ExpandoObject()
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("DynamicProperty/NewInt", 1);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(1, doc.DynamicProperty.NewInt);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddNewPropertyToTypedObjectInExpandoObject()
|
||||||
|
{
|
||||||
|
dynamic dynamicProperty = new ExpandoObject();
|
||||||
|
dynamicProperty.StringProperty = "A";
|
||||||
|
|
||||||
|
var doc = new NestedDTO()
|
||||||
|
{
|
||||||
|
DynamicProperty = dynamicProperty
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("DynamicProperty/StringProperty", "B");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal("B", doc.DynamicProperty.StringProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddNewPropertyToAnonymousObjectShouldFail()
|
||||||
|
{
|
||||||
|
dynamic doc = new
|
||||||
|
{
|
||||||
|
Test = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
dynamic valueToAdd = new { IntValue = 1, StringValue = "test", GuidValue = Guid.NewGuid() };
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("ComplexProperty", valueToAdd);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The property at path '/ComplexProperty' could not be added.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddResultsReplaceShouldFailOnAnonymousDueToNoSetter()
|
||||||
|
{
|
||||||
|
var doc = new
|
||||||
|
{
|
||||||
|
StringProperty = "A"
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("StringProperty", "B");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The property at path '/StringProperty' could not be updated.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddResultsShouldReplace()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.StringProperty = "A";
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("StringProperty", "B");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal("B", doc.StringProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddResultsShouldReplaceInNested()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.InBetweenFirst = new ExpandoObject();
|
||||||
|
doc.InBetweenFirst.InBetweenSecond = new ExpandoObject();
|
||||||
|
doc.InBetweenFirst.InBetweenSecond.StringProperty = "A";
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("/InBetweenFirst/InBetweenSecond/StringProperty", "B");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal("B", doc.InBetweenFirst.InBetweenSecond.StringProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddResultsShouldReplaceInNestedInDynamic()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.Nested = new NestedDTO();
|
||||||
|
doc.Nested.DynamicProperty = new ExpandoObject();
|
||||||
|
doc.Nested.DynamicProperty.InBetweenFirst = new ExpandoObject();
|
||||||
|
doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond = new ExpandoObject();
|
||||||
|
doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty = "A";
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("/Nested/DynamicProperty/InBetweenFirst/InBetweenSecond/StringProperty", "B");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal("B", doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ShouldNotBeAbleToAddToNonExistingPropertyThatIsNotTheRoot()
|
||||||
|
{
|
||||||
|
//Adding to a Nonexistent Target
|
||||||
|
//
|
||||||
|
// An example target JSON document:
|
||||||
|
// { "foo": "bar" }
|
||||||
|
// A JSON Patch document:
|
||||||
|
// [
|
||||||
|
// { "op": "add", "path": "/baz/bat", "value": "qux" }
|
||||||
|
// ]
|
||||||
|
// This JSON Patch document, applied to the target JSON document above,
|
||||||
|
// would result in an error (therefore, it would not be applied),
|
||||||
|
// because the "add" operation's target location that references neither
|
||||||
|
// the root of the document, nor a member of an existing object, nor a
|
||||||
|
// member of an existing array.
|
||||||
|
|
||||||
|
var doc = new NestedDTO()
|
||||||
|
{
|
||||||
|
DynamicProperty = new ExpandoObject()
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("DynamicProperty/OtherProperty/IntProperty", 1);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The property at path '/DynamicProperty/OtherProperty/IntProperty' could not be added.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ShouldNotBeAbleToAddToNonExistingPropertyInNestedPropertyThatIsNotTheRoot()
|
||||||
|
{
|
||||||
|
//Adding to a Nonexistent Target
|
||||||
|
//
|
||||||
|
// An example target JSON document:
|
||||||
|
// { "foo": "bar" }
|
||||||
|
// A JSON Patch document:
|
||||||
|
// [
|
||||||
|
// { "op": "add", "path": "/baz/bat", "value": "qux" }
|
||||||
|
// ]
|
||||||
|
// This JSON Patch document, applied to the target JSON document above,
|
||||||
|
// would result in an error (therefore, it would not be applied),
|
||||||
|
// because the "add" operation's target location that references neither
|
||||||
|
// the root of the document, nor a member of an existing object, nor a
|
||||||
|
// member of an existing array.
|
||||||
|
|
||||||
|
var doc = new
|
||||||
|
{
|
||||||
|
Foo = "bar"
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("baz/bat", "qux");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The property at path '/baz/bat' could not be added.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ShouldReplacePropertyWithDifferentCase()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.StringProperty = "A";
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("stringproperty", "B");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal("B", doc.StringProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddToList()
|
||||||
|
{
|
||||||
|
var doc = new
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("IntegerList/0", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(new List<int>() { 4, 1, 2, 3 }, doc.IntegerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddToListNegativePosition()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.IntegerList = new List<int>() { 1, 2, 3 };
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("IntegerList/-1", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"For operation 'add' on array property at path '/IntegerList/-1', the index is negative.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ShouldAddToListWithDifferentCase()
|
||||||
|
{
|
||||||
|
var doc = new
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("integerlist/0", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(new List<int>() { 4, 1, 2, 3 }, doc.IntegerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddToListInvalidPositionTooLarge()
|
||||||
|
{
|
||||||
|
var doc = new
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("IntegerList/4", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"For operation 'add' on array property at path '/IntegerList/4', the index is larger than the array size.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddToListAtEndWithSerialization()
|
||||||
|
{
|
||||||
|
var doc = new
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("IntegerList/3", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(new List<int>() { 1, 2, 3, 4 }, doc.IntegerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddToListAtBeginning()
|
||||||
|
{
|
||||||
|
var doc = new
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("IntegerList/0", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(new List<int>() { 4, 1, 2, 3 }, doc.IntegerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddToListInvalidPositionTooSmall()
|
||||||
|
{
|
||||||
|
var doc = new
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("IntegerList/-1", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"For operation 'add' on array property at path '/IntegerList/-1', the index is negative.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddToListAppend()
|
||||||
|
{
|
||||||
|
var doc = new
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("IntegerList/-", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(new List<int>() { 1, 2, 3, 4 }, doc.IntegerList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.JsonPatch.Exceptions;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||||
|
{
|
||||||
|
public class AddTypedOperationTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void AddToListNegativePosition()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("IntegerList/-1", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"For operation 'add' on array property at path '/IntegerList/-1', the index is negative.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddToListInList()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTOWithNestedDTO()
|
||||||
|
{
|
||||||
|
ListOfSimpleDTO = new List<SimpleDTO>()
|
||||||
|
{
|
||||||
|
new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("ListOfSimpleDTO/0/IntegerList/0", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
Assert.Equal(new List<int>() { 4, 1, 2, 3 }, doc.ListOfSimpleDTO[0].IntegerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddToListInListInvalidPositionTooSmall()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTOWithNestedDTO()
|
||||||
|
{
|
||||||
|
ListOfSimpleDTO = new List<SimpleDTO>()
|
||||||
|
{
|
||||||
|
new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("ListOfSimpleDTO/-1/IntegerList/0", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The property at path '/ListOfSimpleDTO/-1/IntegerList/0' could not be added.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddToListInListInvalidPositionTooLarge()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTOWithNestedDTO()
|
||||||
|
{
|
||||||
|
ListOfSimpleDTO = new List<SimpleDTO>()
|
||||||
|
{
|
||||||
|
new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Add("ListOfSimpleDTO/20/IntegerList/0", 4);
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The property at path '/ListOfSimpleDTO/20/IntegerList/0' could not be added.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||||
|
{
|
||||||
|
public class NestedDTO
|
||||||
|
{
|
||||||
|
public string StringProperty { get; set; }
|
||||||
|
public dynamic DynamicProperty { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNet.JsonPatch.Exceptions;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||||
|
{
|
||||||
|
public class PatchDocumentTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void InvalidPathAtBeginningShouldThrowException()
|
||||||
|
{
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
patchDoc.Add("//NewInt", 1);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The provided string '//NewInt' is an invalid path.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void InvalidPathAtEndShouldThrowException()
|
||||||
|
{
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
patchDoc.Add("NewInt//", 1);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The provided string 'NewInt//' is an invalid path.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void InvalidPathWithDotShouldThrowException()
|
||||||
|
{
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
patchDoc.Add("NewInt.Test", 1);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The provided string 'NewInt.Test' is an invalid path.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NonGenericPatchDocToGenericMustSerialize()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTO()
|
||||||
|
{
|
||||||
|
StringProperty = "A",
|
||||||
|
AnotherStringProperty = "B"
|
||||||
|
};
|
||||||
|
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Copy("StringProperty", "AnotherStringProperty");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument<SimpleDTO>>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal("A", doc.AnotherStringProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GenericPatchDocToNonGenericMustSerialize()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTO()
|
||||||
|
{
|
||||||
|
StringProperty = "A",
|
||||||
|
AnotherStringProperty = "B"
|
||||||
|
};
|
||||||
|
|
||||||
|
JsonPatchDocument<SimpleDTO> patchDocTyped = new JsonPatchDocument<SimpleDTO>();
|
||||||
|
patchDocTyped.Copy<string>(o => o.StringProperty, o => o.AnotherStringProperty);
|
||||||
|
|
||||||
|
JsonPatchDocument patchDocUntyped = new JsonPatchDocument();
|
||||||
|
patchDocUntyped.Copy("StringProperty", "AnotherStringProperty");
|
||||||
|
|
||||||
|
var serializedTyped = JsonConvert.SerializeObject(patchDocTyped);
|
||||||
|
var serializedUntyped = JsonConvert.SerializeObject(patchDocUntyped);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serializedTyped);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal("A", doc.AnotherStringProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,302 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Dynamic;
|
||||||
|
using Microsoft.AspNet.JsonPatch.Exceptions;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||||
|
{
|
||||||
|
public class RemoveOperationTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void RemovePropertyShouldFailIfRootIsAnonymous()
|
||||||
|
{
|
||||||
|
dynamic doc = new
|
||||||
|
{
|
||||||
|
Test = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("Test");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The property at path '/Test' could not be updated.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemovePropertyShouldFailIfItDoesntExist()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.Test = 1;
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("NonExisting");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"The property at path '/NonExisting' could not be removed.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemovePropertyFromExpandoObject()
|
||||||
|
{
|
||||||
|
dynamic obj = new ExpandoObject();
|
||||||
|
obj.Test = 1;
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("Test");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(obj);
|
||||||
|
|
||||||
|
var cont = obj as IDictionary<string, object>;
|
||||||
|
object valueFromDictionary;
|
||||||
|
|
||||||
|
cont.TryGetValue("Test", out valueFromDictionary);
|
||||||
|
Assert.Null(valueFromDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemovePropertyFromExpandoObjectMixedCase()
|
||||||
|
{
|
||||||
|
dynamic obj = new ExpandoObject();
|
||||||
|
obj.Test = 1;
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("test");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(obj);
|
||||||
|
|
||||||
|
var cont = obj as IDictionary<string, object>;
|
||||||
|
object valueFromDictionary;
|
||||||
|
|
||||||
|
cont.TryGetValue("Test", out valueFromDictionary);
|
||||||
|
Assert.Null(valueFromDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemoveNestedPropertyFromExpandoObject()
|
||||||
|
{
|
||||||
|
dynamic obj = new ExpandoObject();
|
||||||
|
obj.Test = new ExpandoObject();
|
||||||
|
obj.Test.AnotherTest = "A";
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("Test");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(obj);
|
||||||
|
|
||||||
|
var cont = obj as IDictionary<string, object>;
|
||||||
|
object valueFromDictionary;
|
||||||
|
|
||||||
|
cont.TryGetValue("Test", out valueFromDictionary);
|
||||||
|
Assert.Null(valueFromDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemoveNestedPropertyFromExpandoObjectMixedCase()
|
||||||
|
{
|
||||||
|
dynamic obj = new ExpandoObject();
|
||||||
|
obj.Test = new ExpandoObject();
|
||||||
|
obj.Test.AnotherTest = "A";
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("test");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(obj);
|
||||||
|
var cont = obj as IDictionary<string, object>;
|
||||||
|
|
||||||
|
object valueFromDictionary;
|
||||||
|
cont.TryGetValue("Test", out valueFromDictionary);
|
||||||
|
Assert.Null(valueFromDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemove()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
StringProperty = "A"
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("SimpleDTO/StringProperty");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
Assert.Equal(null, doc.SimpleDTO.StringProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemoveMixedCase()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
StringProperty = "A"
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("Simpledto/stringProperty");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(null, doc.SimpleDTO.StringProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemoveFromList()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("SimpleDTO/IntegerList/2");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(new List<int>() { 1, 2 }, doc.SimpleDTO.IntegerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemoveFromListMixedCase()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("SimpleDTO/Integerlist/2");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(new List<int>() { 1, 2 }, doc.SimpleDTO.IntegerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemoveFromListInvalidPositionTooLarge()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("SimpleDTO/IntegerList/3");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"For operation 'remove' on array property at path '/SimpleDTO/IntegerList/3', the index is larger than the array size.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemoveFromListInvalidPositionTooSmall()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("SimpleDTO/IntegerList/-1");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"For operation 'remove' on array property at path '/SimpleDTO/IntegerList/-1', the index is negative.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemoveFromEndOfList()
|
||||||
|
{
|
||||||
|
dynamic doc = new ExpandoObject();
|
||||||
|
doc.SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("SimpleDTO/IntegerList/-");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
Assert.Equal(new List<int>() { 1, 2 }, doc.SimpleDTO.IntegerList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,244 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.JsonPatch.Exceptions;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||||
|
{
|
||||||
|
public class RemoveTypedOperationTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Remove()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTO()
|
||||||
|
{
|
||||||
|
StringProperty = "A"
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("StringProperty");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(null, doc.StringProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemoveFromList()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("IntegerList/2");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(new List<int>() { 1, 2 }, doc.IntegerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemoveFromListInvalidPositionTooLarge()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("IntegerList/3");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"For operation 'remove' on array property at path '/IntegerList/3', the index is larger than the array size.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemoveFromListInvalidPositionTooSmall()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("IntegerList/-1");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"For operation 'remove' on array property at path '/IntegerList/-1', the index is negative.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemoveFromEndOfList()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("IntegerList/-");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(new List<int>() { 1, 2 }, doc.IntegerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemove()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTOWithNestedDTO()
|
||||||
|
{
|
||||||
|
SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
StringProperty = "A"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("SimpleDTO/StringProperty");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(null, doc.SimpleDTO.StringProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemoveFromList()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTOWithNestedDTO()
|
||||||
|
{
|
||||||
|
SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("SimpleDTO/IntegerList/2");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(new List<int>() { 1, 2 }, doc.SimpleDTO.IntegerList);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemoveFromListInvalidPositionTooLarge()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTOWithNestedDTO()
|
||||||
|
{
|
||||||
|
SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("SimpleDTO/IntegerList/3");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"For operation 'remove' on array property at path '/SimpleDTO/IntegerList/3', the index is larger than the array size.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemoveFromListInvalidPositionTooSmall()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTOWithNestedDTO()
|
||||||
|
{
|
||||||
|
SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("SimpleDTO/IntegerList/-1");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
var exception = Assert.Throws<JsonPatchException>(() =>
|
||||||
|
{
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
});
|
||||||
|
Assert.Equal(
|
||||||
|
"For operation 'remove' on array property at path '/SimpleDTO/IntegerList/-1', the index is negative.",
|
||||||
|
exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NestedRemoveFromEndOfList()
|
||||||
|
{
|
||||||
|
var doc = new SimpleDTOWithNestedDTO()
|
||||||
|
{
|
||||||
|
SimpleDTO = new SimpleDTO()
|
||||||
|
{
|
||||||
|
IntegerList = new List<int>() { 1, 2, 3 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// create patch
|
||||||
|
JsonPatchDocument patchDoc = new JsonPatchDocument();
|
||||||
|
patchDoc.Remove("SimpleDTO/IntegerList/-");
|
||||||
|
|
||||||
|
var serialized = JsonConvert.SerializeObject(patchDoc);
|
||||||
|
var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);
|
||||||
|
|
||||||
|
deserialized.ApplyTo(doc);
|
||||||
|
|
||||||
|
Assert.Equal(new List<int>() { 1, 2 }, doc.SimpleDTO.IntegerList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||||
|
{
|
||||||
|
public class SimpleDTO
|
||||||
|
{
|
||||||
|
public List<SimpleDTO> SimpleDTOList { get; set; }
|
||||||
|
public List<int> IntegerList { get; set; }
|
||||||
|
public int IntegerValue { get; set; }
|
||||||
|
public string StringProperty { get; set; }
|
||||||
|
public string AnotherStringProperty { get; set; }
|
||||||
|
public decimal DecimalValue { get; set; }
|
||||||
|
public double DoubleValue { get; set; }
|
||||||
|
public float FloatValue { get; set; }
|
||||||
|
public Guid GuidValue { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.JsonPatch.Test.Dynamic
|
||||||
|
{
|
||||||
|
public class SimpleDTOWithNestedDTO
|
||||||
|
{
|
||||||
|
public int IntegerValue { get; set; }
|
||||||
|
public NestedDTO NestedDTO { get; set; }
|
||||||
|
public SimpleDTO SimpleDTO { get; set; }
|
||||||
|
public List<SimpleDTO> ListOfSimpleDTO { get; set; }
|
||||||
|
|
||||||
|
public SimpleDTOWithNestedDTO()
|
||||||
|
{
|
||||||
|
NestedDTO = new NestedDTO();
|
||||||
|
SimpleDTO = new SimpleDTO();
|
||||||
|
ListOfSimpleDTO = new List<SimpleDTO>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -778,7 +778,7 @@ namespace Microsoft.AspNet.JsonPatch.Test
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
var exception = Assert.Throws<JsonPatchException>(() => { patchDoc.ApplyTo(doc); });
|
var exception = Assert.Throws<JsonPatchException>(() => { patchDoc.ApplyTo(doc); });
|
||||||
Assert.Equal("Property does not exist at path '/simpledto/integerlist/-1'.", exception.Message);
|
Assert.Equal("For operation 'remove' on array property at path '/simpledto/integerlist/-1', the index is negative.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -805,7 +805,7 @@ namespace Microsoft.AspNet.JsonPatch.Test
|
||||||
{
|
{
|
||||||
deserialized.ApplyTo(doc);
|
deserialized.ApplyTo(doc);
|
||||||
});
|
});
|
||||||
Assert.Equal("Property does not exist at path '/simpledto/integerlist/-1'.", exception.Message);
|
Assert.Equal("For operation 'remove' on array property at path '/simpledto/integerlist/-1', the index is negative.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -830,7 +830,7 @@ namespace Microsoft.AspNet.JsonPatch.Test
|
||||||
patchDoc.ApplyTo(doc, logger.LogErrorMessage);
|
patchDoc.ApplyTo(doc, logger.LogErrorMessage);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("Property does not exist at path '/simpledto/integerlist/-1'.", logger.ErrorMessage);
|
Assert.Equal("For operation 'remove' on array property at path '/simpledto/integerlist/-1', the index is negative.", logger.ErrorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1319,11 +1319,10 @@ namespace Microsoft.AspNet.JsonPatch.Test
|
||||||
// create patch
|
// create patch
|
||||||
var patchDoc = new JsonPatchDocument<SimpleDTOWithNestedDTO>();
|
var patchDoc = new JsonPatchDocument<SimpleDTOWithNestedDTO>();
|
||||||
patchDoc.Replace<int>(o => o.SimpleDTO.IntegerList, 5, -1);
|
patchDoc.Replace<int>(o => o.SimpleDTO.IntegerList, 5, -1);
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
var exception = Assert.Throws<JsonPatchException>(() => { patchDoc.ApplyTo(doc); });
|
var exception = Assert.Throws<JsonPatchException>(() => { patchDoc.ApplyTo(doc); });
|
||||||
Assert.Equal(
|
Assert.Equal("For operation 'replace' on array property at path '/simpledto/integerlist/-1', the index is negative.",
|
||||||
"Property does not exist at path '/simpledto/integerlist/-1'.",
|
|
||||||
exception.Message);
|
exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1349,7 +1348,7 @@ namespace Microsoft.AspNet.JsonPatch.Test
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
var exception = Assert.Throws<JsonPatchException>(() => { deserialized.ApplyTo(doc); });
|
var exception = Assert.Throws<JsonPatchException>(() => { deserialized.ApplyTo(doc); });
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
"Property does not exist at path '/simpledto/integerlist/-1'.",
|
"For operation 'replace' on array property at path '/simpledto/integerlist/-1', the index is negative.",
|
||||||
exception.Message);
|
exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -577,7 +577,7 @@ namespace Microsoft.AspNet.JsonPatch.Test
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
var exception = Assert.Throws<JsonPatchException>(() => { patchDoc.ApplyTo(doc); });
|
var exception = Assert.Throws<JsonPatchException>(() => { patchDoc.ApplyTo(doc); });
|
||||||
Assert.Equal("Property does not exist at path '/integerlist/-1'.", exception.Message);
|
Assert.Equal("For operation 'remove' on array property at path '/integerlist/-1', the index is negative.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -598,7 +598,7 @@ namespace Microsoft.AspNet.JsonPatch.Test
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
var exception = Assert.Throws<JsonPatchException>(() => { deserialized.ApplyTo(doc); });
|
var exception = Assert.Throws<JsonPatchException>(() => { deserialized.ApplyTo(doc); });
|
||||||
Assert.Equal("Property does not exist at path '/integerlist/-1'.", exception.Message);
|
Assert.Equal("For operation 'remove' on array property at path '/integerlist/-1', the index is negative.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -621,7 +621,7 @@ namespace Microsoft.AspNet.JsonPatch.Test
|
||||||
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("Property does not exist at path '/integerlist/-1'.", logger.ErrorMessage);
|
Assert.Equal("For operation 'remove' on array property at path '/integerlist/-1', the index is negative.", logger.ErrorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1172,7 +1172,7 @@ namespace Microsoft.AspNet.JsonPatch.Test
|
||||||
{
|
{
|
||||||
patchDoc.ApplyTo(doc);
|
patchDoc.ApplyTo(doc);
|
||||||
});
|
});
|
||||||
Assert.Equal("Property does not exist at path '/integerlist/-1'.", exception.Message);
|
Assert.Equal("For operation 'replace' on array property at path '/integerlist/-1', the index is negative.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1196,7 +1196,7 @@ namespace Microsoft.AspNet.JsonPatch.Test
|
||||||
{
|
{
|
||||||
deserialized.ApplyTo(doc);
|
deserialized.ApplyTo(doc);
|
||||||
});
|
});
|
||||||
Assert.Equal("Property does not exist at path '/integerlist/-1'.", exception.Message);
|
Assert.Equal("For operation 'replace' on array property at path '/integerlist/-1', the index is negative.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue