【问题标题】:How to create Uri without fragmentation (convert # to %23)如何创建没有碎片的 Uri(将 # 转换为 %23)
【发布时间】:2025-12-13 18:30:01
【问题描述】:

我正在尝试使用查询字符串进行高级搜索,但是当我包含 # 时,它不会在创建 uri 时转换为 %23。

var webAddress = "www.worldwideweb.com/abc#d#e";
var uri = new Uri(webAddress).AbsoluteUri;

当我这样做时,会引发异常。 当我只包含一个 # 符号时,它会将其分段。就像在这个例子中

var webAddress = "https://api.stackexchange.com/2.2/search/advanced?site=*&q=[c#] OR [java]"
var uri = new Uri(webAddress).AbsoluteUri;

Uri 现在等于

https://api.stackexchange.com/2.2/search/advanced?site=*&q=[c#]%20OR%20[java]

我该怎么做

https://api.stackexchange.com/2.2/search/advanced?site=*&q=[c#] OR [f#]

进入

https://api.stackexchange.com/2.2/search/advanced?site=*&q=[c%23]%20OR%20[f%23]

我正在使用 .Net Framework 4.6.2

【问题讨论】:

    标签: c# uri


    【解决方案1】:

    我的方法是对每个 Query 参数使用 UriBuilder 和 Dictionary。然后你可以UrlEncode每个参数的值,这样你就可以得到一个有效的Url。

    这就是您的代码的样子:

    var ub = new UriBuilder("https", "api.stackexchange.com");
    ub.Path = "/2.2/search/advanced";
    // query string parameters
    var query = new Dictionary<string,string> ();
    query.Add("site", "*");
    query.Add("q", "[c#] OR [f#]");
    query.Add("filter", "!.UE46gEJXV)W0GSb");
    query.Add("page","1");
    query.Add("pagesize","2");
    
    // iterate over each dictionary item and UrlEncode the value
    ub.Query = String.Join("&",
        query.Select(kv => kv.Key + "=" + WebUtility.UrlEncode(kv.Value)));
    
    var wc = new MyWebClient();
    wc.DownloadString(ub.Uri.AbsoluteUri).Dump("result");
    

    这将导致ub.Uri.AbsoluteUri中的此网址:

    https://api.stackexchange.com/2.2/search/advanced?site=*&amp;q=%5Bc%23%5D+OR+%5Bf%23%5D&amp;filter=!.UE46gEJXV)W0GSb&amp;page=1&amp;pagesize=2

    由于 StackAPI 返回压缩后的内容,请在子类 WebClient 上使用 AutomaticDecompression(如 here 所示 feroze):

    class MyWebClient:WebClient
    {
       protected override WebRequest GetWebRequest(Uri uri) 
       {   
           var wr = base.GetWebRequest(uri) as HttpWebRequest;
           wr.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
           return wr;
       }
    }
    

    当与其他代码结合时,会为我生成输出:

    {
        "items" : [{
                "tags" : ["c#", "asp.net-mvc", "iis", "web-config"],
                "last_activity_date" : 1503056272,
                "question_id" : 45712096,
                "link" : "https://*.com/questions/45712096/can-not-read-web-config-file",
                "title" : "Can not read web.config file"
            }, {
                "tags" : ["c#", "xaml", "uwp", "narrator"],
                "last_activity_date" : 1503056264,
                "question_id" : 45753140,
                "link" : "https://*.com/questions/45753140/narrator-scan-mode-for-textblock-the-narrator-reads-the-text-properties-twice",
                "title" : "Narrator. Scan mode. For TextBlock the narrator reads the Text properties twice"
            }
        ]
    }
    

    【讨论】:

      【解决方案2】:

      如果#只存在于查询部分,你可以这样做:

      var webAddress = "https://api.stackexchange.com/2.2/search/advanced?site=*&q=[c#] OR [java]"
      var uri = new Uri(webAddress).AbsoluteUri;
      var fixedUri = Regex.Replace(uri, "#", "%23");
      

      【讨论】:

      • 这不适用于第一个示例,但由于某种原因它适用于 https://api.stackexchange.com/2.2/search/advanced?site=*&amp;q=[c#] OR [f#] 你知道为什么它适用于该示例而不是第一个示例吗?
      • @TimReinagel 在您的第一个示例中,# 用作锚标记,一个 url 中只能有一个锚标记,因此您的第一个 url 无效。第二个示例中的# 是查询的一部分,因此我们可以对其进行编码
      • @TimReinagel 如果您只想替换 # ,我的回答就足够了。如果要替换更多特殊字符,则必须对 url 进行编码
      • 不,在第二个示例中,它被用作锚点,但是当询问绝对 uri 时,除了 uri 的其余部分之外,您还获得了锚点部分。
      • @TimReinagel 我必须确认你提到的第二个例子是https://api.stackexchange.com/2.2/search/advanced?site=*&amp;q=[c#] OR [java] ??
      最近更新 更多