How do I serialize an object into query-string format?
I'm 99% sure there's no built-in utility method for this. It's not a very common task, since a web server doesn't typically respond with a URLEncoded key/value string.
How do you feel about mixing reflection and LINQ? This works:
var foo = new EditListItemActionModel() { Id = 1, State = 26, Prefix = "f", Index = "oo", ParentID = null};var properties = from p in foo.GetType().GetProperties() where p.GetValue(foo, null) != null select p.Name + "=" + HttpUtility.UrlEncode(p.GetValue(foo, null).ToString());// queryString will be set to "Id=1&State=26&Prefix=f&Index=oo" string queryString = String.Join("&", properties.ToArray());
Update:
To write a method that returns the QueryString representation of any 1-deep object, you could do this:
public string GetQueryString(object obj) { var properties = from p in obj.GetType().GetProperties() where p.GetValue(obj, null) != null select p.Name + "=" + HttpUtility.UrlEncode(p.GetValue(obj, null).ToString()); return String.Join("&", properties.ToArray());}// Usage:string queryString = GetQueryString(foo);
You could also make it an extension method without much additional work
public static class ExtensionMethods { public static string GetQueryString(this object obj) { var properties = from p in obj.GetType().GetProperties() where p.GetValue(obj, null) != null select p.Name + "=" + HttpUtility.UrlEncode(p.GetValue(obj, null).ToString()); return String.Join("&", properties.ToArray()); }}// Usage:string queryString = foo.GetQueryString();
Building on the good ideas from other comments, I have made a generic extension method .ToQueryString(), which can be used on any object.
public static class UrlHelpers{ public static string ToQueryString(this object request, string separator = ",") { if (request == null) throw new ArgumentNullException("request"); // Get all properties on the object var properties = request.GetType().GetProperties() .Where(x => x.CanRead) .Where(x => x.GetValue(request, null) != null) .ToDictionary(x => x.Name, x => x.GetValue(request, null)); // Get names for all IEnumerable properties (excl. string) var propertyNames = properties .Where(x => !(x.Value is string) && x.Value is IEnumerable) .Select(x => x.Key) .ToList(); // Concat all IEnumerable properties into a comma separated string foreach (var key in propertyNames) { var valueType = properties[key].GetType(); var valueElemType = valueType.IsGenericType ? valueType.GetGenericArguments()[0] : valueType.GetElementType(); if (valueElemType.IsPrimitive || valueElemType == typeof (string)) { var enumerable = properties[key] as IEnumerable; properties[key] = string.Join(separator, enumerable.Cast<object>()); } } // Concat all key/value pairs into a string separated by ampersand return string.Join("&", properties .Select(x => string.Concat( Uri.EscapeDataString(x.Key), "=", Uri.EscapeDataString(x.Value.ToString())))); }}
It will also work for objects that have properties of the type Array and generic Lists if they only contain primitives or strings.
Try it out, comments are welcome: Serialize object into a query string with Reflection
Using Json.Net
it would be much easier, by serializing and then deserializing to key value pairs.
Here is a code example:
using Newtonsoft.Json;using System.Web;string ObjToQueryString(object obj){ var step1 = JsonConvert.SerializeObject(obj); var step2 = JsonConvert.DeserializeObject<IDictionary<string, string>>(step1); var step3 = step2.Select(x => HttpUtility.UrlEncode(x.Key) + "=" + HttpUtility.UrlEncode(x.Value)); return string.Join("&", step3);}