Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

QueryBuilder: A Simple Way to Read and Write Query Strings

0.00/5 (No votes)
11 Feb 2015 1  
A simple tutorial to create a pair of classes that enable you, through the use of objects, to read and write query strings in any context

Introduction

In this tip, we will be writing a utility that can read and write URL query strings. It's very basic in functionality but makes reading, editing, writing, and accessing values in a query string very straightforward.

Using this class, you will not have to bother yourself with adding the separating characters between and within parameters. It can also accept a raw query string and parse its segments into objects that contain properties to easily access and set the values.

Using the Code

First, we will create two classes: a QueryBuilder class, and a QueryParameter class. The QueryBuilder class houses a list of QueryParameters and allows you to access each one by its name or index.

To start, you should add using statements to your files to import the necessary namespaces which will look as follows:

C#
using System.Collections.Generic;
using System.Linq;

Creating the Classes

Now, create the QueryBuilder class and the QueryParameter class and add to the QueryBuilder class a global variable of type List<QueryParameter>. Then define a default public constructor that sets the global variable to a new empty List. This is necessary to prevent errors when adding items to the list.

C#
public class QueryBuilder
{
    private List<QueryParameter> _parameters;

    public QueryBuilder () { _parameters = new List<QueryParameter>(); }
}

In the QueryParameter class, add two public properties, one for the name of the parameter and one for the value. After this, add two constructors to the class, a constructor that accepts a name and value as parameters and one that accepts only a name. The constructor that accepts only a name will set the value to a blank string.

C#
public class QueryParameter
{
    public string Name { get; set; }
    public string Value { get; set; }

    public QueryParameter (string name, string value)
    {
        this.Name = name;
        this.Value = value;
    }

    public QueryParameter (string name) : this(name, "") { }
}

Indexers

Once these initial steps are completed, we can add indexers to the QueryBuilder class to allow access to the contained QueryParameters.

This indexer returns a QueryParameter at the specified index.

C#
public QueryParameter this[int index]
{
    get { return _parameters[index]; }
}

This indexer returns the Value of a QueryParameter that has the specified Name.

C#
public string this[string name]
{
    get
    {
        return HasParameter(name) ? _parameters.Find(p => p.Name == name).Value : null;
    }
}

You may notice it contains a method we don't yet have. We need a method like this to avoid Exceptions in the case there is no QueryParameter with the given name. Let's create it now.

C#
public bool HasParameter (string name) { return _parameters.Exists(p => p.Name == name); }

Adding and Removing QueryParameters

The next thing we need is the ability to add to add and remove QueryParameters from our QueryBuilder object. Add the following methods to achieve this:

C#
public void AddParameter (QueryParameter parameter)
{
    _parameters.Add(parameter);
}

public void AddParameter (string name, string value)
{
    AddParameter(new QueryParameter(name, value));
}

public void RemoveParameter (string name)
{
    _parameters.Remove(_parameters.Find(p => p.Name == name));
}

public void RemoveParameter (QueryParameter parameter)
{
    _parameters.Remove(parameter);
}

Parsing

We now have functioning objects that can be created, manipulated, and accessed appropriately. However, the ability to create the objects from a passed in string and the ability to write the objects to a single string are still missing. A couple more methods should handle that.

QueryParameter

Firstly, we will add a method that will create a QueryParameter object out of a string.

C#
public static QueryParameter Create (string parameter)
{
    string trimmed = parameter.Replace("&", "").Replace("?", "");
    if( trimmed.Contains("=") )
    {
        string[] split = trimmed.Split('=');
        return new QueryParameter(split[0], split[1]);
    }
    return new QueryParameter(trimmed);
}

In this method, we first remove the unnecessary characters that may have been passed in with our string. Then we check if an equal sign is inside the remaining text.

If the text does contain an equal sign, we split the parameter string into its two parts, the name being on the left of the equal sign and the value being on the right. Using our split values, we then pass them into the constructor of a new QueryParameter object and return it. If the text does not contain an equal sign, we treat it as a name with no value and we use the second constructor we created earlier, then return the object.

The reason we will make the method static is for ease of use. Its usage would look something like this:

C#
QueryParameter qp = QueryParameter.Create("name=value");
QueryBuilder

Now for reading in an entire query string. We need to add a method in QueryBuilder similar to the one we just added to QueryParameter.

C#
public static QueryBuilder Create (string queryString)
{
    QueryBuilder toReturn = new QueryBuilder();
    if( queryString.Contains('&') )
    {
        foreach( string p in queryString.Split('&') )
        {
            toReturn.AddParameter(QueryParameter.Create(p));
        }
    }
    else
    {
        toReturn.AddParameter(QueryParameter.Create(queryString));
    }
    return toReturn;
}

It's static again for the same reason as before. Let's step through what this code is doing. We first create a QueryBuilder object that we will be returning once all of the parameters have been parsed and added.
We check if the string contains an ampersand (&) because its presence would indicate that there is more than one parameter in the string. If the ampersand is there, we loop through the array created by splitting the string and create and append each parameter. If there is no ampersand, we treat the string as a single parameter and add it to the initial QueryBuilder object, then return it.

Flattening

That takes care of reading from a string now what about writing to one?

C#
private string Flatten ()
{
    return this.Name + ( string.IsNullOrEmpty(this.Value) ? "" : "=" ) + this.Value;
}

This method is one long string concatenation, starting with the name of the parameter and then we either add an equal sign or nothing depending on if the value is blank. Finally, we add the value to the end, which if it is blank will not change the string.

We left the method private because we are going to give public access to the value by overriding the ToString method like so:

C#
public override string ToString () { return this.Flatten(); }

This is the method for writing the entire query string to a string and it goes in the QueryBuilder class.

C#
private string CompileQueryString ()
{
    return "?" + string.Join("&", _parameters.Select( p => p.ToString() ).ToArray());
}

With each iteration, we append the string value of the parameter to the returning string and then return it.
We left this private for the same reason we left it private in QueryParameter and to override ToString would look something like this:

C#
public override string ToString () { return CompileQueryString(); }

Conclusion

Now, we have a functional and useful way to read and write query strings. It can be used in the context of an ASP.NET page, a Windows Forms application, or just about any other situation.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here