【问题标题】:Convert a Dictionary to string of url parameters?将字典转换为 url 参数字符串?
【发布时间】:2014-06-24 11:58:54
【问题描述】:

有没有办法将代码中的字典转换为url参数字符串?

例如

// An example list of parameters
Dictionary<string, object> parameters ...;
foreach (Item in List)
{
    parameters.Add(Item.Name, Item.Value);
}

string url = "http://www.somesite.com?" + parameters.XX.ToString();

在 MVC HtmlHelper 中,您可以使用 UrlHelper(或控制器中的 Url)生成 URL,但在 Web 表单代码隐藏中,此 HtmlHelper 不可用。

string url = UrlHelper.GenerateUrl("Default", "Action", "Controller", 
    new RouteValueDictionary(parameters), htmlHelper.RouteCollection , 
    htmlHelper.ViewContext.RequestContext, true);

如果没有 MVC 帮助器,如何在 C# Web 窗体代码隐藏(在 MVC/Web 窗体应用程序中)中完成此操作?

【问题讨论】:

    标签: c# asp.net-mvc dictionary webforms


    【解决方案1】:

    一种方法是:

    var url = string.Format("http://www.yoursite.com?{0}",
        HttpUtility.UrlEncode(string.Join("&",
            parameters.Select(kvp =>
                string.Format("{0}={1}", kvp.Key, kvp.Value)))));
    

    您还可以使用 C#6 中介绍的字符串插值:

    var url = $"http://www.yoursite.com?{HttpUtility.UrlEncode(string.Join("&", parameters.Select(kvp => $"{kvp.Key}={kvp.Value}")))}";
    

    如果你不需要UrlEncode,你可以去掉它,我只是为了完整起见添加了它。

    【讨论】:

    • 效率不高:string.Format 重复 (params.Count + 1) 次,创建 IEnumerator 对象,调用了这么多方法。创建匿名方法。简单地连接字符串(.
    • 如果不放yoursite.com? UrlEncode 之外的部分,结果将如下所示: http%3a%2f%2fwww.yoursite.com%3f ...我将对键和值进行编码,仅此而已。像这样: $"http ://www.yoursite.com?{string.Join("&", parameters.Select(kvp => $"{HttpUtility.UrlEncode(kvp.Key)}={HttpUtility.UrlEncode( kvp.Value)}"))}"
    • 这是无效的答案。 HttpUtility.UrlEncode("a=b&amp;c=d") 将编码 '=' 和 '&' 字符并返回 "a%3db%26c%3dd"。正确方法:$"https://example.com?{string.Join("&amp;", parameters.Select(kvp =&gt; $"{HttpUtility.UrlEncode(kvp.Key)}={HttpUtility.UrlEncode(kvp.Value)}"))}"
    • 我认为没有必要对字典Key进行url编码。相反,我只是对值进行 url 编码。这对我来说很安全: string.Join("&", parameters.Select(kvp => $"{kvp.Key}={HttpUtility.UrlEncode(kvp.Value)}"))
    【解决方案2】:

    也许做一个静态帮助类:

    public static string QueryString(IDictionary<string, object> dict)
    {
        var list = new List<string>();
        foreach(var item in dict)
        {
            list.Add(item.Key + "=" + item.Value);
        }
        return string.Join("&", list);
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用 Microsoft.AspNetCore.WebUtilities 中的 QueryHelpers:

      string url = QueryHelpers.AddQueryString("https://me.com/xxx.js", dictionary);
      

      【讨论】:

        【解决方案4】:

        最短路径:

        string s = string.Join("&", dd.Select((x) => x.Key + "=" + x.Value.ToString()));
        

        但更短并不意味着更高的效率。最好使用StringBuilderAppend 方法:

        first = true;
        foreach(var item in dd)
        {
            if (first)
                first = false;
            else
                sb.Append('&');
            sb.Append(item.Key);
            sb.Append('=');
            sb.Append(item.Value.ToString());
        }
        

        【讨论】:

        【解决方案5】:

        我并不是说这个选项更好(我个人认为不是),但我在这里只是说它存在。

        QueryBuilder 类:

        var queryStringDictionary = new Dictionary<string, string>
        {
            { "username", "foo" },
            { "password", "bar" }
        };
        
        var queryBuilder = new QueryBuilder(queryStringDictionary);
        queryBuilder.Add("type", "user");
        
        //?username=foo&password=bar&type=user
        QueryString result = queryBuilder.ToQueryString();
        

        【讨论】:

        • 为什么你认为这不是更好的选择?我认为这更好,因为您不必自己对值进行编码。这是一个小得多的解决方案。
        【解决方案6】:

        您可以使用IEnumerable&lt;string&gt;String.Join

        var parameters = new List<string>();
        foreach (var item in List)
        {
            parameters.Add(item.Name + "=" + item.Value.ToString());
        }
        
        string url = "http://www.somesite.com?" + String.Join("&", parameters);
        

        或更短

        string baseUri = "http://www.somesite.com?";
        string url = baseUri + String.Join("&", list.Select(i => $"{i.Name}={i.Value}"));
        

        【讨论】:

        • 我显然遗漏了一些东西,因为看起来如果你传入{ "abc" -&gt; "def", "ghi" -&gt; "jkl" } 这会产生abc=&amp;def&amp;ghi=&amp;jkl
        【解决方案7】:

        我已经写了这些扩展方法:

        将查询字符串添加到基本网址:

        public static string AddQueryString(this string url, IDictionary<string, object> parameters) => 
             $"{url}?{parameters.ToQueryString()}";
        

        将参数字典转换为查询字符串:

        private static string ToQueryString(this IDictionary<string, object> parameters) => 
            string.Join("&", parameters.Select(x => $"{x.Key}={x.Value}"));
        

        转换为查询字符串的实际代码:

        string.Join("&", parameters.Select(x => $"{x.Key}={x.Value}"));
        

        编辑:

        在生产中使用时,请考虑在此函数中使用URL.Encode 对参数进行编码。如果您使用它,请确保字典中的参数尚未编码。

        【讨论】:

        • @CarlosMuñoz 实施细节
        • 是的,正确实现细节。否则可能会导致错误
        • 同意卡洛斯:string.Join("&amp;", parameters.Select(kvp =&gt; $"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value.ToString())}"));
        • @Thymine 我添加了评论。在我的场景中,参数已经在字典中编码。
        【解决方案8】:

        这是您要找的(未经测试的代码)吗?

        StringBuilder sb = new StringBuilder();
        sb.Append("http://www.somesite.com?");
        
        foreach(var item in parameters)
        {
        sb.append(string.Format("{0}={1}&", item.Key, item.Value))
        }
        string finalUrl = sb.ToString();
        finalUrl = finalUrl.Remove(finalUrl.LasIndexOf("&"));
        

        【讨论】:

          【解决方案9】:

          你可以试试这个:

          var parameters = new Dictionary<string, string>(); // You pass this
          var url = "http://www.somesite.com?";
          int i = 0;
          foreach (var item in parameters)
          {
              url += item.Key + "=" + item.Value;
              url += i != parameters.Count ? "&" : string.Empty;
              i++;
          }
          
          return url;
          

          我没有运行逻辑,但这可能会对你有所帮助。

          如果您是 Web 表单中的 UrlRouting,那就另当别论了。

          退房:

          http://msdn.microsoft.com/en-us/library/cc668201(v=vs.90).aspx

          【讨论】:

            【解决方案10】:
            // this is wrong
            var url = string.Format("http://www.yoursite.com?{0}",
                HttpUtility.UrlEncode(string.Join("&",
                    parameters.Select(kvp =>
                        string.Format("{0}={1}", kvp.Key, kvp.Value))))); 
            

            我从(迈克的)接受的答案中尝试了这段代码,但没有奏效。其实这是错误的。让我们看看这个答案有什么问题。 如果你写HttpUtility.UrlEncode("a=1&amp;b=2"),它也会编码=&amp;并返回"a%3d1%26b%3d2",这是不正确的。因此,您只需要像这样对键和值进行编码:

            // this works
            var encodedUrl = string.Format("http://www.yoursite.com?{0}", 
                string.Join("&", parameters.Select(kvp => string.Format("{0}={1}", 
                    HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value)))));
            

            或者(使用字符串插值)

            var encodedUrl = $"http://www.yoursite.com?{string.Join("&", parameters.Select(kvp => $"{HttpUtility.UrlEncode(kvp.Key)}={HttpUtility.UrlEncode(kvp.Value)}"))}";
            

            【讨论】:

              【解决方案11】:

              使用 Newtonsoft JSON,您可以通过扩展函数将匿名对象快速序列化为 http 查询。

              此方法还支持使用括号将数组作为参数传递给 PHP。

                  public static string Join(this List<string> a, string seperator)
                  {
                      return string.Join(seperator, a.ToArray());
                  }
              
                  public static string ToHttpQuery(this object a)
                  {
                      string result = "";
              
                      foreach (var b in JObject.FromObject(a))
                      {
                          if (result.Length > 0)
                              result += "&";
              
                          if (b.Value.Type == JTokenType.Array)
                              result += b.Value.Select(x => b.Key + "[]=" + Uri.EscapeDataString(x.ToString())).ToList().Join("&");
                          else
                              result += b.Key + "=" + Uri.EscapeDataString(b.Value.ToString());
                      }
              
                      return result;
                  }
              

              示例用法:

                      string query = new
                      {
                          test = new string[] { "ree", "roo" },
                          myId = 123,
                          port = PORTS.MAIN_INTERFACE_IO,
                          targetUrl = "http://example.com/?fee=123"
                      }.ToHttpQuery();
                      
                      string myUrl = "http://example.com/?" + query;
              

              【讨论】:

                【解决方案12】:

                您可以在项目中添加以下类并使用扩展方法。

                using System.Collections.Generic;
                using System.Linq;
                using System.Text;
                
                public static class CollectionExtensions {
                    public static string ToQueryString(this IDictionary<string, string> dict)
                    {
                
                    if (dict.Count == 0) return string.Empty;
                
                    var buffer = new StringBuilder();
                    int count = 0;
                    bool end = false;
                
                    foreach (var key in dict.Keys)
                    {
                        if (count == dict.Count - 1) end = true;
                
                        if (end)
                            buffer.AppendFormat("{0}={1}", key, dict[key]);
                        else
                            buffer.AppendFormat("{0}={1}&", key, dict[key]);
                
                        count++;
                    }
                
                    return buffer.ToString();
                }
                }
                

                使用代码:

                var queryString = dictionary.ToQueryString();
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2011-02-17
                  • 2020-09-16
                  • 2021-07-25
                  • 1970-01-01
                  相关资源
                  最近更新 更多