URL有时无法正确编码 - 线程问题?

时间:2011-07-18 13:03:20

标签: c# multithreading

我正在使用C#中的Windows窗体应用程序,并且有一个类似下面的方法,可由多个线程访问(确切地说,由多个后台工作者访问):

public Uri signURL(OAuthToken token, string url)
{
   UriBuilder builder = new UriBuilder(addOAuthParameters(url));
   NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);

   query.Set("oauth_consumer_key", consumerKey);

   /*
    * & sometimes not replaced by %26
    */
   query.Set("oauth_signature", consumerSecret + "&" + token.Secret);
   query.Set("oauth_token", token.Token);
   builder.Query = query.ToString();

   return builder.Uri;
}

我使用此方法使用一些必需的OAuth参数对任意URL进行签名,然后执行HttpWebRequest以检索内容。

编辑1:以下是addOAuthParameter方法的内容:

private Uri addOAuthParameters(string uri)
{
    UriBuilder builder = new UriBuilder(uri);
    NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);
    query.Set("oauth_signature_method", "PLAINTEXT");
    query.Set("oauth_timestamp", "" + (int)(DateTime.UtcNow -
        new DateTime(1970, 1, 1)).TotalSeconds);
    query.Set("oauth_nonce", "" + getNonce());
    query.Set("oauth_version", "1.0");
    builder.Query = query.ToString();
    return builder.Uri;
}

有时,oauth_signature参数包含一个&符号,尽管这应该由NameValueCollection对象用%26正确编码,结果,我得到一个“401 Unauthorized”。当多个后台工作程序(多个线程?)访问该方法时,我感觉会发生这种情况。这可能吗?

编辑2:好的,似乎我已经缩小了问题范围。如果我执行了Debug.Assert(builder.Uri.ToString().Contain("%26") && builder.Uri.PathAndQuery.Contains("%26"));,则builder.Uri.ToString()builder.Uri.PathAndQuery的情况下不包含%26。现在,为什么?

调试问题结果非常困难。有没有人有任何建议?

1 个答案:

答案 0 :(得分:4)

Uri.ToString仅用于显示文档,表明它返回未转义的字符串。

您想使用Uri.AbsoluteUriUri.OriginalStringUri.GetComponents

var uri = new Uri("http://example.com/some?query=testing%26other");
Console.WriteLine(uri.ToString());
Console.WriteLine(uri.GetComponents(UriComponents.AbsoluteUri, UriFormat.UriEscaped));

http://example.com/some?query=testing&other
/some?query=testing%26other

GetComponents的优点是明确指定了转义,因此没有歧义。

一些简单的建议(最初来自Keith Brown的博客文章,Beware Uri.ToString)。

  • 当你知道它是绝对的时,使用Uri.AbsoluteUri获取URI的值。
  • 当URI可以是绝对值或相对值时,使用Uri.OriginalString获取URI的值(此方法不会为相对URI抛出InvalidOperationException)。
  • 使用Uri.ToString只有在你真正希望它被转义时才能获取URI的值(例如,当你想为人类很好地展示它时)。
  • 在调试器中查看URI时,请记住调试器使用Uri.ToString,因此您看到的内容可能与URI所包含的内容不完全匹配。