文字 Uri 请求

发布于 2024-12-27 01:54:03 字数 1048 浏览 1 评论 0原文

我看过很多帖子询问如何使用不合格的 Uris,但没有一个给出好的答案。我正在编写一个 Windows Phone 控件,它需要使用 HTTP GET 请求 ATOM 数据。 URL 中需要包含字符 %3d(等号)。这是不容协商的,因为它是我无法控制的第三方服务。想象一下如下的 URL:

http://host.com?arg1=val1&arg= val2%3d

我正在将 WebClient 与 DownloadStringAsync 结合使用,但它只接受 Uri 对象,而不接受字符串中的 URL。 Uri 对象自动转义这些字符并发送:

http://host.com?arg1=val1& arg=val2=

这失败了。有一个已弃用的构造函数参数“UserExcaped”正是我所需要的,但它不可用。我担心我唯一的选择是使用原始套接字和最少的 HTTP 支持来实现我自己的字符串下载方法。

还有其他想法吗?非常感谢帮助!

更新 <代码>


    string apps = "http://blah.com/api?prev=AAAAAAA%3d&next=BBBBBBB";
    var u = new Uri(apps);
    string apps2 = u.ToString();
    Debug.Assert(apps == apps2); // That %3d will always be converted to an equals sign

我还应该指出,如果我尝试巧妙地将百分比编码为 %25 (因此它是“prev=AAAAAA%253d&next=BBBBB”),那么我会得到确切的文字字符串,其中 %25 仍然完好无损!只是 %3d 它积极地转换为等号。

I've seen a number of posts that ask about using non-conforming Uris, but none of them have a good answer. I'm writing a Windows Phone control and it needs to request ATOM data using HTTP GET. The URL needs to include the characters %3d (the equal sign) in it. This is non-negotiable as it's a third-party service over which I have no control. Imagine a URL like the following:

http://host.com?arg1=val1&arg=val2%3d

I'm using WebClient with DownloadStringAsync, but it only accepts Uri objects, not URL in strings. The Uri object automatically unescapes those characters and sends:

http://host.com?arg1=val1&arg=val2=

This fails. There's a deprecated constructor argument "UserExcaped" that is exactly what I need, but it's not available. I fear that my only option is to implement my own string download method using a raw socket and minimal HTTP support.

Any other thoughts? Help is very much appreciated!!

UPDATE


    string apps = "http://blah.com/api?prev=AAAAAAA%3d&next=BBBBBBB";
    var u = new Uri(apps);
    string apps2 = u.ToString();
    Debug.Assert(apps == apps2); // That %3d will always be converted to an equals sign

I should also point out, that if I try to be clever by encoding the percent as %25 (so it's "prev=AAAAAA%253d&next=BBBBB") then I get that exact literal string with %25 still intact! It's just %3d that it's aggressive about converting to an equals sign.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

洋洋洒洒 2025-01-03 01:54:03

Uri 类就是这样设计的。 MSDN

作为某些方案构造函数中规范化的一部分,
转义表示被压缩。 URI 将针对的方案
紧凑转义序列包括以下内容:file、http、https、
net.pipe 和 net.tcp。对于所有其他方案,转义序列是
未压实。

您是否尝试过使用 HttpWebRequest 来代替?它比 WebClient 的工作量要多一些,但它允许您传递字符串作为目标。

编辑 - 另一种方法可能是创建您自己的 UriParser ,它允许编码版本。扩展 UriParser 的示例可以此处找到

对于其他运行 Windows Phone 的用户,您可以使用反射来解决此问题。

MethodInfo getSyntax = typeof(UriParser).GetMethod("GetSyntax", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
FieldInfo flagsField = typeof(UriParser).GetField("m_Flags", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if (getSyntax != null && flagsField != null)
{
   foreach (string scheme in new[] { "http", "https" })
   {

       UriParser parser = (UriParser)getSyntax.Invoke(null, new object[] { scheme });
       if (parser != null)
       {
           int flagsValue = (int)flagsField.GetValue(parser);

           //0x20000 is the SimpleUserSyntax attribute
           if ((flagsValue & 0x20000) != 0)
              flagsField.SetValue(parser, flagsValue & ~0x20000);
       }
    }
}


Uri u = new Uri("http://host.com?arg1=val&arg=val2%3d");
//At this point, the %3d remains as expected.

The Uri class is designed to be like that. MSDN:

As part of canonicalization in the constructor for some schemes,
escaped representations are compacted. The schemes for which URI will
compact escaped sequences include the following: file, http, https,
net.pipe, and net.tcp. For all other schemes, escaped sequences are
not compacted.

Have you tried using HttpWebRequest instead? It's a bit more work than a WebClient, but it lets you pass a string as the destination.

Edit - Another approach could be to create your own UriParser which allows the encoded version. An example of extending the UriParser can be found here.

For others not running Windows Phone, you can use reflection to fix this.

MethodInfo getSyntax = typeof(UriParser).GetMethod("GetSyntax", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
FieldInfo flagsField = typeof(UriParser).GetField("m_Flags", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if (getSyntax != null && flagsField != null)
{
   foreach (string scheme in new[] { "http", "https" })
   {

       UriParser parser = (UriParser)getSyntax.Invoke(null, new object[] { scheme });
       if (parser != null)
       {
           int flagsValue = (int)flagsField.GetValue(parser);

           //0x20000 is the SimpleUserSyntax attribute
           if ((flagsValue & 0x20000) != 0)
              flagsField.SetValue(parser, flagsValue & ~0x20000);
       }
    }
}


Uri u = new Uri("http://host.com?arg1=val&arg=val2%3d");
//At this point, the %3d remains as expected.
噩梦成真你也成魔 2025-01-03 01:54:03

尝试使用 Hammock - 您应该能够给它一个字符串而不是 Uri。

Try using Hammock - you should be able to give it a string rather than a Uri.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文