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()
{