diff --git a/src/Umbraco.Core/StringUdi.cs b/src/Umbraco.Core/StringUdi.cs index 7f1189677f..0f42f4b5f6 100644 --- a/src/Umbraco.Core/StringUdi.cs +++ b/src/Umbraco.Core/StringUdi.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core /// The entity type part of the udi. /// The string id part of the udi. public StringUdi(string entityType, string id) - : base(entityType, "umb://" + entityType + "/" + id) + : base(entityType, "umb://" + entityType + "/" + Uri.EscapeUriString(id)) { Id = id; } @@ -32,7 +32,7 @@ namespace Umbraco.Core public StringUdi(Uri uriValue) : base(uriValue) { - Id = uriValue.AbsolutePath.TrimStart('/'); + Id = Uri.UnescapeDataString(uriValue.AbsolutePath.TrimStart('/')); } /// diff --git a/src/Umbraco.Core/Udi.cs b/src/Umbraco.Core/Udi.cs index 9d67c6ccab..142bf025a9 100644 --- a/src/Umbraco.Core/Udi.cs +++ b/src/Umbraco.Core/Udi.cs @@ -101,7 +101,8 @@ namespace Umbraco.Core public override string ToString() { // UriValue is created in the ctor and is never null - return UriValue.ToString(); + // use AbsoluteUri here and not ToString else it's not encoded! + return UriValue.AbsoluteUri; } /// @@ -159,7 +160,7 @@ namespace Umbraco.Core } if (udiType == UdiType.StringUdi) { - udi = path == string.Empty ? GetRootUdi(uri.Host) : new StringUdi(uri.Host, path); + udi = path == string.Empty ? GetRootUdi(uri.Host) : new StringUdi(uri.Host, Uri.UnescapeDataString(path)); return true; } if (tryParse) return false; diff --git a/src/Umbraco.Tests/UdiTests.cs b/src/Umbraco.Tests/UdiTests.cs index 9b803d5fa3..6e7e4671a9 100644 --- a/src/Umbraco.Tests/UdiTests.cs +++ b/src/Umbraco.Tests/UdiTests.cs @@ -31,6 +31,34 @@ namespace Umbraco.Tests Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/test-id", udi.ToString()); } + [Test] + public void StringEncodingTest() + { + // absolute path is unescaped + var uri = new Uri("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test"); + Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/this is a test", uri.ToString()); + Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test", uri.AbsoluteUri); + Assert.AreEqual("/this%20is%20a%20test", uri.AbsolutePath); + + Assert.AreEqual("/this is a test", Uri.UnescapeDataString(uri.AbsolutePath)); + Assert.AreEqual("%2Fthis%20is%20a%20test", Uri.EscapeDataString("/this is a test")); + Assert.AreEqual("/this%20is%20a%20test", Uri.EscapeUriString("/this is a test")); + + var udi = Udi.Parse("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test"); + Assert.AreEqual(Constants.UdiEntityType.AnyString, udi.EntityType); + Assert.IsInstanceOf(udi); + var stringEntityId = udi as StringUdi; + Assert.IsNotNull(stringEntityId); + Assert.AreEqual("this is a test", stringEntityId.Id); + Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test", udi.ToString()); + + var udi2 = new StringUdi(Constants.UdiEntityType.AnyString, "this is a test"); + Assert.AreEqual(udi, udi2); + + var udi3 = new StringUdi(Constants.UdiEntityType.AnyString, "path to/this is a test.xyz"); + Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/path%20to/this%20is%20a%20test.xyz", udi3.ToString()); + } + [Test] public void GuidEntityCtorTest() {