Search code examples
c#webrequesthttpwebresponse

How to wrap the body of a POST request in order to be able to send restricted characters


Using powershell to get the current token of a user from an external service I do not have problem:

$uri = "http://myserver/fmetoken/view"
$postParams = @{user='Myuser';password='PS78U-w&';}
$foo = Invoke-WebRequest -Uri $uri -Method Post -Body $postParams

$foo.Content

i receive the token.

if I use postman to verify it, there is no issue.

but if I want to implement the same action in c# the response is: 'The remote server returned an error: (401) Unauthorized.' when the password contains charactesrs like '&' and '='

var url = $"{fmeServerUrl}/fmetoken/view";
var body = $"user={settingsUserFme}&password={settingsPasswordFme}";

var byteArray = Encoding.UTF8.GetBytes(body);
var responseCode = 0;
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.Credentials = CredentialCache.DefaultCredentials;
request.ContentType = "application/x-www-form-urlencoded";

request.ContentLength = byteArray.Length;
var dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();

WebResponse response = request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
    responseresult = reader.ReadToEnd();
    reader.Close();
}

I already tried to use:

var bodyencoded = System.Net.WebUtility.UrlEncode(body);
var byteArray = Encoding.UTF8.GetBytes(bodyencoded);

but in this case I receive a bad request


Solution

  • If you UrlEncode the whole body, the & and = characters in the body that are meant to help with parsing are discarded, so your request would have transformed into something like this:

    user=Myuser&password=PS78U-w&
    user=Myuser%26password=PS78U-w%26 // post UrlEncode
    

    so the server just assumes you are sending a really long username instead of two different parameters.

    To avoid this, you can UrlEncode the password parameter separately, then put it into your body variable.

    var passencoded = System.Net.WebUtility.UrlEncode(pass)
    var body = $"user={settingsUserFme}&password={passencoded}";
    

    Which should have the result: user=Myuser&password=PS78U-w%26, noting that the ampersand right before password is significant and preserved.