From 2ca6a824682f758dca32f4bb94b678329dd9893c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrej=20=C4=8Ci=C5=BEm=C3=A1rik?= Date: Wed, 2 Nov 2022 17:29:29 +0100 Subject: [PATCH 1/3] Ignore query parameters with null values --- src/Framework/Framework/Routing/UrlHelper.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Framework/Framework/Routing/UrlHelper.cs b/src/Framework/Framework/Routing/UrlHelper.cs index 00fff757f9..2ea785e43d 100644 --- a/src/Framework/Framework/Routing/UrlHelper.cs +++ b/src/Framework/Framework/Routing/UrlHelper.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Text; using DotVVM.Framework.Utils; @@ -24,19 +25,19 @@ public static string BuildUrlSuffix(string? urlSuffix, object? query) case null: break; case IEnumerable> keyValueCollection: - foreach (var item in keyValueCollection) + foreach (var item in keyValueCollection.Where(i => i.Value != null)) { AppendQueryParam(ref resultSuffix, item.Key, item.Value); } break; case IEnumerable> keyValueCollection: - foreach (var item in keyValueCollection) + foreach (var item in keyValueCollection.Where(i => i.Value != null)) { AppendQueryParam(ref resultSuffix, item.Key, item.Value.ToString().NotNull()); } break; default: - foreach (var prop in query.GetType().GetProperties()) + foreach (var prop in query.GetType().GetProperties().Where(p => p.GetValue(query) != null)) { AppendQueryParam(ref resultSuffix, prop.Name, prop.GetValue(query)!.ToString().NotNull()); } From 1f3249a14fc36b4b9f233fc953c03d22ef9aacf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrej=20=C4=8Ci=C5=BEm=C3=A1rik?= Date: Wed, 2 Nov 2022 19:38:57 +0100 Subject: [PATCH 2/3] Fixed issue with query parameters with empty value --- src/Framework/Framework/Routing/UrlHelper.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Framework/Framework/Routing/UrlHelper.cs b/src/Framework/Framework/Routing/UrlHelper.cs index 2ea785e43d..f4a93a4982 100644 --- a/src/Framework/Framework/Routing/UrlHelper.cs +++ b/src/Framework/Framework/Routing/UrlHelper.cs @@ -48,7 +48,14 @@ public static string BuildUrlSuffix(string? urlSuffix, object? query) } private static string AppendQueryParam(ref string urlSuffix, string name, string value) - => urlSuffix += (urlSuffix.LastIndexOf('?') < 0 ? "?" : "&") + $"{Uri.EscapeDataString(name)}={Uri.EscapeDataString(value)}"; + { + urlSuffix += (urlSuffix.LastIndexOf('?') < 0 ? "?" : "&"); + var hasValue = value.Trim() != string.Empty; + + return (!hasValue) ? + urlSuffix += Uri.EscapeDataString(name) : + urlSuffix += $"{Uri.EscapeDataString(name)}={Uri.EscapeDataString(value)}"; + } /// /// Checks whether the URL is local. From 54b4aeb698c5776f587f58647d96d34cc4b9fc1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrej=20=C4=8Ci=C5=BEm=C3=A1rik?= Date: Wed, 2 Nov 2022 19:39:12 +0100 Subject: [PATCH 3/3] Added tests --- src/Tests/Routing/UrlHelperTests.cs | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/Tests/Routing/UrlHelperTests.cs b/src/Tests/Routing/UrlHelperTests.cs index e0a34768da..6d1384244d 100644 --- a/src/Tests/Routing/UrlHelperTests.cs +++ b/src/Tests/Routing/UrlHelperTests.cs @@ -31,5 +31,51 @@ public void UrlHelper_IsLocalUrl(string url, bool expectedResult) Assert.AreEqual(expectedResult, result); } + [TestMethod] + public void UrlHelper_BuildUrlSuffix_EnumerableStringString() + { + var suffix = "suffix"; + var query = new List>() + { + new KeyValuePair("key1", "value1"), + new KeyValuePair("key2", null!), + new KeyValuePair("key3", string.Empty), + new KeyValuePair("key4", "value4") + }; + var result = UrlHelper.BuildUrlSuffix(suffix, query); + Assert.AreEqual("suffix?key1=value1&key3&key4=value4", result); + } + + [TestMethod] + public void UrlHelper_BuildUrlSuffix_EnumerableStringObject() + { + var suffix = "suffix"; + var query = new List>() + { + new KeyValuePair("key1", "value1"), + new KeyValuePair("key2", null!), + new KeyValuePair("key3", string.Empty), + new KeyValuePair("key4", "value4") + }; + var result = UrlHelper.BuildUrlSuffix(suffix, query); + Assert.AreEqual("suffix?key1=value1&key3&key4=value4", result); + } + + [TestMethod] + public void UrlHelper_BuildUrlSuffix_Object() + { + var suffix = "suffix"; + var query = new TestUrlSuffixDescriptor(); + var result = UrlHelper.BuildUrlSuffix(suffix, query); + Assert.AreEqual("suffix?key1=value1&key3&key4=value4", result); + } + + private class TestUrlSuffixDescriptor + { + public string key1 { get; set; } = "value1"; + public object key2 { get; set; } = null; + public object key3 { get; set; } = string.Empty; + public string key4 { get; set; } = "value4"; + } } }