diff --git a/src/Components/WebView/WebView/src/PathString.cs b/src/Components/WebView/WebView/src/PathString.cs
deleted file mode 100644
index b8bb145e5f6ec3ae3cade0812d70dd4f9a4df390..0000000000000000000000000000000000000000
--- a/src/Components/WebView/WebView/src/PathString.cs
+++ /dev/null
@@ -1,482 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-// NOTE: This file is copied from src/Http/Http.Abstractions/src/PathString.cs
-// and made internal with a namespace change.
-// It can't be referenced directly from the StaticFiles package because that would cause this package to require
-// Microsoft.AspNetCore.App, thus preventing it from being used anywhere ASP.NET Core isn't supported (such as
-// various platforms that .NET MAUI runs on, such as Android and iOS).
-
-using System;
-using System.ComponentModel;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using System.Text;
-
-namespace Microsoft.AspNetCore.Components.WebView
-{
-    /// <summary>
-    /// Provides correct escaping for Path and PathBase values when needed to reconstruct a request or redirect URI string
-    /// </summary>
-    [TypeConverter(typeof(PathStringConverter))]
-    internal readonly struct PathString : IEquatable<PathString>
-    {
-        /// <summary>
-        /// Represents the empty path. This field is read-only.
-        /// </summary>
-        public static readonly PathString Empty = new(string.Empty);
-
-        /// <summary>
-        /// Initialize the path string with a given value. This value must be in unescaped format. Use
-        /// PathString.FromUriComponent(value) if you have a path value which is in an escaped format.
-        /// </summary>
-        /// <param name="value">The unescaped path to be assigned to the Value property.</param>
-        public PathString(string? value)
-        {
-            if (!string.IsNullOrEmpty(value) && value[0] != '/')
-            {
-                throw new ArgumentException(Resources.FormatException_PathMustStartWithSlash(nameof(value)), nameof(value));
-            }
-            Value = value;
-        }
-
-        /// <summary>
-        /// The unescaped path value
-        /// </summary>
-        public string? Value { get; }
-
-        /// <summary>
-        /// True if the path is not empty
-        /// </summary>
-        [MemberNotNullWhen(true, nameof(Value))]
-        public bool HasValue
-        {
-            get { return !string.IsNullOrEmpty(Value); }
-        }
-
-        /// <summary>
-        /// Provides the path string escaped in a way which is correct for combining into the URI representation.
-        /// </summary>
-        /// <returns>The escaped path value</returns>
-        public override string ToString()
-        {
-            return ToUriComponent();
-        }
-
-        /// <summary>
-        /// Provides the path string escaped in a way which is correct for combining into the URI representation.
-        /// </summary>
-        /// <returns>The escaped path value</returns>
-        public string ToUriComponent()
-        {
-            if (!HasValue)
-            {
-                return string.Empty;
-            }
-
-            var value = Value;
-            var i = 0;
-            for (; i < value.Length; i++)
-            {
-                if (!PathStringHelper.IsValidPathChar(value[i]) || PathStringHelper.IsPercentEncodedChar(value, i))
-                {
-                    break;
-                }
-            }
-
-            if (i < value.Length)
-            {
-                return ToEscapedUriComponent(value, i);
-            }
-
-            return value;
-        }
-
-        private static string ToEscapedUriComponent(string value, int i)
-        {
-            StringBuilder? buffer = null;
-
-            var start = 0;
-            var count = i;
-            var requiresEscaping = false;
-
-            while (i < value.Length)
-            {
-                var isPercentEncodedChar = PathStringHelper.IsPercentEncodedChar(value, i);
-                if (PathStringHelper.IsValidPathChar(value[i]) || isPercentEncodedChar)
-                {
-                    if (requiresEscaping)
-                    {
-                        // the current segment requires escape
-                        buffer ??= new StringBuilder(value.Length * 3);
-                        buffer.Append(Uri.EscapeDataString(value.Substring(start, count)));
-
-                        requiresEscaping = false;
-                        start = i;
-                        count = 0;
-                    }
-
-                    if (isPercentEncodedChar)
-                    {
-                        count += 3;
-                        i += 3;
-                    }
-                    else
-                    {
-                        count++;
-                        i++;
-                    }
-                }
-                else
-                {
-                    if (!requiresEscaping)
-                    {
-                        // the current segment doesn't require escape
-                        buffer ??= new StringBuilder(value.Length * 3);
-                        buffer.Append(value, start, count);
-
-                        requiresEscaping = true;
-                        start = i;
-                        count = 0;
-                    }
-
-                    count++;
-                    i++;
-                }
-            }
-
-            if (count == value.Length && !requiresEscaping)
-            {
-                return value;
-            }
-            else
-            {
-                if (count > 0)
-                {
-                    buffer ??= new StringBuilder(value.Length * 3);
-
-                    if (requiresEscaping)
-                    {
-                        buffer.Append(Uri.EscapeDataString(value.Substring(start, count)));
-                    }
-                    else
-                    {
-                        buffer.Append(value, start, count);
-                    }
-                }
-
-                return buffer?.ToString() ?? string.Empty;
-            }
-        }
-
-        /// <summary>
-        /// Returns an PathString given the path as it is escaped in the URI format. The string MUST NOT contain any
-        /// value that is not a path.
-        /// </summary>
-        /// <param name="uriComponent">The escaped path as it appears in the URI format.</param>
-        /// <returns>The resulting PathString</returns>
-        public static PathString FromUriComponent(string uriComponent)
-        {
-            // REVIEW: what is the exactly correct thing to do?
-            return new PathString(Uri.UnescapeDataString(uriComponent));
-        }
-
-        /// <summary>
-        /// Returns an PathString given the path as from a Uri object. Relative Uri objects are not supported.
-        /// </summary>
-        /// <param name="uri">The Uri object</param>
-        /// <returns>The resulting PathString</returns>
-        public static PathString FromUriComponent(Uri uri)
-        {
-            if (uri == null)
-            {
-                throw new ArgumentNullException(nameof(uri));
-            }
-
-            // REVIEW: what is the exactly correct thing to do?
-            return new PathString("/" + uri.GetComponents(UriComponents.Path, UriFormat.Unescaped));
-        }
-
-        /// <summary>
-        /// Determines whether the beginning of this <see cref="PathString"/> instance matches the specified <see cref="PathString"/>.
-        /// </summary>
-        /// <param name="other">The <see cref="PathString"/> to compare.</param>
-        /// <returns>true if value matches the beginning of this string; otherwise, false.</returns>
-        public bool StartsWithSegments(PathString other)
-        {
-            return StartsWithSegments(other, StringComparison.OrdinalIgnoreCase);
-        }
-
-        /// <summary>
-        /// Determines whether the beginning of this <see cref="PathString"/> instance matches the specified <see cref="PathString"/> when compared
-        /// using the specified comparison option.
-        /// </summary>
-        /// <param name="other">The <see cref="PathString"/> to compare.</param>
-        /// <param name="comparisonType">One of the enumeration values that determines how this <see cref="PathString"/> and value are compared.</param>
-        /// <returns>true if value matches the beginning of this string; otherwise, false.</returns>
-        public bool StartsWithSegments(PathString other, StringComparison comparisonType)
-        {
-            var value1 = Value ?? string.Empty;
-            var value2 = other.Value ?? string.Empty;
-            if (value1.StartsWith(value2, comparisonType))
-            {
-                return value1.Length == value2.Length || value1[value2.Length] == '/';
-            }
-            return false;
-        }
-
-        /// <summary>
-        /// Determines whether the beginning of this <see cref="PathString"/> instance matches the specified <see cref="PathString"/> and returns
-        /// the remaining segments.
-        /// </summary>
-        /// <param name="other">The <see cref="PathString"/> to compare.</param>
-        /// <param name="remaining">The remaining segments after the match.</param>
-        /// <returns>true if value matches the beginning of this string; otherwise, false.</returns>
-        public bool StartsWithSegments(PathString other, out PathString remaining)
-        {
-            return StartsWithSegments(other, StringComparison.OrdinalIgnoreCase, out remaining);
-        }
-
-        /// <summary>
-        /// Determines whether the beginning of this <see cref="PathString"/> instance matches the specified <see cref="PathString"/> when compared
-        /// using the specified comparison option and returns the remaining segments.
-        /// </summary>
-        /// <param name="other">The <see cref="PathString"/> to compare.</param>
-        /// <param name="comparisonType">One of the enumeration values that determines how this <see cref="PathString"/> and value are compared.</param>
-        /// <param name="remaining">The remaining segments after the match.</param>
-        /// <returns>true if value matches the beginning of this string; otherwise, false.</returns>
-        public bool StartsWithSegments(PathString other, StringComparison comparisonType, out PathString remaining)
-        {
-            var value1 = Value ?? string.Empty;
-            var value2 = other.Value ?? string.Empty;
-            if (value1.StartsWith(value2, comparisonType))
-            {
-                if (value1.Length == value2.Length || value1[value2.Length] == '/')
-                {
-                    remaining = new PathString(value1[value2.Length..]);
-                    return true;
-                }
-            }
-            remaining = Empty;
-            return false;
-        }
-
-        /// <summary>
-        /// Determines whether the beginning of this <see cref="PathString"/> instance matches the specified <see cref="PathString"/> and returns
-        /// the matched and remaining segments.
-        /// </summary>
-        /// <param name="other">The <see cref="PathString"/> to compare.</param>
-        /// <param name="matched">The matched segments with the original casing in the source value.</param>
-        /// <param name="remaining">The remaining segments after the match.</param>
-        /// <returns>true if value matches the beginning of this string; otherwise, false.</returns>
-        public bool StartsWithSegments(PathString other, out PathString matched, out PathString remaining)
-        {
-            return StartsWithSegments(other, StringComparison.OrdinalIgnoreCase, out matched, out remaining);
-        }
-
-        /// <summary>
-        /// Determines whether the beginning of this <see cref="PathString"/> instance matches the specified <see cref="PathString"/> when compared
-        /// using the specified comparison option and returns the matched and remaining segments.
-        /// </summary>
-        /// <param name="other">The <see cref="PathString"/> to compare.</param>
-        /// <param name="comparisonType">One of the enumeration values that determines how this <see cref="PathString"/> and value are compared.</param>
-        /// <param name="matched">The matched segments with the original casing in the source value.</param>
-        /// <param name="remaining">The remaining segments after the match.</param>
-        /// <returns>true if value matches the beginning of this string; otherwise, false.</returns>
-        public bool StartsWithSegments(PathString other, StringComparison comparisonType, out PathString matched, out PathString remaining)
-        {
-            var value1 = Value ?? string.Empty;
-            var value2 = other.Value ?? string.Empty;
-            if (value1.StartsWith(value2, comparisonType))
-            {
-                if (value1.Length == value2.Length || value1[value2.Length] == '/')
-                {
-                    matched = new PathString(value1.Substring(0, value2.Length));
-                    remaining = new PathString(value1[value2.Length..]);
-                    return true;
-                }
-            }
-            remaining = Empty;
-            matched = Empty;
-            return false;
-        }
-
-        /// <summary>
-        /// Adds two PathString instances into a combined PathString value.
-        /// </summary>
-        /// <returns>The combined PathString value</returns>
-        public PathString Add(PathString other)
-        {
-            if (HasValue &&
-                other.HasValue &&
-                Value[^1] == '/')
-            {
-                // If the path string has a trailing slash and the other string has a leading slash, we need
-                // to trim one of them.
-                var combined = string.Concat(Value.AsSpan(), other.Value.AsSpan(1));
-                return new PathString(combined);
-            }
-
-            return new PathString(Value + other.Value);
-        }
-
-        /// <summary>
-        /// Combines a PathString and QueryString into the joined URI formatted string value.
-        /// </summary>
-        /// <returns>The joined URI formatted string value</returns>
-        public string Add(QueryString other)
-        {
-            return ToUriComponent() + other.ToUriComponent();
-        }
-
-        /// <summary>
-        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.
-        /// </summary>
-        /// <param name="other">The second PathString for comparison.</param>
-        /// <returns>True if both PathString values are equal</returns>
-        public bool Equals(PathString other)
-        {
-            return Equals(other, StringComparison.OrdinalIgnoreCase);
-        }
-
-        /// <summary>
-        /// Compares this PathString value to another value using a specific StringComparison type
-        /// </summary>
-        /// <param name="other">The second PathString for comparison</param>
-        /// <param name="comparisonType">The StringComparison type to use</param>
-        /// <returns>True if both PathString values are equal</returns>
-        public bool Equals(PathString other, StringComparison comparisonType)
-        {
-            if (!HasValue && !other.HasValue)
-            {
-                return true;
-            }
-            return string.Equals(Value, other.Value, comparisonType);
-        }
-
-        /// <summary>
-        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.
-        /// </summary>
-        /// <param name="obj">The second PathString for comparison.</param>
-        /// <returns>True if both PathString values are equal</returns>
-        public override bool Equals(object? obj)
-        {
-            if (obj is null)
-            {
-                return !HasValue;
-            }
-            return obj is PathString pathString && Equals(pathString);
-        }
-
-        /// <summary>
-        /// Returns the hash code for the PathString value. The hash code is provided by the OrdinalIgnoreCase implementation.
-        /// </summary>
-        /// <returns>The hash code</returns>
-        public override int GetHashCode()
-        {
-            return (HasValue ? StringComparer.OrdinalIgnoreCase.GetHashCode(Value) : 0);
-        }
-
-        /// <summary>
-        /// Operator call through to Equals
-        /// </summary>
-        /// <param name="left">The left parameter</param>
-        /// <param name="right">The right parameter</param>
-        /// <returns>True if both PathString values are equal</returns>
-        public static bool operator ==(PathString left, PathString right)
-        {
-            return left.Equals(right);
-        }
-
-        /// <summary>
-        /// Operator call through to Equals
-        /// </summary>
-        /// <param name="left">The left parameter</param>
-        /// <param name="right">The right parameter</param>
-        /// <returns>True if both PathString values are not equal</returns>
-        public static bool operator !=(PathString left, PathString right)
-        {
-            return !left.Equals(right);
-        }
-
-        /// <summary>
-        /// </summary>
-        /// <param name="left">The left parameter</param>
-        /// <param name="right">The right parameter</param>
-        /// <returns>The ToString combination of both values</returns>
-        public static string operator +(string left, PathString right)
-        {
-            // This overload exists to prevent the implicit string<->PathString converter from
-            // trying to call the PathString+PathString operator for things that are not path strings.
-            return string.Concat(left, right.ToString());
-        }
-
-        /// <summary>
-        /// </summary>
-        /// <param name="left">The left parameter</param>
-        /// <param name="right">The right parameter</param>
-        /// <returns>The ToString combination of both values</returns>
-        public static string operator +(PathString left, string? right)
-        {
-            // This overload exists to prevent the implicit string<->PathString converter from
-            // trying to call the PathString+PathString operator for things that are not path strings.
-            return string.Concat(left.ToString(), right);
-        }
-
-        /// <summary>
-        /// Operator call through to Add
-        /// </summary>
-        /// <param name="left">The left parameter</param>
-        /// <param name="right">The right parameter</param>
-        /// <returns>The PathString combination of both values</returns>
-        public static PathString operator +(PathString left, PathString right)
-        {
-            return left.Add(right);
-        }
-
-        /// <summary>
-        /// Operator call through to Add
-        /// </summary>
-        /// <param name="left">The left parameter</param>
-        /// <param name="right">The right parameter</param>
-        /// <returns>The PathString combination of both values</returns>
-        public static string operator +(PathString left, QueryString right)
-        {
-            return left.Add(right);
-        }
-
-        /// <summary>
-        /// Implicitly creates a new PathString from the given string.
-        /// </summary>
-        /// <param name="s"></param>
-        public static implicit operator PathString(string? s)
-            => ConvertFromString(s);
-
-        /// <summary>
-        /// Implicitly calls ToString().
-        /// </summary>
-        /// <param name="path"></param>
-        public static implicit operator string(PathString path)
-            => path.ToString();
-
-        internal static PathString ConvertFromString(string? s)
-            => string.IsNullOrEmpty(s) ? new PathString(s) : FromUriComponent(s);
-    }
-
-    internal sealed class PathStringConverter : TypeConverter
-    {
-        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
-            => sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
-
-        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
-            => value is string @string
-            ? PathString.ConvertFromString(@string)
-            : base.ConvertFrom(context, culture, value);
-
-        public override object ConvertTo(ITypeDescriptorContext context,
-           CultureInfo culture, object value, Type destinationType)
-            => destinationType == typeof(string)
-            ? value.ToString() ?? string.Empty
-            : base.ConvertTo(context, culture, value, destinationType);
-    }
-}
diff --git a/src/Components/WebView/WebView/src/PathStringHelper.cs b/src/Components/WebView/WebView/src/PathStringHelper.cs
deleted file mode 100644
index e132eeb13098ef41edbc3937415ded9dec4b1e54..0000000000000000000000000000000000000000
--- a/src/Components/WebView/WebView/src/PathStringHelper.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-// NOTE: This file is copied from src/Http/Http.Abstractions/src/Internal/PathStringHelper.cs
-// and made internal with a namespace change.
-// It can't be referenced directly from the StaticFiles package because that would cause this package to require
-// Microsoft.AspNetCore.App, thus preventing it from being used anywhere ASP.NET Core isn't supported (such as
-// various platforms that .NET MAUI runs on, such as Android and iOS).
-
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-
-namespace Microsoft.AspNetCore.Components.WebView
-{
-    internal static class PathStringHelper
-    {
-        // uint[] bits uses 1 cache line (Array info + 16 bytes)
-        // bool[] would use 3 cache lines (Array info + 128 bytes)
-        // So we use 128 bits rather than 128 bytes/bools
-        private static readonly uint[] ValidPathChars = {
-            0b_0000_0000__0000_0000__0000_0000__0000_0000, // 0x00 - 0x1F
-            0b_0010_1111__1111_1111__1111_1111__1101_0010, // 0x20 - 0x3F
-            0b_1000_0111__1111_1111__1111_1111__1111_1111, // 0x40 - 0x5F
-            0b_0100_0111__1111_1111__1111_1111__1111_1110, // 0x60 - 0x7F
-        };
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static bool IsValidPathChar(char c)
-        {
-            // Use local array and uint .Length compare to elide the bounds check on array access
-            var validChars = ValidPathChars;
-            var i = (int)c;
-
-            // Array is in chunks of 32 bits, so get offset by dividing by 32
-            var offset = i >> 5;		// i / 32;
-            // Significant bit position is the remainder of the above calc; i % 32 => i & 31
-            var significantBit = 1u << (i & 31);
-
-            // Check offset in bounds and check if significant bit set
-            return (uint)offset < (uint)validChars.Length &&
-                ((validChars[offset] & significantBit) != 0);
-        }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static bool IsPercentEncodedChar(string str, int index)
-        {
-            var len = (uint)str.Length;
-            if (str[index] == '%' && index < len - 2)
-            {
-                return AreFollowingTwoCharsHex(str, index);
-            }
-
-            return false;
-        }
-
-        [MethodImpl(MethodImplOptions.NoInlining)]
-        private static bool AreFollowingTwoCharsHex(string str, int index)
-        {
-            Debug.Assert(index < str.Length - 2);
-
-            var c1 = str[index + 1];
-            var c2 = str[index + 2];
-            return IsHexadecimalChar(c1) && IsHexadecimalChar(c2);
-        }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static bool IsHexadecimalChar(char c)
-        {
-            // Between 0 - 9 or uppercased between A - F
-            return (uint)(c - '0') <= 9 || (uint)((c & ~0x20) - 'A') <= ('F' - 'A');
-        }
-    }
-}
diff --git a/src/Components/WebView/WebView/src/QueryString.cs b/src/Components/WebView/WebView/src/QueryString.cs
deleted file mode 100644
index f2a23c6b2e883e4696b699099abe8b5e48aa4ace..0000000000000000000000000000000000000000
--- a/src/Components/WebView/WebView/src/QueryString.cs
+++ /dev/null
@@ -1,304 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-// NOTE: This file is copied from src/Http/Http.Abstractions/src/QueryString.cs
-// and made internal with a namespace change.
-// It can't be referenced directly from the StaticFiles package because that would cause this package to require
-// Microsoft.AspNetCore.App, thus preventing it from being used anywhere ASP.NET Core isn't supported (such as
-// various platforms that .NET MAUI runs on, such as Android and iOS).
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Text;
-using System.Text.Encodings.Web;
-using Microsoft.Extensions.Primitives;
-
-namespace Microsoft.AspNetCore.Components.WebView
-{
-    /// <summary>
-    /// Provides correct handling for QueryString value when needed to reconstruct a request or redirect URI string
-    /// </summary>
-    internal readonly struct QueryString : IEquatable<QueryString>
-    {
-        /// <summary>
-        /// Represents the empty query string. This field is read-only.
-        /// </summary>
-        public static readonly QueryString Empty = new QueryString(string.Empty);
-
-        /// <summary>
-        /// Initialize the query string with a given value. This value must be in escaped and delimited format with
-        /// a leading '?' character.
-        /// </summary>
-        /// <param name="value">The query string to be assigned to the Value property.</param>
-        public QueryString(string? value)
-        {
-            if (!string.IsNullOrEmpty(value) && value[0] != '?')
-            {
-                throw new ArgumentException("The leading '?' must be included for a non-empty query.", nameof(value));
-            }
-            Value = value;
-        }
-
-        /// <summary>
-        /// The escaped query string with the leading '?' character
-        /// </summary>
-        public string? Value { get; }
-
-        /// <summary>
-        /// True if the query string is not empty
-        /// </summary>
-        public bool HasValue => !string.IsNullOrEmpty(Value);
-
-        /// <summary>
-        /// Provides the query string escaped in a way which is correct for combining into the URI representation.
-        /// A leading '?' character will be included unless the Value is null or empty. Characters which are potentially
-        /// dangerous are escaped.
-        /// </summary>
-        /// <returns>The query string value</returns>
-        public override string ToString()
-        {
-            return ToUriComponent();
-        }
-
-        /// <summary>
-        /// Provides the query string escaped in a way which is correct for combining into the URI representation.
-        /// A leading '?' character will be included unless the Value is null or empty. Characters which are potentially
-        /// dangerous are escaped.
-        /// </summary>
-        /// <returns>The query string value</returns>
-        public string ToUriComponent()
-        {
-            // Escape things properly so System.Uri doesn't mis-interpret the data.
-            return !string.IsNullOrEmpty(Value) ? Value!.Replace("#", "%23") : string.Empty;
-        }
-
-        /// <summary>
-        /// Returns an QueryString given the query as it is escaped in the URI format. The string MUST NOT contain any
-        /// value that is not a query.
-        /// </summary>
-        /// <param name="uriComponent">The escaped query as it appears in the URI format.</param>
-        /// <returns>The resulting QueryString</returns>
-        public static QueryString FromUriComponent(string uriComponent)
-        {
-            if (string.IsNullOrEmpty(uriComponent))
-            {
-                return new QueryString(string.Empty);
-            }
-            return new QueryString(uriComponent);
-        }
-
-        /// <summary>
-        /// Returns an QueryString given the query as from a Uri object. Relative Uri objects are not supported.
-        /// </summary>
-        /// <param name="uri">The Uri object</param>
-        /// <returns>The resulting QueryString</returns>
-        public static QueryString FromUriComponent(Uri uri)
-        {
-            if (uri == null)
-            {
-                throw new ArgumentNullException(nameof(uri));
-            }
-
-            string queryValue = uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped);
-            if (!string.IsNullOrEmpty(queryValue))
-            {
-                queryValue = "?" + queryValue;
-            }
-            return new QueryString(queryValue);
-        }
-
-        /// <summary>
-        /// Create a query string with a single given parameter name and value.
-        /// </summary>
-        /// <param name="name">The un-encoded parameter name</param>
-        /// <param name="value">The un-encoded parameter value</param>
-        /// <returns>The resulting QueryString</returns>
-        public static QueryString Create(string name, string value)
-        {
-            if (name == null)
-            {
-                throw new ArgumentNullException(nameof(name));
-            }
-
-            if (!string.IsNullOrEmpty(value))
-            {
-                value = UrlEncoder.Default.Encode(value);
-            }
-            return new QueryString($"?{UrlEncoder.Default.Encode(name)}={value}");
-        }
-
-        /// <summary>
-        /// Creates a query string composed from the given name value pairs.
-        /// </summary>
-        /// <param name="parameters"></param>
-        /// <returns>The resulting QueryString</returns>
-        public static QueryString Create(IEnumerable<KeyValuePair<string, string?>> parameters)
-        {
-            var builder = new StringBuilder();
-            var first = true;
-            foreach (var pair in parameters)
-            {
-                AppendKeyValuePair(builder, pair.Key, pair.Value, first);
-                first = false;
-            }
-
-            return new QueryString(builder.ToString());
-        }
-
-        /// <summary>
-        /// Creates a query string composed from the given name value pairs.
-        /// </summary>
-        /// <param name="parameters"></param>
-        /// <returns>The resulting QueryString</returns>
-        public static QueryString Create(IEnumerable<KeyValuePair<string, StringValues>> parameters)
-        {
-            var builder = new StringBuilder();
-            var first = true;
-
-            foreach (var pair in parameters)
-            {
-                // If nothing in this pair.Values, append null value and continue
-                if (StringValues.IsNullOrEmpty(pair.Value))
-                {
-                    AppendKeyValuePair(builder, pair.Key, null, first);
-                    first = false;
-                    continue;
-                }
-                // Otherwise, loop through values in pair.Value
-                foreach (var value in pair.Value)
-                {
-                    AppendKeyValuePair(builder, pair.Key, value, first);
-                    first = false;
-                }
-            }
-
-            return new QueryString(builder.ToString());
-        }
-
-        /// <summary>
-        /// Concatenates <paramref name="other"/> to the current query string.
-        /// </summary>
-        /// <param name="other">The <see cref="QueryString"/> to concatenate.</param>
-        /// <returns>The concatenated <see cref="QueryString"/>.</returns>
-        public QueryString Add(QueryString other)
-        {
-            if (!HasValue || Value!.Equals("?", StringComparison.Ordinal))
-            {
-                return other;
-            }
-            if (!other.HasValue || other.Value!.Equals("?", StringComparison.Ordinal))
-            {
-                return this;
-            }
-
-            // ?name1=value1 Add ?name2=value2 returns ?name1=value1&name2=value2
-            return new QueryString(string.Concat(Value, "&", other.Value.AsSpan(1)));
-        }
-
-        /// <summary>
-        /// Concatenates a query string with <paramref name="name"/> and <paramref name="value"/>
-        /// to the current query string.
-        /// </summary>
-        /// <param name="name">The name of the query string to concatenate.</param>
-        /// <param name="value">The value of the query string to concatenate.</param>
-        /// <returns>The concatenated <see cref="QueryString"/>.</returns>
-        public QueryString Add(string name, string value)
-        {
-            if (name == null)
-            {
-                throw new ArgumentNullException(nameof(name));
-            }
-
-            if (!HasValue || Value!.Equals("?", StringComparison.Ordinal))
-            {
-                return Create(name, value);
-            }
-
-            var builder = new StringBuilder(Value);
-            AppendKeyValuePair(builder, name, value, first: false);
-            return new QueryString(builder.ToString());
-        }
-
-        /// <summary>
-        /// Evalutes if the current query string is equal to <paramref name="other"/>.
-        /// </summary>
-        /// <param name="other">The <see cref="QueryString"/> to compare.</param>
-        /// <returns><see langword="true"/> if the ssquery strings are equal.</returns>
-        public bool Equals(QueryString other)
-        {
-            if (!HasValue && !other.HasValue)
-            {
-                return true;
-            }
-            return string.Equals(Value, other.Value, StringComparison.Ordinal);
-        }
-
-        /// <summary>
-        /// Evaluates if the current query string is equal to an object <paramref name="obj"/>.
-        /// </summary>
-        /// <param name="obj">An object to compare.</param>
-        /// <returns><see langword="true" /> if the query strings are equal.</returns>
-        public override bool Equals(object? obj)
-        {
-            if (ReferenceEquals(null, obj))
-            {
-                return !HasValue;
-            }
-            return obj is QueryString && Equals((QueryString)obj);
-        }
-
-        /// <summary>
-        /// Gets a hash code for the value.
-        /// </summary>
-        /// <returns>The hash code as an <see cref="int"/>.</returns>
-        public override int GetHashCode()
-        {
-            return (HasValue ? Value!.GetHashCode() : 0);
-        }
-
-        /// <summary>
-        /// Evaluates if one query string is equal to another.
-        /// </summary>
-        /// <param name="left">A <see cref="QueryString"/> instance.</param>
-        /// <param name="right">A <see cref="QueryString"/> instance.</param>
-        /// <returns><see langword="true" /> if the query strings are equal.</returns>
-        public static bool operator ==(QueryString left, QueryString right)
-        {
-            return left.Equals(right);
-        }
-
-        /// <summary>
-        /// Evaluates if one query string is not equal to another.
-        /// </summary>
-        /// <param name="left">A <see cref="QueryString"/> instance.</param>
-        /// <param name="right">A <see cref="QueryString"/> instance.</param>
-        /// <returns><see langword="true" /> if the query strings are not equal.</returns>
-        public static bool operator !=(QueryString left, QueryString right)
-        {
-            return !left.Equals(right);
-        }
-
-        /// <summary>
-        /// Concatenates <paramref name="left"/> and <paramref name="right"/> into a single query string.
-        /// </summary>
-        /// <param name="left">A <see cref="QueryString"/> instance.</param>
-        /// <param name="right">A <see cref="QueryString"/> instance.</param>
-        /// <returns>The concatenated <see cref="QueryString"/>.</returns>
-        public static QueryString operator +(QueryString left, QueryString right)
-        {
-            return left.Add(right);
-        }
-
-        private static void AppendKeyValuePair(StringBuilder builder, string key, string? value, bool first)
-        {
-            builder.Append(first ? '?' : '&');
-            builder.Append(UrlEncoder.Default.Encode(key));
-            builder.Append('=');
-            if (!string.IsNullOrEmpty(value))
-            {
-                builder.Append(UrlEncoder.Default.Encode(value));
-            }
-        }
-    }
-}