views:

222

answers:

3

Hi All,

I want to dynamically populate a link with the URI of the current request, but set one specific query string parameter. All other querystring paramaters (if there are any) should be left untouched. And I don't know in advance what they might be.

Eg, imagine I want to build a link back to the current page, but with the querystring parameter "valueOfInterest" always set to be "wibble" (I'm doing this from the code-behind of an aspx page, .Net 3.5 in C# FWIW).

Eg, a request for either of these two:

/somepage.aspx
/somepage.aspx?valueOfInterest=sausages

would become:

/somepage.aspx?valueOfInterest=wibble

And most importantly (perhaps) a request for:

/somepage.aspx?boring=something
/somepage.aspx?boring=something&valueOfInterest=sausages

would preserve the boring params to become:

/somepage.aspx?boring=something&valueOfInterest=wibble

Caveats: I'd like to avoid string manipulation if there's something more elegant in asp.net that is more robust. However if there isn't something more elegant, so be it.

I've done (a little) homework: I found a blog post which suggested copying the request into a local HttpRequest object, but that still has a read-only collection for the querystring params. I've also had a look at using a URI object, but that doesn't seem to have a querystring

A: 

If you can't find something that exists to do it, then build a bullet-proof function to do it that is thoroughly tested and can be relied upon. If this uses string manipulation, but is efficient and fully tested, then in reality it will be little different to what you may find any way.

ck
Unfortunately I guess I might have to. I think accessing the Request querystring params so easily, made me expect that Asp.net would contain something equally rich for other URIs that can be manipulated as well as read. If it has to be roll my own then I will.
Andrew M
+1  A: 
        UriBuilder u = new UriBuilder(Request.Url);
        NameValueCollection nv = new NameValueCollection(Request.QueryString);
        nv["valueofinterest"] = "wibble";
        string newQuery = "";

        foreach (string k in nv.Keys)
        {
            newQuery += k + "=" + nv[k] + "&";
        }
        u.Query = newQuery.Substring(0,newQuery.Length-1);
        Response.Redirect(u.ToString());

that should do it

Laurence Burke
I wouldn't do that, I'd use the QueryString object to read the data in, then build the new output using String manipulation
ck
Caveats: I'd like to avoid string manipulation if there's something more elegant in asp.net that is more robust. However if there isn't something more elegant, so be it.he says he wishes to avoid string manipulation
Laurence Burke
Hi Laurence, it looks OK and I gave you an upvote, but it's a bit on the verbose side. ergunin's solution is a lot terser, and I can read VB.net OK, even if I don't use it myself.Your answer derives a new class from NameValueCollection, and then provides lots of methods to help, including one's that effectively use string manipulation (well split) to populate the NameValueCollection. This is a bit overkill compared to ergunin's which simply uses a NameValueCollection.
Andrew M
Sorry Laurence, I was planning to re-write his idea in C# and iron out any wrinkles as I went. I wasn't going to copy-pasta it (or your version) into any of my production code without fathoming it out first. (After all I wouldn't learn for next time if I just pasted it in).
Andrew M
I dont think his code would work in c# but if it does I think that the named value collection part of his code would need a nv.add("valueofinterest","wibble") if its not there otherwise I am pretty sure it will give an error
Laurence Burke
NameValueCollection nv = new NameValueCollection(Request.QueryString); if (nv.GetValues("valueofinterest") != null) nv.Set("valueofinterest", "wibble"); else nv.Add("valueofinterest", "wibble");
Laurence Burke
Didn't realize you wanted C#, revised my answer.
egrunin
Your C# example is still wrong ergunin
Laurence Burke
I've tested it, it works. See the comments added to my latest edit.
egrunin
egrunin
Um, I meant: that behavior on the part of Uri.Query is annoying, not you :)
egrunin
+2  A: 

This will work as long as [1] you have a valid URL to begin with (which seems reasonable) [2] you make sure that your new value ('sausages') is properly escaped. There's no parsing, the only string manipulation is to concatenate the parameters.

Edit

Here's the C#:

    UriBuilder u = new UriBuilder(Request.Url);
    NameValueCollection nv = new NameValueCollection(Request.QueryString);

    /* A NameValueColllection automatically makes room if this is a new
       name. You don't have to check for NULL.
     */
    nv["valueOfInterest"] = "sausages";

    /* Appending to u.Query doesn't quite work, it
       overloaded to add an extra '?' each time. Have to 
       use StringBuilder instead.
    */
    StringBuilder newQuery = new StringBuilder();
    foreach (string k in nv.Keys)
        newQuery.AppendFormat("&{0}={1}", k, nv[k]);

    u.Query = newQuery.ToString();
    Response.Redirect(u.Uri.ToString());
egrunin
would newQuery.AppendFormat("
Laurence Burke
Yes, it does leave you with a superfluous (but harmless) extra ampersand before the first parameter. You could add a conditional to remove it after the loop is done; I don't.
egrunin