Skip to content

Commit

Permalink
Issue #567: Escape character , for example ('/') is not proper handle…
Browse files Browse the repository at this point in the history
…d at key or function in quoted string
  • Loading branch information
xuzhg committed Apr 21, 2022
1 parent 9b45501 commit 3c7e83f
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 1 deletion.
3 changes: 2 additions & 1 deletion sample/ODataRoutingSample/Controllers/PeopleController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class PeopleController : ControllerBase
new Person
{
FirstName = "Goods",
LastName = "Zhangg",
LastName = "Zha/ngg",
},
new Person
{
Expand All @@ -42,6 +42,7 @@ public IActionResult Get(CancellationToken token)
return Ok(_persons);
}

// People(FirstName='Goods',LastName='Zha%2Fngg')
[HttpGet]
[EnableQuery]
public IActionResult Get(string keyFirstName, string keyLastName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
Expand Down Expand Up @@ -172,6 +173,7 @@ public override bool TryTranslate(ODataTemplateTranslateContext context)
IEdmTypeReference edmType = keyProperty.Type;
string strValue = rawValue as string;
string newStrValue = context.GetParameterAliasOrSelf(strValue);
newStrValue = Uri.UnescapeDataString(newStrValue);
if (newStrValue != strValue)
{
updateValues[templateName] = newStrValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public static IList<OperationSegmentParameter> Match(ODataTemplateTranslateConte
{
string strValue = rawValue as string;
string newStrValue = context.GetParameterAliasOrSelf(strValue);
newStrValue = Uri.UnescapeDataString(newStrValue);
if (newStrValue != strValue)
{
updatedValues[parameterTemp] = newStrValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,5 +370,39 @@ public void TryTranslateFunctionSegmentTemplate_ReturnsODataFunctionSegment_With
Assert.Equal(42, e.Value);
});
}

[Fact]
public void TryTranslateFunctionSegmentTemplate_ReturnsODataFunctionSegment_UsingEscapedString()
{
// Arrange
var primitive = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.String, false);
EdmFunction function = new EdmFunction("NS", "MyFunction", primitive, true, null, false);
function.AddParameter("bindingParameter", primitive);
function.AddParameter("name", primitive);

FunctionSegmentTemplate template = new FunctionSegmentTemplate(function, null);
EdmModel edmModel = new EdmModel();
edmModel.AddElement(function);

RouteValueDictionary routeValue = new RouteValueDictionary(new { name = "'Ji%2FChange%23%20T'" });

ODataTemplateTranslateContext context = new ODataTemplateTranslateContext
{
RouteValues = routeValue,
Model = edmModel
};

// Act
bool ok = template.TryTranslate(context);

// Assert
Assert.True(ok);
ODataPathSegment actual = Assert.Single(context.Segments);
OperationSegment functionSegment = Assert.IsType<OperationSegment>(actual);
Assert.Same(function, functionSegment.Operations.First());
var parameter = Assert.Single(functionSegment.Parameters);
Assert.Equal("name", parameter.Name);
Assert.Equal("Ji/Change# T", parameter.Value.ToString());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,53 @@ public void TryTranslateKeySegmentTemplate_WorksWithKeyParametersAlias()
Assert.Equal(42, actualKeys.Value);
}

[Fact]
public void TryTranslateKeySegmentTemplate_WorksWithKeyValue_UsingEscapedString()
{
// Arrange
EdmModel model = new EdmModel();
EdmEntityType customerType = new EdmEntityType("NS", "Customer");
EdmStructuralProperty firstName = customerType.AddStructuralProperty("FirstName", EdmPrimitiveTypeKind.String);
EdmStructuralProperty lastName = customerType.AddStructuralProperty("LastName", EdmPrimitiveTypeKind.String);
customerType.AddKeys(firstName, lastName);
model.AddElement(customerType);
EdmEntityContainer container = new EdmEntityContainer("NS", "Default");
EdmEntitySet customers = container.AddEntitySet("Customers", customerType);
model.AddElement(container);
RouteValueDictionary routeValueDictionary = new RouteValueDictionary(new { First = "'Zhang'", Last = "'Gan%2Fnng%23%20T'" });
IDictionary<string, string> keys = new Dictionary<string, string>
{
{ "FirstName", "{first}" },
{ "LastName", "{last}" }
};
KeySegmentTemplate template = new KeySegmentTemplate(keys, customerType, customers);

ODataTemplateTranslateContext context = new ODataTemplateTranslateContext
{
RouteValues = routeValueDictionary,
Model = model
};

// Act
bool ok = template.TryTranslate(context);

// Assert
Assert.True(ok);
ODataPathSegment actual = Assert.Single(context.Segments);
KeySegment keySegment = Assert.IsType<KeySegment>(actual);
Assert.Collection(keySegment.Keys,
e =>
{
Assert.Equal("FirstName", e.Key);
Assert.Equal("Zhang", e.Value);
},
e =>
{
Assert.Equal("LastName", e.Key);
Assert.Equal("Gan/nng# T", e.Value);
});
}

[Fact]
public void CreateKeySegmentKeySegmentTemplate_ThrowsArgumentNull_EntityType()
{
Expand Down

0 comments on commit 3c7e83f

Please sign in to comment.