lko
lko

Reputation: 8289

Convert a Dictionary to string of url parameters?

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

Answers (13)

Mike Perrenoud
Mike Perrenoud

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

Wiktor Zychla
Wiktor Zychla

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

John
John

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

Er Suman G
Er Suman G

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

Shimmy Weitzhandler
Shimmy Weitzhandler

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

Nick N.
Nick N.

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

Lazar Norris
Lazar Norris

Reputation: 371

You can use QueryHelpers from Microsoft.AspNetCore.WebUtilities:

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

Upvotes: 36

MohammadSoori
MohammadSoori

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

Christoph Fink
Christoph Fink

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

Stas BZ
Stas BZ

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

Alok
Alok

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

JuhaKangas
JuhaKangas

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

Alan Tsai
Alan Tsai

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

Related Questions