Skip to content

Commit

Permalink
Aligning KeySegment encoding with Microsoft.OData.UriParser. Fixes OD…
Browse files Browse the repository at this point in the history
  • Loading branch information
uffelauesen committed Jan 13, 2025
1 parent 5da66a5 commit 8ba6561
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 5 deletions.
17 changes: 14 additions & 3 deletions src/Microsoft.AspNetCore.OData/Routing/ODataPathSegmentHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ internal static string ConvertKeysToString(IEnumerable<KeyValuePair<string, obje
return string.Join(
",",
keyValuePairs.Select(keyValuePair =>
TranslateNode(keyValuePair.Value).EscapeBackSlashUriString()).ToArray());
TranslateNode(keyValuePair.Value)).ToArray());
}
}

Expand All @@ -328,7 +328,7 @@ internal static string ConvertKeysToString(IEnumerable<KeyValuePair<string, obje
keyValuePairs.Select(keyValuePair =>
(keyValuePair.Key +
"=" +
TranslateNode(keyValuePair.Value).EscapeBackSlashUriString())).ToArray());
TranslateNode(keyValuePair.Value))).ToArray());
}

internal static string TranslateNode(object node)
Expand Down Expand Up @@ -364,6 +364,17 @@ internal static string TranslateNode(object node)
return parameterAliasNode.Alias;
}

return ODataUriUtils.ConvertToUriLiteral(node, ODataVersion.V4);
string uriLiteral = ODataUriUtils.ConvertToUriLiteral(node, ODataVersion.V4);

if (node is string && uriLiteral.StartsWith('\'') && uriLiteral.EndsWith('\''))
{
// ODataUriUtils.ConvertToUriLiteral does not encoded the value.
// The result for keys to use on the wire (like odata.id, odata.readlink, odata.editLink and Location header) should be encoded,
// but still wrapped in unencoded '
// This to allign with how ODLs UriParser construct OData ID Uri's
return '\'' + Uri.EscapeDataString(uriLiteral.Substring(1, uriLiteral.Length - 2)) + '\'';
}

return uriLiteral;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -402,14 +402,60 @@ public void ConvertKeysToString_ConvertKeysValues_ShouldEscapeUriString()
IEnumerable<KeyValuePair<string, object>> keys = new KeyValuePair<string, object>[]
{
KeyValuePair.Create("Id", (object)4),
KeyValuePair.Create("Name", (object)"2425/&Foo")
KeyValuePair.Create("Name", (object)"'24 25/&Foo,?\"")
};

// Act
string actual = ODataPathSegmentHandler.ConvertKeysToString(keys, entityType);

// Assert
Assert.Equal("Id=4,Name='2425%2F&Foo'", actual);
Assert.Equal("Id=4,Name='%27%2724%2025%2F%26Foo%2C%3F%22'", actual);
}

[Fact]
public void ConvertKeysToString_ConvertKeysValues_ProducesSameEncodingAsODL()
{
// Arrange
EdmEntityType entityType = new EdmEntityType("NS", "Entity");
IEdmStructuralProperty key1 = entityType.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false));
IEdmStructuralProperty key2 = entityType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(false));

entityType.AddKeys(key1, key2);
IEnumerable<KeyValuePair<string, object>> keys = new KeyValuePair<string, object>[]
{
KeyValuePair.Create("Id", (object)4),
KeyValuePair.Create("Name", (object)"'24 25/&Foo,?\"")
};

// Act
string actual = '(' + ODataPathSegmentHandler.ConvertKeysToString(keys, entityType) + ')';

ODataPath path = new ODataPath(new KeySegment(keys, entityType, null));

// Assert
Assert.Equal(path.ToResourcePathString(ODataUrlKeyDelimiter.Parentheses), actual);
}

[Fact]
public void ConvertKeysToString_ConvertKeysValues_ShouldNotQuoteNull()
{
// Arrange
EdmEntityType entityType = new EdmEntityType("NS", "Entity");
IEdmStructuralProperty key1 = entityType.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false));
IEdmStructuralProperty key2 = entityType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true));

entityType.AddKeys(key1, key2);
IEnumerable<KeyValuePair<string, object>> keys = new KeyValuePair<string, object>[]
{
KeyValuePair.Create("Id", (object)4),
KeyValuePair.Create("Name", (object)null)
};

// Act
string actual = ODataPathSegmentHandler.ConvertKeysToString(keys, entityType);

// Assert
Assert.Equal("Id=4,Name=null", actual);
}

[Fact]
Expand Down

0 comments on commit 8ba6561

Please sign in to comment.