Update or add a querystring param/value

I was looking that the url filters http://templates.servicestack.net/docs/default-filters#url-handling
as I was wanting to add or update a querystring param.

so my url could be anything really, I just want to preserve and update/append a specific qs param

e.g.
/somepath?qs1=1&qs2=2

{{ qs | setParam("qs", someObj) | assignTo: newQs }}

I see the qs is a NetCoreQueryStringCollection which is readonly so can’t add params.
The existing filters are more for building a url from scratch.

Am I missing something already exsting for handling this use case?

The new qs and query return the Request.QueryString collection, the URL Handling filters work on strings, which you can get by calling .ToString() on the collection, e.g:

{{ qs | toString | addQueryString({ qs3: 3}) | assignTo: newQs }}
1 Like

FYI to improve the experience a bit I’ve added queryString to return Request.QueryString.ToString()

{{ queryString | addQueryString({ qs3: 3 }) }}

You can also use addItem to add an item to a collection, inc. a Dictionary to a Dictionary, a KeyValuePair to a dictionary, etc then you can use the new toQueryString filter to generate the queryString, e.g:

{{ {a:1} | addItem({b:2}) | toQueryString }}

{{ {a:1} | addItem(pair('b',2)) | toQueryString }} //pair -> KeyValuePair<string,object>

Although it’s easier in these cases to use the object expression support directly, i.e:

{{ {a:1,b:2,...moreArgs} | toQueryString }}
1 Like

Thanks. I couldn’t quite get it to work with the above so I wrote the following filter.

{{ setQueryStringParam(qs, "param", "paramVal") | assignTo: newQs }}
public QueryString setQueryStringParam(NameValueCollection queryString, string param, string value)
{
    var qs = queryString == null ? new Dictionary<string, string>() : queryString.ToDictionary();
    if(value == null) qs.Remove(param);
    else
    {
        if (qs.ContainsKey(param))
            qs[param] = value;
        else
            qs.Add(param, value);
    }
    return QueryString.Create(qs);
}

ok no worries, glad you’ve found a solution. I wanted to ensure this scenario is well supported so I’ve added a new queryDictionary filter to return the QueryString in an Object Dictionary (so it can be queried/modified as a dictionary) and added support for NameValueCollection in underlying Dictionary conversion APIs, I’ve also changed toQueryString to prefix the QueryString with a ? which different URL Handling APIs were checking for.

Anyway there’s now a lot of ways to achieve the same result which you can test by replacing the URL Handling Live preview with:

http://templates.servicestack.net/docs/default-filters?qs1=1&qs2=2#url-handling

{{ `?${qs}` | addQueryString({ qs3:3}) }}
{{ queryString | addQueryString({ qs3:3}) }}
{{ qs | toObjectDictionary | addItem({ qs3:3 }) | toQueryString }}
{{ queryDictionary | addItem({ qs3:3 }) | toQueryString }}
{{ queryDictionary | addItem(pair('qs3',3)) | toQueryString }}

Which all return the same string result:

?qs1=1&qs2=2&qs3=3
?qs1=1&qs2=2&qs3=3
?qs1=1&qs2=2&qs3=3
?qs1=1&qs2=2&qs3=3
?qs1=1&qs2=2&qs3=3

As they all return a string they can be further manipulated with the various URL handling features:

{{ queryDictionary | addItem({ qs3:3 }) | toQueryString | addQueryString({ qs4:4 }) }}
{{ queryDictionary | addItem({ qs3:3 }) | toQueryString | setQueryString({ qs1:5 }) }}
{{ queryDictionary | addItem({ qs3:3 }) | toQueryString | addHashParams({ qs4:4 }) }}
{{ queryDictionary | toQueryString | addHashParams({qs4:4}) | setHashParams({qs4:5}) }}

Which returns:

?qs1=1&qs2=2&qs3=3&qs4=4
?qs1=5&qs2=2&qs3=3
?qs1=1&qs2=2&qs3=3#qs4=4
?qs1=1&qs2=2#qs4=5
1 Like