Convert a custom object to a query string I wrote an extension method that takes a custom object and converts its properties to a query string for use in a URL. You can specify what properties you want included by using a [QueryString] attribute. For example:

class Thing 
{
    [QueryString]
    public int Id {get; set;}
    [QueryString]
    public string Name {get; set;}
    public object MetaData {get; set;}
}

var thing = new Thing { Id = 1, Name = "Test", MetaData = someObj };
thing.ToQueryString(); // outputs `?Id=1&amp;Name=Test


Here's the code for the extension method:

public static string ToQueryString(this object obj)
{

    StringBuilder queryStringBuilder = new StringBuilder("?");

    Type objType = obj.GetType();
    // Get properties marked with `[QueryString]`
    List&lt;PropertyInfo&gt; props = objType.GetProperties()
        .Where(p =&gt; Attribute.IsDefined(p, typeof(QueryStringAttribute)))
        .ToList();

    foreach (var prop in props)
    {
        string name = prop.Name;
        var value = prop.GetValue(obj, null);

        if (value != null)
        {
            // Check's if this is the last property, if so, don't add an '&amp;'
            if (props.IndexOf(prop) != (props.Count - 1))
            {
                queryStringBuilder.Append($"{Uri.EscapeDataString(name)}={Uri.EscapeDataString(value.ToString())}&amp;");
            }
            else
            {
                queryStringBuilder.Append($"{Uri.EscapeDataString(name)}={Uri.EscapeDataString(value.ToString())}");
            }
        }
    }

    return queryStringBuilder.ToString();
}


The code works just fine, but it seems a bit messy to me. Specifically, checking if we are on the last property seems a bit messy, because we end up doing the same thing, just nixing one character. Is there a way to make that a little cleaner? Are there any other way's this method could be simplified?
I wouldn't go the StringBuilder route, simply because you need to handle the "what if I'm at the start/end" problem. Instead, simply collect the "URL_translated" key-value pairs into an IEnumerable&lt;string&gt; and then apply string.join().

If you're working in .NET Core, Microsoft does all the lifting for you. Here's how they do it.