Safely Escaping Data Strings

by Jan 12, 2022

Typically you use methods like EscapeUriString() to safely escape string data that you want to append to URLs (as pointed out in our previous tip).

However, this can cause severe headaches because EscapeUriString() is specifically designed to escape a full URL including the domain part, not just your arguments. That’s why it can corrupt the data you want to send to someone else, i.e. a morse web service. Try for yourself and run this:

$url = "https://api.funtranslations.com/translate/morse.json?text=One&Two"

$Escaped = [Uri]::EscapeUriString($url)

$result = Invoke-RestMethod -Uri $url
$result.contents

The result reveals the issue:

 
translated text translation
---------- ---- -----------
--- -. .   One  morse   
 

Even though you sent the text “One&Two” to the webservice, it returned morse code only for the text “One”. When you look at the content of $Escaped you can see why that is:

 
PS C:\> $escaped
https://api.funtranslations.com/translate/morse.json?text=One&Two     
 

EscapeUriString() did not escape the ampersand – because the ampersand is a valid part of URLs and used to separate arguments. In essence, the webservice received two arguments, and since it only supports one, it discarded the second.

While EscapeUriString() is convenient to quickly escape full URLs, it has serious drawbacks. To work around this, always make sure you separate the base URL from your data arguments. If you do, you can use EscapeDataString() instead which makes sure that *all* special characters are correctly escaped:

$Text = 'One&Two'
$Escaped = [Uri]::EscapeDataString($Text)
$baseurl = "https://api.funtranslations.com/translate/morse.json?text="
$url = $baseurl + $Escaped

$resultok = Invoke-RestMethod -Uri $url
$resultok.contents

Now the result is correct (the webservice used for illustration does have a rate limit so if you called it too often you will need to wait for an hour to verify):

That’s because $escaped now escaped all special characters, including the ampersand:

 
PS> $escaped
One%26Two    
 

As an added benefit, you now also get the return ticket: UnescapeDataString() returns an escaped data string back to normal:

# escape special characters
$text = 'This is a text with [special] characters!'

$escaped = [Uri]::EscapeDataString($text)
$escaped

# unescape escaped strings
$unescaped = [Uri]::UnescapeDataString($escaped)
$unescaped

The result looks like this:

 
This%20is%20a%20text%20with%20%5Bspecial%5D%20characters%21
This is a text with [special] characters!    
 


Twitter This Tip! ReTweet this Tip!