Reputation: 131
I'm creating a method that should be able to have a Dictionary as parameter.
This method prepares a set of parameters to be appended to a URI as get/post parameters. The problem is that when I call BuildQueryData(item), I get an error: Cannot convert KeyValuePair to Dictionary.
private string BuildQueryData(Dictionary<string, object> param)
{
if (param == null)
return "";
StringBuilder b = new StringBuilder();
foreach (var item in param)
{
Dictionary<string, object> o;
if (item.GetType() == "".GetType())
b.Append(string.Format("&{0}={1}", item.Key, WebUtility.UrlEncode((string)item.Value)));
else if (item.GetType() == new Dictionary<string, object>().GetType())
b.Append(BuildQueryData(item));
}
try { return b.ToString().Substring(1); }
catch (Exception e)
{
log.Error(e.Message);
return e.Message;
}
}
Depending on the type of the object passed inside the Dictionary, it should either create a string when a string is passed or call itself when another Dictionary is passed.
Thanks in advance for your expertise
Upvotes: 1
Views: 218
Reputation: 44026
You could make it more fancy by creating a method that flattens a nested dictionary:
private static IEnumerable<KeyValuePair<string, string>>
Flatten(Dictionary<string, object> dictionary)
{
if (dictionary == null) yield break;
foreach (var entry in dictionary)
{
if (entry.Value is string s)
{
yield return new KeyValuePair<string, string>(entry.Key, s);
}
else if (entry.Value is Dictionary<string, object> innerDictionary)
{
foreach (var innerEntry in Flatten(innerDictionary))
{
yield return innerEntry;
}
}
else if (entry.Value == null)
{
// Do nothing
}
else
{
throw new ArgumentException(nameof(dictionary));
}
}
}
...and then use it like this:
string queryData = String.Join("&", Flatten(myNestedDictionary)
.Select(e => e.Key + "=" + WebUtility.UrlEncode(e.Value)));
Upvotes: 1
Reputation: 9249
You have to check item.Value
instead of item
.
Furthermore I tried to improve your code a little bit by using is
instead of GetType()
and getting rid of the try-catch
here. (And why Substring(1)
?)
(Somehow I got a feeling that the suggested approach with overloading won't work that easily in this case, but I'm not sure about this.)
private string BuildQueryData(Dictionary<string, object> param)
{
if (param == null )
return "";
StringBuilder b = new StringBuilder();
foreach (var item in param)
{
if (item.Value is string s)
b.AppendFormat("&{0}={1}", item.Key, WebUtility.UrlEncode(s));
else if (item.Value is Dictionary<string, object> dict)
b.Append(BuildQueryData(dict));
}
return b.ToString();
}
Upvotes: 1