From 2f78d1a8f3a4bb304ae87e7f8ed63cbff1c2c6db Mon Sep 17 00:00:00 2001 From: Ronald Barendse Date: Wed, 24 Jul 2024 14:28:19 +0200 Subject: [PATCH] Fix `UdiRange.Parse()` throwing `ArgumentException` for valid value (#16788) * Add test to assert UdiRange can round-trip all selectors * Fix parsing UdiRange without a selector --- src/Umbraco.Core/UdiRange.cs | 22 +++++++++++++------ .../Umbraco.Core/CoreThings/UdiTests.cs | 15 +++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Core/UdiRange.cs b/src/Umbraco.Core/UdiRange.cs index dd497e2f9e..b91b811b06 100644 --- a/src/Umbraco.Core/UdiRange.cs +++ b/src/Umbraco.Core/UdiRange.cs @@ -75,17 +75,25 @@ public class UdiRange public static bool operator !=(UdiRange range1, UdiRange range2) => !(range1 == range2); - public static UdiRange Parse(string s) + public static UdiRange Parse(string value) { - if (Uri.IsWellFormedUriString(s, UriKind.Absolute) == false - || Uri.TryCreate(s, UriKind.Absolute, out Uri? uri) == false) + if (Uri.TryCreate(value, UriKind.Absolute, out Uri? uri) is false || + uri.IsWellFormedOriginalString() is false) { - // if (tryParse) return false; - throw new FormatException(string.Format("String \"{0}\" is not a valid udi range.", s)); + throw new FormatException($"String \"{value}\" is not a valid UDI range."); } - Uri udiUri = uri.Query == string.Empty ? uri : new UriBuilder(uri) { Query = string.Empty }.Uri; - return new UdiRange(Udi.Create(udiUri), uri.Query.TrimStart(Constants.CharArrays.QuestionMark)); + // Remove selector from UDI + Uri udiUri = string.IsNullOrEmpty(uri.Query) + ? uri + : new UriBuilder(uri) { Query = string.Empty }.Uri; + + var udi = Udi.Create(udiUri); + + // Only specify selector if query string is not empty + return string.IsNullOrEmpty(uri.Query) + ? new UdiRange(udi) + : new UdiRange(udi, uri.Query.TrimStart(Constants.CharArrays.QuestionMark)); } public override string ToString() => _uriValue.ToString(); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/UdiTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/UdiTests.cs index cf89b6d13b..b7f9e4c4cd 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/UdiTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/CoreThings/UdiTests.cs @@ -201,6 +201,21 @@ public class UdiTests Assert.Throws(() => new UdiRange(guidUdi, "x")); } + [Test] + [TestCase(Constants.DeploySelector.This)] + [TestCase(Constants.DeploySelector.ThisAndChildren)] + [TestCase(Constants.DeploySelector.ThisAndDescendants)] + [TestCase(Constants.DeploySelector.ChildrenOfThis)] + [TestCase(Constants.DeploySelector.DescendantsOfThis)] + [TestCase(Constants.DeploySelector.EntitiesOfType)] + public void RangeParseTest(string selector) + { + var expected = new UdiRange(Udi.Create(Constants.UdiEntityType.AnyGuid, Guid.NewGuid()), selector); + var actual = UdiRange.Parse(expected.ToString()); + + Assert.AreEqual(expected, actual); + } + [Test] public void TryParseTest() {