Search code examples
c#special-charactersrequest.querystring

Plus sign in query string for ASP.NET site


I few years ago I created a database driven ASP.NET site, which uses a single APSX page to display all site pages. So all the URLs of the site are in the following format:

/main.aspx?page=Page+Title+One

/main.aspx?page=Another+Article+Title

/main.aspx?page=Third+Page

The main.aspx page gets the query string data (Page+Title+One for example) and uses it as a key to pull the appropriate article content from the SQL server database. The actual title of the page is stored in the db with spaces instead of pluses (for example "Page Title One").

The poor decision to go with the + sign as a word separator in the URL query string is causing lots of issues with search engines lately (duplicate content, etc.), so I want to fix it, but without changing URLs.

What I want to do is when search engine or visitor tries to visit the wrong URL missing the + signs and having white spaces instead, for example:

/main.aspx?page=Page Title One

I want to do 301 permanent redirect to:

/main.aspx?page=Page+Title+One

To be able to do this I need to check if the query string value has pluses or white spaces, however when I get the value with Request.QueryString["page"] even if the actual quesry string has pluses in it I still get string with white spaces "Page Title One".

The site runs on IIS6/Win 2003.

How can I do this?


Solution

  • Well, of course you can't put a space in a URI in any case. What you can do is put %20 in which is the way to encode a space at any point in a URI as well as + being the normal way to encode a space in the query portion, and the recommended way to do so in that portion of it because %20 can cause problems.

    Because of this is an implementaiton detail application/x-www-form-urlencoded and we normally care about the actual data sent, Request.QueryString[] does the unescaping for you, turning both + and %20 into a space.

    You want to look at the Request.RawUrl (returns a string) or Request.Url which returns a Uri. Probably the easiest is to feed Request.Url into a UriBuilder so you can change just the query and get a Uri back.

    Still, I'd recommend the opposite approach, if you're having issues with duplicate content due to the two possible ways of encoding a space in the query string, go with the recommended norm and turn the cases of %20 into + rather than the other way around.

    var u = Request.Url;
    if(u.Query.Contains("%20"))
    {
        var ub = new UriBuilder(u);
        Console.WriteLine(ub.Query);
        string query = ub.Query;
        //note bug in Query property - it includes ? in get and expects it not to be there on set
        ub.Query = ub.Query.Replace("%20", "+").Substring(1);
        Response.StatusCode = 301;
        Response.RedirectLocation = ub.Uri.AbsoluteUri;
        Response.End();
    }