【问题标题】:C# Httpclient FormUrlEncodedContent EncodingC# Httpclient FormUrlEncodedContent 编码
【发布时间】:2017-03-17 08:23:04
【问题描述】:

我在使用 httpclient 将数据发布到服务器时遇到问题。它适用于带有 FormUrlEncodedContent 的 httpClient.PostAsync。

但是,如果我的 FormUrlEncodedContent 内容包含一个字符“~”,它不会将其转换为 %7E。我不知道如何强制它对其进行编码。

以下是我目前的编码示例。

var content = new FormUrlEncodedContent(new Dictionary<string, string>()
{
    ["content"] = "Hello World~"
});
var response = await httpClient.PostAsync(url, content);

正文内容的 Fiddler 原始结果将是:

content=Hello%20World~

这不是我的预期。我希望结果应该是 内容=Hello%20World%7E

我该怎么做?

谢谢

【问题讨论】:

    标签: c# uwp .net-core


    【解决方案1】:

    这很有趣。所以波浪号 (~) 非常特别……如果您查看 rfc2396 和 rfc3986,它实际上是允许在 URL 中的。 rfc1738 将其定义为 %7e,但 rfc2396 和 rfc3986 类型推翻了这一点。

    所以……这基本上取决于编码实现。例如 PHP 在某个时候改变了它:http://php.net/manual/en/function.rawurlencode.php

    顺便说一句。在 CoreFx repo 你可以看看FormUrlEncodedContent的源代码

    如您所见,它使用Uri.EscapeDataString

    它指出

    默认情况下,EscapeDataString 方法转换所有字符,除了 将 RFC 2396 未保留字符转换为十六进制 表示。

    RFC 2396 中,波浪号被定义为无保留字符。

    因此,根据文档,这是有效的,fiddler 向您显示的是一个绝对有效的 URL。

    对于您获取 %7e 而不是 '~' 的具体问题: 一种选择是手动替换它,因为这确实是一种特殊情况。

    另一种是使用System.Web.HttpUtility.UrlEncode,将其编码为%7e。 EscapeDataString(由 FormUrlEncodedContent 使用)和 System.Web.HttpUtility.UrlEncode 之间的区别在于 EscapeDataString 使用尽可能多的纯文本字符。但是它们都创建了一个有效的 URL 编码字符串。

    【讨论】:

    • 谢谢它的工作。我使用 corefx one 的源代码并创建自己的类。在编码的方法中。我只需要将 ~ 替换为 %7E。 private static string Encode(string data) { if (String.IsNullOrEmpty(data)) { return String.Empty; } // 将空格转义为 '+'。 return Uri.EscapeDataString(data).Replace("%20", "+").Replace("~", "%7E"); }
    • @Jobria 是的,这似乎没问题。
    【解决方案2】:

    所以您想使用“System.Web”库中的 HttpUtility UrlEncode 方法。有关 msdn 页面,请参阅 here

    System.Web.HttpUtility.UrlEncode(@"~\Hello World");
    

    结果:

    %7e%5cUrl%5cHello+World

    我已经尝试并测试了它 - 它正确地将符号替换为正确编码的对应物。

    【讨论】:

    • 你是对的 - 抱歉,我没有看到 netcore 标签。 @gregkalapos 在那里有一个很好的答案。 Uri.EscapeDataString 本身就可以很好地工作 - 使用 netcore 控制台应用程序和 netcore Web 服务进行了尝试。
    【解决方案3】:

    这是一个应该做的工作:

            var formParams = new Dictionary<string, string>(){
                ["content"] = "Hello World~"
            };
    
            var stringFormParams = new Func<IDictionary<string,string>,string>((dic) => {
                string result = "";
                foreach(var param in dic) {
                    if (result.Length > 0) { result += "&"; }
                    result += param.Key + "=" + WebUtility.UrlEncode(param.Value);
                }   
                return result;             
            }).Invoke(formParams); 
    
            var stringContent = new StringContent(stringFormParams, Encoding.UTF8, "application/x-www-form-urlencoded");
            Console.WriteLine(stringContent.ReadAsStringAsync().Result);
    
            HttpClient httpClient = new HttpClient();
            var response = await httpClient.PostAsync(url, stringContent);
    

    输出:

    content=Hello+World%7E
    

    【讨论】:

    • 我认为这仍然有效。但是我还没有测试过。我使用了gregkalapos one的答案。不管怎样,谢谢你的帮助。
    【解决方案4】:

    @gregkalapos 和 @Bertie 给出了精彩的答案。

    但我有其他方法可以使用 Uri 进行编码。

    Uri.EscapeDataString(str) 
    

    如果你需要unescape,请使用Uri.UnescapeDataString(str)

    见:How to encode/decode url strings in an UWP App

    【讨论】:

    • 但如果内容中有非英文字符(如中文或日文),则会出现问题
    • @Jobria 汉字和日文都可以用,我很好用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多