views:

73

answers:

5

Is there a utility to combine querystrings? I'm looking for something like:

Input: Combine("test=a&test2=b", "test3=c") Result: "test=a&test2=b&test3=c"

Input: Combine("test=a&test2=b", "") Result: "test=a&test2=b"

Input: Combine("", "test3=c") Result: "test3=c"

And maybe some weird ones:

Input: Combine("&test=a&test2=b", "?test3=c") Result: "test=a&test2=b&test3=c"

A: 

Wouldn't such method work for you?

string Combine(string s1, string s2)
{
     if(string.IsNullOrEmpty(s1)) return s2;
     if(string.IsNullOrEmpty(s2)) return s1;
     //several '?' at start are not expected so we can use TrimStart
     return s1.TrimStart('?', '&') + "&" + s2.TrimStart('?', '&');
}
iPhone beginner
A: 

You can combine any number of query strings with that

CombineQueryStrings(params string[] segments ){
    List<string> list = new List<string>();
    foreach (var s in segments)
    {
        list.Add(s.Trim('?', '&'));
    }
    return string.Join("&", list.ToArray());
}
Draco Ater
It seems that you don't handle `Combine("", "test3=c")` case properly
iPhone beginner
A: 

I am not sure if you would get a out of box solution for your requirement. You could use extension method as a way to achieve this. For more information on extension method refer: Extension Methods

ARS
A: 

This is a .NET 4.0 solution because of the Join overload that's being used and it's not completely out of the box. However, it uses .NET System.Web.HttpUtility to correctly parse the querystrings.

var r1 = HttpUtility.ParseQueryString("?test3=c");
var r2 = HttpUtility.ParseQueryString("");
var r3 = HttpUtility.ParseQueryString("test2=d");

var total = new NameValueCollection();

total.Add(r1);
total.Add(r2);
total.Add(r3);

var qs = String.Join(
    "&", 
    total.AllKeys.Select(key => key + "=" + total[key]));

Console.WriteLine(qs);

Outputs:

// test3=c&test2=d
João Angelo
I don't think that this is a good idea as you decode URL-encoded characters in HttpUtility.ParseQueryString and don't encode them when you join strings back.
iPhone beginner
@iPhone beginner, the code sample is just to demonstrate a way to achieve what the OP requested. It's not intended to be a complete solution. As a side note the `HttpUtility` class also has methods for URL-encoding a string.
João Angelo
Anyway, why do you need to use HttpUtility here at all? What OP needs is just proper string concatenation with a few tricks. I don't see a reason to parse strings, decode them, and then encode and join again. IMHO, this is too lot of work and too many places to make a mistake.
iPhone beginner
@iPhone beginner, let's agree to disagree. The answer was provided in order to provide information that I consider helpful to the OP and that demonstrates a possible solution to the problem. That's all, no more no less.
João Angelo
I unfortunately cannot use .Net 4.0 yet, but thank you.
adam0101
A: 

I use the following class to help me modify and set query strings. While it doesn't solve your exact problem, you can use it and add some more functions of your own to accomplish whatever you want. I just find it handy to treat query strings as an IDictionary when I want to modify them.

public static class QueryStringExtensions
{
    /// <summary>
    /// Creates a dictionary from a query string or other parameter collection
    /// </summary>
    /// <param name="queryString"></param>
    /// <returns></returns>
    public static IDictionary<string, string> ToDictionary(this NameValueCollection queryString)
    {
        var dict = new Dictionary<string, string>();
        foreach (string key in queryString.Keys)
        {
            dict[key] = queryString[key];
        }
        return dict;
    }

    /// <summary>
    /// Generates a query string from a dictionary
    /// </summary>
    /// <param name="dictionary"></param>
    /// <returns></returns>
    public static string ToQueryString(this IDictionary<string, string> dictionary)
    {
        if (dictionary.Count == 0) return "";
        var items = new List<string>();
        foreach (string key in dictionary.Keys)
        {
            items.Add(key + "=" + dictionary[key]);
        }
        return "?" + items.Concatenate("&");
    }

    /// <summary>
    /// Generates a query stirng from a dictionary only using the keys in the keys parameter
    /// </summary>
    /// <param name="dictionary"></param>
    /// <param name="keys"></param>
    /// <returns></returns>
    public static string ToQueryString(this IDictionary<string, string> dictionary, IEnumerable<string> keys)
    {
        var items = new List<string>();
        foreach (string key in dictionary.Keys.Intersect(keys))
        {
            items.Add(key + "=" + dictionary[key]);
        }
        if (items.Count == 0) return "";
        return "?" + items.Concatenate("&");
    }

    /// <summary>
    /// joins an enumerable around a seperator.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="input"></param>
    /// <param name="seperator"></param>
    /// <returns></returns>
    public static string Concatenate<T>(this IEnumerable<T> input, string seperator)
    {
        var ar = input.Select(i => i.ToString()).ToArray();
        return string.Join(seperator, ar);
    }
}
tster
Don't you forget to URL-encode characters?
iPhone beginner
good point! I always like when posting code here makes it better.
tster