Change Single URL query string value

0 votes
asked Sep 28, 2010 by star

I have an ASP.NET page which takes a number of parameters in the query string:

search.aspx?q=123&source=WebSearch

This would display the first page of search results. Now within the rendering of that page, I want to display a set of links that allow the user to jump to different pages within the search results. I can do this simply by append &page=1 or &page=2 etc.

Where it gets complicated is that I want to preserve the input query string from the original page for every parameter except the one that I'm trying to change. There may be other parameters in the url used by other components and the value I'm trying to replace may or may not already be defined:

search.aspx?q=123&source=WebSearch&page=1&Theme=Blue

In this case to generate a link to the next page of results, I want to change page=1 to page=2 while leaving the rest of the query string unchanged.

Is there a builtin way to do this, or do I need to do all of the string parsing/recombining manually?

5 Answers

0 votes
answered Sep 28, 2010 by chris-chadwick

Use the URIBuilder Specifically the link textQuery property

I believe that does what you need.

0 votes
answered Sep 28, 2010 by josh-stodola

Using this QueryStringBuilder helper class, you can grab the current QueryString and call the Add method to change an existing key/value pair...

//before: "?id=123&page=1&sessionId=ABC"
string newQueryString = QueryString.Current.Add("page", "2");
//after: "?id=123&page=2&sessionId=ABC"
0 votes
answered Sep 28, 2010 by ahmad-mageed

You can't modify the QueryString directly as it is readonly. You will need to get the values, modify them, then put them back together. Try this:

var nameValues = HttpUtility.ParseQueryString(Request.QueryString.ToString());
nameValues.Set("page", "2");
string url = Request.Url.AbsolutePath;
string updatedQueryString = "?" + nameValues.ToString();
Response.Redirect(url + updatedQueryString);

The ParseQueryString method returns a NameValueCollection (actually it really returns a HttpValueCollection which encodes the results, as I mention in an answer to another question). You can then use the Set method to update a value. You can also use the Add method to add a new one, or Remove to remove a value. Finally, calling ToString() on the name NameValueCollection returns the name value pairs in a name1=value1&name2=value2 querystring ready format. Once you have that append it to the URL and redirect.

Alternately, you can add a new key, or modify an existing one, using the indexer:

nameValues["temp"] = "hello!"; // add "temp" if it didn't exist
nameValues["temp"] = "hello, world!"; // overwrite "temp"
nameValues.Remove("temp"); // can't remove via indexer

You may need to add a using System.Collections.Specialized; to make use of the NameValueCollection class.

0 votes
answered Sep 28, 2010 by annakata

You can do this without all the overhead of redirection (which is not inconsiderable). My personal preference is to work with a NameValueCollection which a querystring really is, but using reflection:

// reflect to readonly property 
PropertyInfo isReadOnly = typeof(System.Collections.Specialized.NameValueCollection).GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic); 

// make collection editable 
isReadOnly.SetValue(this.Request.QueryString, false, null); 

// remove 
this.Request.QueryString.Remove("foo"); 

// modify 
this.Request.QueryString.Set("bar", "123"); 

// make collection readonly again 
isReadOnly.SetValue(this.Request.QueryString, true, null); 
0 votes
answered Sep 15, 2017 by pim

This is pretty arbitrary, in .NET Core at least. And it all boils down to asp-all-route-data

Consider the following trivial example (taken from the "paginator" view model I use in virtually every project):

public class SomeViewModel 
{

    public Dictionary<string, string> NextPageLink(IQueryCollection query)
    {
        /*
         * NOTE: how you derive the "2" is fully up to you
         */
        return ParseQueryCollection(query, "page", "2");
    }

    Dictionary<string, string> ParseQueryCollection(IQueryCollection query, string replacementKey, string replacementValue)
    {
        var dict = new Dictionary<string, string>()
        {
            { replacementKey, replacementValue }
        };

        foreach (var q in query)
        {
            if (!string.Equals(q.Key, replacementKey, StringComparison.OrdinalIgnoreCase))
            {
                dict.Add(q.Key, q.Value);
            }
        }

        return dict;
    }
}

Then to use in your view, simply pass the method the current request query collection from Context.Request:

<a asp-all-route-data="@Model.NextPageLink(Context.Request.Query)">Next</a>
Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...