美文网首页
HttpUtility.ParseQueryString 在.N

HttpUtility.ParseQueryString 在.N

作者: gruan | 来源:发表于2022-04-21 10:30 被阅读0次

    .NET48 代表 .NET FULL FRAMEWORK
    .NET5 代表 .NET CORE 及以上版本

    先看看这两个地址:

    http://www.baidu.com?y=%u4e2d
    http://www.baidu.com?y=%e4%b8%ad

    %u4e2d = \u4e2d =

    生成这两个地址的代码是一样的:

    public static string SetUrlKeyValue2(this string url, IEnumerable<KeyValuePair<string, string>> kvs, bool ignoreCase = true, Encoding encoding = null)
    {
        if (kvs.IsNullOrEmpty())
            return url;
    
        url ??= "";
        encoding ??= Encoding.UTF8;
    
        var query = "";
        var prefix = url;
        if (url.IndexOf("?") > -1)
        {
            prefix = url.Substring(0, url.IndexOf("?"));
            query = url.Substring(url.IndexOf("?"));
        }
    
        NameValueCollection ns = HttpUtility.ParseQueryString(query, encoding);
    
    //#if NETFULL
    //    ns = new HttpQSCollection(ns);
    //#endif
    
        foreach (var kv in kvs)
            ns.Set(kv.Key, kv.Value);
    
        return HttpUtility.UrlPathEncode($"{prefix}?{ns}");
    }
    

    第一个地址是无效地址, 在浏览器里用 decodeURI 是报错的:

    NETFULL_DECODEURL.png

    第二个是正确的:


    NET5_DECODEURI.png

    第一个地址是 .NET4.8 生成的, 第二个是 .NET5 生成的,相同的代码。。。

    至于为什么会有这么大的差异,要从 HttpUtility.ParseQueryString 说起。

    在 .NET4.8 下,HttpUtility.ParseQueryString 的返回是:System.Web.HttpValueCollection 类型的实例
    在 .NET5 下, 返回类型是 System.Web.HttpUtility.HttpQSCollection 类型的实例。

    NET5.png NETFULL.png

    HttpQSCollection 类在 .NET 4.8 中不存在,在 .NET5 里, 也只是一个不公开的内部类。
    这个类很简单,只重写了 NameValueCollectionToString 方法而已, 源码在:HttpUtility.cs 中可以找到:

        internal sealed class HttpQSCollection : NameValueCollection
        {
    
            /// <summary>
            /// 
            /// </summary>
            /// <param name="ns"></param>
            public HttpQSCollection(NameValueCollection ns)
                : base(ns)
            {
            }
    
            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                int count = Count;
                if (count == 0)
                    return "";
                StringBuilder sb = new StringBuilder();
                string[] keys = AllKeys;
                for (int i = 0; i < count; i++)
                {
                    sb.AppendFormat("{0}={1}&", keys[i], HttpUtility.UrlEncode(this[keys[i]]));
                }
                if (sb.Length > 0)
                    sb.Length--;
                return sb.ToString();
            }
        }
    

    把上面的代码代入, 就可能修正 .NET4.8 的问题了。

    public static string SetUrlKeyValue2(this string url, IEnumerable<KeyValuePair<string, string>> kvs, bool ignoreCase = true, Encoding encoding = null)
    {
        if (kvs.IsNullOrEmpty())
            return url;
    
        url ??= "";
        encoding ??= Encoding.UTF8;
    
        var query = "";
        var prefix = url;
        if (url.IndexOf("?") > -1)
        {
            prefix = url.Substring(0, url.IndexOf("?"));
            query = url.Substring(url.IndexOf("?"));
        }
    
        NameValueCollection ns = HttpUtility.ParseQueryString(query, encoding);
    
    #if NETFULL
        ns = new HttpQSCollection(ns);
    #endif
    
        foreach (var kv in kvs)
            ns.Set(kv.Key, kv.Value);
    
        return HttpUtility.UrlPathEncode($"{prefix}?{ns}");
    }
    

    相关文章

      网友评论

          本文标题:HttpUtility.ParseQueryString 在.N

          本文链接:https://www.haomeiwen.com/subject/qqriertx.html