【问题标题】:Creating an Uri in .NET automatically urldecodes all parameters from passed string在 .NET 中创建 Uri 会自动对传递的字符串中的所有参数进行 urldecode
【发布时间】:2011-09-05 12:06:45
【问题描述】:

假设我想从以下字符串创建一个 Uri 对象:

string url = @"http://someserver.com?param1=1&url=http%3a%2f%2fwww.otherserver.com";
Uri uri = new Uri(url, UriKind.Absolute);

预期结果是:

http://someserver.com?param1=1&url=http%3a%2f%2fwww.otherserver.com 

获得:

http://someserver.com/?param1=1&url=http://www.otherserver.com

在许多允许创建 Uri 的相关方法中发现了相同的行为:Uri.TryCreate、UriBuilder.Uri 等。

如何获得保留初始编码参数的 Uri?

【问题讨论】:

  • 做什么的预期结果?如果我在控制台应用程序Console.WriteLine(uri.AbsoluteUri); 中尝试您的代码,则返回编码的 url
  • 其他相关搜索。它实际上是解码字符串的 ToString() 方法。 .OriginalString 或 .AbsoluteUri 将返回编码后的字符串。对于相对 url,使用 .PathAndQuery

标签: c# .net url escaping


【解决方案1】:

在 .NET4 中,您可以为某些方案 via a configuration 禁用 Uri 压缩:

<configuration>
  <uri>
    <schemeSettings>
      <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes"/>
    </schemeSettings>
  </uri>
</configuration>

请注意,禁用默认行为会带来安全隐患。

【讨论】:

    【解决方案2】:

    您是如何“获取”该网址的?如果我在 Visual Studio 中将鼠标悬停在它上面,它确实会显示解码后的 URL。

    但每当我通过AbsoluteUri 属性访问它时,它都会显示编码后的 URL。

    【讨论】:

    • 好吧,我正在描述观察到的行为。这是一个 asp.net mvc 应用程序,但没关系。
    • 我没有问什么,我问的是如何。
    • 哎呀抱歉。我使用 asp.net mvc 路由形成,但我需要花费一些时间。
    • 我正在回复您的“获得”。仅当您将其转换为字符串时才会这样打印。 AbsoluteUri 属性可以满足您的需求。
    【解决方案3】:

    这种行为是documented:

    作为某些方案的构造函数中规范化的一部分, 转义的表示被压缩。 URI 将用于的方案 紧凑的转义序列包括:文件、http、https、 net.pipe 和 net.tcp。对于所有其他方案,转义序列是 没有压实。例如:如果您将两个点“..”编码为 "%2E%2E" 则 URI 构造函数将压缩此序列一段时间 计划。例如,以下代码示例显示了一个 URI http 方案的构造函数。

    因此,一种解决方法可能是暂时使用自定义方案(例如leavemealone://)来构造 URL 对象(可能通过UriBuilder?)。

    【讨论】:

    • 有趣的是,我发现rtsp:// 也会发生压缩。文档对包含哪些内容含糊不清(说“某些”方案未压缩,而压缩的方案“包含”这些)。
    【解决方案4】:

    在我的情况下,我通过返回 UriBuilder 类的 ToString() 方法而不是使用同一类的 Uri 属性来解决它。

    【讨论】:

      【解决方案5】:

      我推荐使用 Flurl 库。它允许对 URI 进行流畅和正确的构建和分析。见他们的例子。 https://flurl.dev/docs/fluent-url/

      它以 NuGet 包的形式提供。你不需要 HTTP-Stuff

          using Flurl;
      
          var url = "http://www.some-api.com"
          .AppendPathSegment("endpoint")
          .SetQueryParams(new {
              api_key = ConfigurationManager.AppSettings["SomeApiKey"],
              max_results = 20,
              q = "Don't worry, I'll get encoded!"
          })
          .SetFragment("after-hash");
      

      【讨论】:

        猜你喜欢
        • 2013-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-03
        • 1970-01-01
        • 2012-08-14
        • 2016-12-24
        相关资源
        最近更新 更多