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}" },