I'm not aware of anything in C# to do this, but you could use jQuery to do this client-side.
var data = @Html.Raw(Json.Encode(Model));
var query = $.param(data);
UPDATE
I didn't notice that you just decided to use JSON. Of course, that's the easiest and best option if the API endpoint supports it (are there really any that don't, though?). Nevertheless, I was intrigued by how to actually serialize an object into x-www-form-urlecoded in C#, and was more than a little surprised that there's no built in way that I could find. Even with the FormUrlEncodedMediaTypeFormatter
in Web API, they side-stepped the issue by making it a read-only formatter (i.e. it can read x-www-form-urlencoded into a object, but not vice-versa). So, I wrote this kind of quick and dirty method. (Note: It uses reflection, so insert flame here, but I'm not sure how else you would achieve something like this.)
public void BuildFormUrlEncodedDataString(Type type, object obj, StringBuilder builder, string prefix = "")
{
var props = type.GetProperties();
foreach (var prop in props)
{
if (prop.CanRead)
{
if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) && prop.PropertyType.IsGenericType)
{
IEnumerable list = (IEnumerable)prop.GetValue(obj);
if (list != null)
{
var i = 0;
foreach (var item in list)
{
if (item != null)
{
prefix += string.Format("{0}[{1}].", HttpUtility.UrlEncode(prop.Name), i);
BuildFormUrlEncodedDataString(item.GetType(), item, builder, prefix);
i++;
}
}
}
}
else if (prop.PropertyType.IsPrimitive || prop.PropertyType.Equals(typeof(String)))
{
var item = prop.GetValue(obj);
if (item != null)
{
builder.AppendFormat("{0}{1}{2}={3}",
builder.Length == 0 ? string.Empty : "&",
prefix,
prop.Name,
HttpUtility.UrlEncode(item.ToString())
);
}
}
else
{
var item = prop.GetValue(obj);
if (item != null)
{
prefix += string.Format("{0}.", HttpUtility.UrlEncode(prop.Name));
BuildFormUrlEncodedDataString(item.GetType(), item, builder, prefix);
}
}
}
}
}
And you would use it like so:
var builder = new StringBuilder();
BuildFormUrlEncodedDataString(myObject.GetType(), myObject, builder)
var queryString = builder.ToString();
It's more an intellectual exercise at this point, since you no longer need it, but it was a fun diversion. Maybe it will come in handy to someone else.