.NET(C#): 解析和创建URL中的Query String

.NET(C#): 解析和创建URL中的Query String

2012年07月11日 ⁄ 综合 ⁄ 共 3538字 ⁄ 字号 小 中 大 ⁄ 评论关闭

工程中需要解析和构造URL中的Query String,客户端,自然用不到ASP.NET,也不想用什么第三方类库。自己写一个。

当然.NET 4.5中的FormUrlEncodedContent可以快速构建一个Query String数据,它继承自HttpContent,主要用来设置HTTP包的内容。

来用FormUrlEncodedContent创建一个简单的Query String:

//+ using System.Net.Http;

var data = new Dictionary<string, string>() { { "q", "一二三 Mgen" }, { "output", "search" } };

var content = new FormUrlEncodedContent(data);

Console.WriteLine(await content.ReadAsStringAsync());

 

输出:

q=%E4%B8%80%E4%BA%8C%E4%B8%89+Mgen&output=search

 

FormUrlEncodedContent会用到Uri.EsacapeDataString但是会把%20替换成+。

 

不过一个简单的Query String自然也不需要把代码要求提升到.NET 4.5。后来又写了两个方法,使用DataToUrl和UrlToData可以实现完整的带Query String的转换和创建。

 

方法使用IEnumerable<KeyValuePair<string, string>>做参数数据,和FormUrlEncodedContent保持一致,方便用户使用Dictionary<string, string>。

 

示例代码:

//URL数据

var data = new Dictionary<string, string>() { { "q", "一二三 Mgen" }, { "output", "search" } };

 

//编码

var str = DataToUrl("http://www.google.com", data);

Console.WriteLine("编码");

Console.WriteLine(str);

 

//解码

Console.WriteLine("解码");

var decoded = UrlToData(str);

Console.WriteLine(decoded.Item1);

Console.WriteLine(String.Join("\n", decoded.Item2));

 

输出:

编码

http://www.google.com?q=%E4%B8%80%E4%BA%8C%E4%B8%89%20Mgen&output=search

解码

http://www.google.com

[q, 一二三 Mgen]

[output, search]

 

当然程序还考虑到一些特殊情况,比如某些Query String有些不规则,如Google的查询可能会出现如下地址:

 

有?hl=en还有#hl=en。这个#应该是URL中跳转到HTML中链接位置,不属于Query String中的,Query String中应该对#进行编码,但是既然#出现在Google查询的参数中,那么程序只能去调节算法。一些Query String解析代码遇到此类URL要么挂掉要么显示:tab = ww#hl(我猜想是因为解析数据是按照=分割字符串,然后取前两个值,但是这里还多个”=en”,所以他就被忽略了)。至于该不该把#hl=en也解析出来,我认为不应该,毕竟他不符合URL Query String参数的格式。但是也不该把他忽略掉,解析不了就把原始值显示出来。

 

那么使用我的方法解析这种URL:

var url = "http://www.google.com/webhp?hl=en&tab=ww#hl=en&newwindow=1

&output=search&sclient=psy-ab&q=mgen&oq=mgen&gs_l=hp.3..0l4.6238.6514

.0.6788.4.4.0.0.0.0.171.481.1j3.4.0.les%3B..0.0...1c.1.n1GMg7Ow5KA&pb

x=1&bav=on.2,or.r_gc.r_pw.r_qf.&fp=5b519d645da47f94&biw=1241&bih=606";

var decoded = UrlToData(url);

Console.WriteLine(decoded.Item1);

Console.WriteLine(String.Join("\n", decoded.Item2));

 

结果:

http://www.google.com/webhp

[hl, en]

[tab, ww#hl=en]

[newwindow, 1]

[output, search]

[sclient, psy-ab]

[q, mgen]

[oq, mgen]

[gs_l, hp.3..0l4.6238.6514.0.6788.4.4.0.0.0.0.171.481.1j3.4.0.les;..0.0...1c.1.n

1GMg7Ow5KA]

[pbx, 1]

[bav, on.2,or.r_gc.r_pw.r_qf.]

[fp, 5b519d645da47f94]

[biw, 1241]

[bih, 606]

 

 

最后,方法源代码

//编码

static string DataToUrl(string url, IEnumerable<KeyValuePair<string, string>> data)

{

    if (data == null)

        throw new ArgumentNullException("data");

 

    bool first = true;

    var sb = new StringBuilder(url);

    foreach (var item in data)

    {

        if (first)

        {

            sb.Append('?');

            first = false;

        }

        else

            sb.Append('&');

 

        sb.Append(Uri.EscapeDataString(item.Key) + "=" + Uri.EscapeDataString(item.Value));

    }

 

    return sb.ToString();

}

 

//解码

static Tuple<string, IEnumerable<KeyValuePair<string, string>>> UrlToData(string url)

{

    if (url == null)

        throw new ArgumentNullException("url");

 

    url = url.Trim();

    try

    {

        var split = url.Split(new[] { '?', '&' }, StringSplitOptions.RemoveEmptyEntries);

        if (split.Length == 1)

            return new Tuple<string, IEnumerable<KeyValuePair<string, string>>>(url, null);

 

        //获取前面的URL地址

        var host = split[0];

 

        var pairs = split.Skip(1).Select(s =>

            {

                //没有用String.Split防止某些少见Query String中出现多个=,要把后面的无法处理的=全部显示出来

                var idx = s.IndexOf('=');

                return new KeyValuePair<string, string>(Uri.UnescapeDataString(s.Substring(0, idx)),Uri.UnescapeDataString(s.Substring(idx + 1)));

            }).ToList();

 

        return new Tuple<string, IEnumerable<KeyValuePair<string, string>>>(host, pairs);

    }

    catch (Exception ex)

    {

        throw new FormatException("URL格式错误", ex);

    }

}

 转载:http://www.xuebuyuan.com/130990.html

posted @ 2016-05-25 08:47  晒晒  阅读(4189)  评论(0)    收藏  举报