diff --git a/aspnetcore-features/UrlEncodingAndDecoding/Tests/Tests.csproj b/aspnetcore-features/UrlEncodingAndDecoding/Tests/Tests.csproj
index c5ecdf5955..8226e5e78e 100644
--- a/aspnetcore-features/UrlEncodingAndDecoding/Tests/Tests.csproj
+++ b/aspnetcore-features/UrlEncodingAndDecoding/Tests/Tests.csproj
@@ -1,7 +1,7 @@
- net7.0
+ net10.0
enable
enable
@@ -10,10 +10,10 @@
-
-
-
-
+
+
+
+
diff --git a/aspnetcore-features/UrlEncodingAndDecoding/Tests/UrlEncodingDecodingUnitTest.cs b/aspnetcore-features/UrlEncodingAndDecoding/Tests/UrlEncodingDecodingUnitTest.cs
index 1003e561b8..ac6e1395e4 100644
--- a/aspnetcore-features/UrlEncodingAndDecoding/Tests/UrlEncodingDecodingUnitTest.cs
+++ b/aspnetcore-features/UrlEncodingAndDecoding/Tests/UrlEncodingDecodingUnitTest.cs
@@ -1,4 +1,5 @@
using System.Net;
+using System.Text.Encodings.Web;
using System.Web;
namespace Tests
@@ -22,7 +23,7 @@ public void GivenAUrl_WhenEncodingWithHttpUtility_ThenCharactersEncoded()
[DataRow(EncodedUrlLowerPlus)]
[DataRow(EncodedUrlUpperPercent)]
[DataRow(EncodedUrlUpperPlus)]
- [DataTestMethod]
+ [TestMethod]
public void GivenAUrl_WhenDecodingWithHttpUtility_ThenCharactersDecoded(string encodedUrl)
{
var decoded = HttpUtility.UrlDecode(encodedUrl);
@@ -41,7 +42,7 @@ public void GivenAUrl_WhenEncodingWithWebUtility_ThenCharactersEncoded()
[DataRow(EncodedUrlLowerPlus)]
[DataRow(EncodedUrlUpperPercent)]
[DataRow(EncodedUrlUpperPlus)]
- [DataTestMethod]
+ [TestMethod]
public void GivenAUrl_WhenDecodingWithWebUtility_ThenCharactersDecoded(string encodedUrl)
{
var decoded = WebUtility.UrlDecode(encodedUrl);
@@ -58,7 +59,7 @@ public void GivenAUrl_WhenEncodingWithUri_ThenCharactersEncoded()
}
[DataRow(EncodedUrlUpperPercent)]
- [DataTestMethod]
+ [TestMethod]
public void GivenAUrl_WhenDecodingWithUri_ThenCharactersDecoded(string encodedUrl)
{
var decoded = Uri.UnescapeDataString(encodedUrl);
@@ -68,12 +69,73 @@ public void GivenAUrl_WhenDecodingWithUri_ThenCharactersDecoded(string encodedUr
[DataRow(EncodedUrlLowerPlus)]
[DataRow(EncodedUrlUpperPlus)]
- [DataTestMethod]
+ [TestMethod]
public void GivenAUrl_WhenDecodingWithUri_ThenCharactersNotDecoded(string encodedUrl)
{
var decoded = Uri.UnescapeDataString(encodedUrl);
Assert.AreNotEqual(Url, decoded); //Uri.UnescapeDataString does not decode + character to space
}
+
+ [TestMethod]
+ public void GivenAUrl_WhenEncodingWithUrlEncoder_ThenCharactersEncoded()
+ {
+ var encoded = UrlEncoder.Default.Encode(Url);
+
+ Assert.AreEqual(EncodedUrlUpperPercent, encoded);
+ }
+
+ [TestMethod]
+ public void GivenAVeryLongString_WhenEscapingWithUri_ThenNoLengthLimitApplies()
+ {
+ var longValue = new string('a', 100_000) + " ";
+
+ var encoded = Uri.EscapeDataString(longValue);
+
+ Assert.AreEqual(100_003, encoded.Length);
+ }
+
+ [TestMethod]
+ public void GivenTheEncodeUriComponentSafeCharacters_WhenEscapingWithUri_ThenTheyAreEscaped()
+ {
+ var encoded = Uri.EscapeDataString("!'()*~");
+
+ Assert.AreEqual("%21%27%28%29%2A~", encoded);
+ }
+
+ [TestMethod]
+ public void GivenABarePath_WhenConstructingAUri_ThenTheOutcomeIsPlatformDependent()
+ {
+ if (OperatingSystem.IsWindows())
+ {
+ //A bare path is not an absolute URI on Windows and not a rooted local path either.
+ Assert.ThrowsExactly(() => new Uri("/foo"));
+ Assert.IsFalse(Uri.TryCreate("/foo", UriKind.Absolute, out _));
+ }
+ else
+ {
+ //On Unix a bare path IS a rooted local path, so it parses as an absolute file URI.
+ var uri = new Uri("/foo");
+
+ Assert.AreEqual("file", uri.Scheme);
+ Assert.AreEqual("file:///foo", uri.AbsoluteUri);
+ Assert.IsTrue(Uri.TryCreate("/foo", UriKind.Absolute, out _));
+ }
+
+ //The relative remedy works the same way on every platform.
+ Assert.IsTrue(Uri.TryCreate("/foo", UriKind.Relative, out _));
+ Assert.IsFalse(new Uri("/foo", UriKind.Relative).IsAbsoluteUri);
+ }
+
+ [TestMethod]
+ public void GivenAProtocolRelativeUrl_WhenConstructingAUri_ThenItParsesAsAFileUri()
+ {
+ //Same on Windows and on Unix: this does not throw, it becomes a file URI.
+ var uri = new Uri("//example.com");
+
+ Assert.AreEqual("file", uri.Scheme);
+ Assert.AreEqual("file://example.com/", uri.AbsoluteUri);
+ Assert.IsTrue(Uri.TryCreate("//example.com", UriKind.Absolute, out _));
+ }
}
}
\ No newline at end of file
diff --git a/aspnetcore-features/UrlEncodingAndDecoding/UrlEncodingAndDecoding/Program.cs b/aspnetcore-features/UrlEncodingAndDecoding/UrlEncodingAndDecoding/Program.cs
index 8fd07966e0..87b6fb2eb9 100644
--- a/aspnetcore-features/UrlEncodingAndDecoding/UrlEncodingAndDecoding/Program.cs
+++ b/aspnetcore-features/UrlEncodingAndDecoding/UrlEncodingAndDecoding/Program.cs
@@ -1,4 +1,5 @@
using System.Net;
+using System.Text.Encodings.Web;
using System.Web;
var url = @"http://example.com/resource?foo=bar with space#fragment";
@@ -12,10 +13,18 @@
var uriEncoded = Uri.EscapeDataString(url);
var uriDecoded = Uri.UnescapeDataString(uriEncoded);
+var urlEncoderEncoded = UrlEncoder.Default.Encode(url);
+
Console.WriteLine(httpUtilityEncoded);
Console.WriteLine(webUtilityEncoded);
Console.WriteLine(uriEncoded);
+Console.WriteLine(urlEncoderEncoded);
Console.WriteLine(httpUtilityDecoded);
Console.WriteLine(webUtilityDecoded);
-Console.WriteLine(uriDecoded);
\ No newline at end of file
+Console.WriteLine(uriDecoded);
+
+// In real code we encode a single value, not the address it goes into:
+var searchUrl = $"https://example.com/search?q={Uri.EscapeDataString("bar with space")}";
+
+Console.WriteLine(searchUrl);
\ No newline at end of file
diff --git a/aspnetcore-features/UrlEncodingAndDecoding/UrlEncodingAndDecoding/UrlEncodingAndDecoding.csproj b/aspnetcore-features/UrlEncodingAndDecoding/UrlEncodingAndDecoding/UrlEncodingAndDecoding.csproj
index f02677bf64..dfb40caafc 100644
--- a/aspnetcore-features/UrlEncodingAndDecoding/UrlEncodingAndDecoding/UrlEncodingAndDecoding.csproj
+++ b/aspnetcore-features/UrlEncodingAndDecoding/UrlEncodingAndDecoding/UrlEncodingAndDecoding.csproj
@@ -2,7 +2,7 @@
Exe
- net7.0
+ net10.0
enable
enable