Friday, April 24, 2009

Asp.Net Server.UrlEncode doesn't work if performed once


I have found one interesting thing about UrlEncode when I was working on a project.

In many page requests we were passing sensitive query string parameters. As these were sensitive we were encrypting them using some encrypting algorithm. That algorithm was producing non numeric characters (Ex:'/', '&', '=','?',...) which are recognized by the web server. This was leading to conflicts by the web server and the application was breaking.

To Avoid this we started performing Server.UrlEncode on the encrypted string and using it in any url or querystring. On landing page we were doing Server.Decode and then decrypting the resulted string. Please see the blow code for better understanding.

Server.UrlEncode(Utility.Encrypt("sensitive data"));
Utility.Decrypt(Server.UrlDecode("url encoded and encrypted sensitive data"));

But this didn't help us. Even though we did url encoding we were not seeing the url encoded url in the browser. And due to this the application was breaking. After this we did a long research and tried all combinations but nothing helped.

Finally we got the solution. The solution is we need to perform the url encoding twice and url decoding once. That's how it was working perfectly. We changed the code accordingly in the entire project and we didn't see any issue. The final fix for this problem is shown below.

Server.UrlEncode(Server.UrlEncode(Utility.Encrypt("sensitive data"))); //Encode twice
Utility.Decrypt(Server.UrlDecode("url encoded and encrypted sensitive data")); //Decode once


int CustomerID;
string CustomerIDEncrypyted = Utility.Encrypt(CustomerID.ToString());
string CustomerIDEncoded = Server.UrlEncode(Server.UrlEncode(CustomerIDEncrypyted));
string url = string.Format("Customer.aspx?CID={0}", CustomerIDEncoded );
anchorNext.Href = url;

//PageLoad event code in Customer.aspx.cs page

protected void Page_Load(object sender, EventArgs e)
string CustomerIDEncoded = Request.QueryString["CID"];
string CustomerIDDecoded = Server.Decode(CustomerIDEncoded);
string CustomerIDDecrypted = Utility.Decrypt(CustomerIDDecoded);
kick it on


Anonymous said...

I can't thank you enough for writing this. My scenareo was exactly the same, encrypting a link, then it wasn't decrypting properly on the other end.

I would have never figured this out.

So now the question is, do I have to go through my code and double up on all the Server.UrlEncodes? Or does it only matter on really long strings like the encrypted url? Any thoughts?

Kiran said...

Hate to bring up this post, but it helped me understand what's going with my code. Apparently, if the URL is retreived through the API (for example, using Request.Querystring and the like), the resulting string is already UrlDecoded. Therefore for me, even if I do a UrlEncode, I was not seeing it on my other page. I have to do a double encode, and for my landing page, I had to just UrlDecode once, and my ReturnUrl will have the encoded string. And when I called for ReturnUrl on another page, it will be decoded automatically.