diff --git a/sample/ODataAlternateKeySample/Models/AlternateKeyRepositoryInMemory.cs b/sample/ODataAlternateKeySample/Models/AlternateKeyRepositoryInMemory.cs index 44fbf01ee..d2d6a686c 100644 --- a/sample/ODataAlternateKeySample/Models/AlternateKeyRepositoryInMemory.cs +++ b/sample/ODataAlternateKeySample/Models/AlternateKeyRepositoryInMemory.cs @@ -17,11 +17,11 @@ static AlternateKeyRepositoryInMemory() { // Customers var names = new[] { "Tom", "Jerry", "Mike", "Ben", "Sam", "Peter" }; - _customers = Enumerable.Range(1, 5).Select(e => new Customer + _customers = Enumerable.Range(1, 5).Select((e, i) => new Customer { Id = e, Name = names[e - 1], - SSN = "SSN-" + e + "-" + (100 + e), + SSN = i % 2 == 0 ? "SSN-" + e + "-" + (100 + e) : "SSN-%25-" + e + "-" + (100 + e), Titles = new string[] { "abc", null, "efg" } }).ToList(); diff --git a/src/Microsoft.AspNetCore.OData/Common/StringExtensions.cs b/src/Microsoft.AspNetCore.OData/Common/StringExtensions.cs index fb4be3ae5..bca3db0b2 100644 --- a/src/Microsoft.AspNetCore.OData/Common/StringExtensions.cs +++ b/src/Microsoft.AspNetCore.OData/Common/StringExtensions.cs @@ -11,6 +11,22 @@ namespace Microsoft.AspNetCore.OData.Common { internal static class StringExtensions { + /// + /// Unescape Uri string for %2F + /// See details at: https://github.com/dotnet/aspnetcore/issues/14170#issuecomment-533342396 + /// + /// The Uri string. + /// Unescaped back slash Uri string. + public static string UnescapeBackSlashUriString(this string uriString) + { + if (uriString == null) + { + return null; + } + + return uriString.Replace("%2f", "%2F").Replace("%2F", "/"); + } + /// /// Normalize the http method. /// diff --git a/src/Microsoft.AspNetCore.OData/Microsoft.AspNetCore.OData.xml b/src/Microsoft.AspNetCore.OData/Microsoft.AspNetCore.OData.xml index 069a24b55..2e2b82c65 100644 --- a/src/Microsoft.AspNetCore.OData/Microsoft.AspNetCore.OData.xml +++ b/src/Microsoft.AspNetCore.OData/Microsoft.AspNetCore.OData.xml @@ -1047,6 +1047,14 @@ a fast getter. This method is more memory efficient than a dynamically compiled lambda, and about the same speed. + + + Unescape Uri string for %2F + See details at: https://github.com/dotnet/aspnetcore/issues/14170#issuecomment-533342396 + + The Uri string. + Unescaped back slash Uri string. + Normalize the http method. diff --git a/src/Microsoft.AspNetCore.OData/Routing/Template/KeySegmentTemplate.cs b/src/Microsoft.AspNetCore.OData/Routing/Template/KeySegmentTemplate.cs index b139b7cf5..a390de3ac 100644 --- a/src/Microsoft.AspNetCore.OData/Routing/Template/KeySegmentTemplate.cs +++ b/src/Microsoft.AspNetCore.OData/Routing/Template/KeySegmentTemplate.cs @@ -172,8 +172,11 @@ public override bool TryTranslate(ODataTemplateTranslateContext context) IEdmTypeReference edmType = keyProperty.Type; string strValue = rawValue as string; + string newStrValue = context.GetParameterAliasOrSelf(strValue); - newStrValue = Uri.UnescapeDataString(newStrValue); + + // rawValue from Request route values, it's unescaped except the back-slash. + newStrValue = newStrValue.UnescapeBackSlashUriString(); if (newStrValue != strValue) { updateValues[templateName] = newStrValue; diff --git a/test/Microsoft.AspNetCore.OData.Tests/Routing/Template/KeySegmentTemplateTests.cs b/test/Microsoft.AspNetCore.OData.Tests/Routing/Template/KeySegmentTemplateTests.cs index d79a635fe..ab6fb288c 100644 --- a/test/Microsoft.AspNetCore.OData.Tests/Routing/Template/KeySegmentTemplateTests.cs +++ b/test/Microsoft.AspNetCore.OData.Tests/Routing/Template/KeySegmentTemplateTests.cs @@ -497,7 +497,7 @@ public void TryTranslateKeySegmentTemplate_WorksWithKeyValue_UsingEscapedString( 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'" }); + RouteValueDictionary routeValueDictionary = new RouteValueDictionary(new { First = "'Zhang'", Last = "'Gan%2Fnng# T'" }); IDictionary keys = new Dictionary { { "FirstName", "{first}" },