Reputation: 8289
Is there a way to convert a Dictionary in code into a url parameter string?
e.g.
// 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();
Inside MVC HtmlHelpers you can generate URLs with the UrlHelper (or Url in controllers) but in Web Forms code-behind the this HtmlHelper is not available.
string url = UrlHelper.GenerateUrl("Default", "Action", "Controller",
new RouteValueDictionary(parameters), htmlHelper.RouteCollection ,
htmlHelper.ViewContext.RequestContext, true);
How could this be done in C# Web Forms code-behind (in an MVC/Web Forms app) without the MVC helper?
Upvotes: 36
Views: 60273
Reputation: 67898
One approach would be:
var url = string.Format("https://example.org?{0}",
string.Join("&",
parameters.Select(kvp =>
string.Format(
"{0}={1}",
kvp.Key,
HttpUtility.UrlEncode(kvp.Value.ToString())))));
You could also use string interpolation as introduced in C#6:
var url = $"https://example.org?{string.Join("&", parameters.Select(kvp => $"{kvp.Key}={HttpUtility.UrlEncode(kvp.Value.ToString())}"))}";
And you could get rid of the UrlEncode
if you don't need it, I just added it for completeness.
Upvotes: 68
Reputation: 48230
This is old also there are other correct answers.
However, the builtin HttpValueCollection
already does escaping correctly, the only trick then is to rewrite the dictionary to it.
This means the following snippet reuses the implementation from the base class library and would be useful for anyone not using the NET.Core implementations (for example - people who still code against NET.Framework)
public static string ToQueryString( IDictionary<string, object> dict )
{
var collection = HttpUtility.ParseQueryString(string.Empty);
foreach ( var key in dict.Keys )
{
collection.Add( key, dict[key].ToString() );
}
return collection.ToString();
}
Upvotes: 0
Reputation: 6268
Using Newtonsoft JSON you can can quickly serialize an anonymous object into a http query by making extension functions.
This method also supports passing arrays as parameters to PHP using brackets.
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;
}
Example usage:
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;
Upvotes: 0
Reputation: 691
// 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)))));
I tried this code from the accepted answer (of Mike), but it did not worked. Actually that is wrong. Let's see what is wrong with that answer.
If you write HttpUtility.UrlEncode("a=1&b=2")
, it will also encode =
and &
and returns "a%3d1%26b%3d2"
which is not correct. So, you need to encode just keys and values like this:
// 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)))));
Or (using string interpolation)
var encodedUrl = $"http://www.yoursite.com?{string.Join("&", parameters.Select(kvp => $"{HttpUtility.UrlEncode(kvp.Key)}={HttpUtility.UrlEncode(kvp.Value)}"))}";
Upvotes: 3
Reputation: 104721
I'm not saying this option is better (I personally think it's not), but I'm here just to say it exists.
The QueryBuilder
class:
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();
Upvotes: 18
Reputation: 13559
I have written these extensions methods:
Add querystring to base url:
public static string AddQueryString(this string url, IDictionary<string, object> parameters) =>
$"{url}?{parameters.ToQueryString()}";
Convert dictionary of parameters to query string:
private static string ToQueryString(this IDictionary<string, object> parameters) =>
string.Join("&", parameters.Select(x => $"{x.Key}={x.Value}"));
Actual code to convert to query string:
string.Join("&", parameters.Select(x => $"{x.Key}={x.Value}"));
Edit:
When using in production consider encoding the parameters with URL.Encode
within this function. If you use this make sure the parameters in the dictionary are not already encoded.
Upvotes: 2
Reputation: 371
You can use QueryHelpers from Microsoft.AspNetCore.WebUtilities:
string url = QueryHelpers.AddQueryString("https://me.com/xxx.js", dictionary);
Upvotes: 36
Reputation: 2408
You can add the following class to the project and use the extension method.
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();
}
}
to use the code:
var queryString = dictionary.ToQueryString();
Upvotes: -1
Reputation: 23103
You could use a IEnumerable<string>
and 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);
or shorter
string baseUri = "http://www.somesite.com?";
string url = baseUri + String.Join("&", list.Select(i => $"{i.Name}={i.Value}"));
Upvotes: 5
Reputation: 1192
the most short way:
string s = string.Join("&", dd.Select((x) => x.Key + "=" + x.Value.ToString()));
But shorter does not mean more efficiency. Better use StringBuilder
and Append
method:
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());
}
Upvotes: 5
Reputation: 1310
You may try this:
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;
I have not run the logic, but this might help you.
If you would be UrlRouting in webforms then it would be a different story.
Check out:
http://msdn.microsoft.com/en-us/library/cc668201(v=vs.90).aspx
Upvotes: 1
Reputation: 883
Make a static helper class perhaps:
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);
}
Upvotes: 14
Reputation: 2525
Is this what you looking for (untested code)?
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("&"));
Upvotes: 1