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!