I am writing a service in C# .NET that takes some data, generates an XML string, and posts it to a webservice.
I have that working properly, but now I want to base64encode the XML string on the C# end and decode it in PHP on the webservice side.
Something is going wrong, because the decoding is not working as expected on the PHP side
On the PHP side I just do
$xml = trim(base64_decode($_POST['xmlpost']));
Which works fine from webservice to webservice.
Here is the C# code:
string xml = ###XMLHERE###;
WebRequest request = (HttpWebRequest)WebRequest.Create(liveURL);
//base 64 encode
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(xml);
string byteArrayEncoded = System.Convert.ToBase64String(plainTextBytes, 0, plainTextBytes.Length);
byte[] byteArray = Encoding.UTF8.GetBytes("xmlpost=" + byteArrayEncoded + "&test=1");
//send request
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
request.Method = "POST";
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
I know the XML format is correct because it works fine without encoding. What am I doing wrong?
Side note: after I fix this I am also trying to ensure that single quotes, double quotes and ampersands can be in the XML node text, if anyone can also help me with that.
The base64 encoding uses characters like +, / and = that must be escaped in the URL encoded form data. Something like this should yield better results for you.
string byteArrayEncoded = System.Convert.ToBase64String(plainTextBytes, 0, plainTextBytes.Length);
string byteArrayUrlEncoded = System.Web.HttpUtility.UrlEncode(byteArrayEncoded);
byte[] byteArray = Encoding.UTF8.GetBytes("xmlpost=" + byteArrayUrlEncoded + "&test=1");
Related
I am attempting to send XML to a URL and read the response, but the response is coming back empty every time. I think this is because its being processed Asynchronously and so the receiving code hasn't had a chance to complete by the time I read the response. In Javascrpt I would use
xmlhttp.Open("POST", url, false);
to send a request Synchronously. How can I achieve it in C#?
My code is currently
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Credentials = CredentialCache.DefaultCredentials;
objRequest.Method = "POST";
objRequest.ContentType = "text/xml";
Stream dataStream = objRequest.GetRequestStream();
byte[] bytes = new byte[UpliftJobXMLString.Length * sizeof(char)];
System.Buffer.BlockCopy(UpliftJobXMLString.ToCharArray(), 0, bytes, 0, bytes.Length);
dataStream.Write(bytes, 0, bytes.Length);
dataStream.Close();
HttpWebResponse response = (HttpWebResponse)objRequest.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(response.GetResponseStream());
string respString = System.Web.HttpUtility.HtmlDecode(sr.ReadToEnd()); //always empty
Thanks
I'm fairly certain that this is not an async issue. Have you checked what sr.ReadToEnd() returns before the HtmlDecode?
Furthermore, you should check that the server is returning what you're expecting for it to return. Check the response StatusCode and StatusDescription. If your server is throwing an internal server exception (500) or something similar, the response string you read would come up empty as the content of the response would not be sent by the server in the first place.
I don't think your problem is related to sync/async operations. Your code to convert the string to byte array
byte[] bytes = new byte[UpliftJobXMLString.Length * sizeof(char)];
System.Buffer.BlockCopy(UpliftJobXMLString.ToCharArray(), 0, bytes, 0, bytes.Length);
is similar to Unicode encoding(2 bytes per char).
See the differences among encodings
string UpliftJobXMLString = "abcĂ";
byte[] bytesASCII = Encoding.ASCII.GetBytes(UpliftJobXMLString);
byte[] bytesUTF8 = Encoding.UTF8.GetBytes(UpliftJobXMLString);
byte[] bytesUnicode = Encoding.Unicode.GetBytes(UpliftJobXMLString);
Therefore, either set the content-encoding to unicode or use another encoding. For ex;
objRequest.ContentType = "text/xml; charset=utf-8";
I'm working on a project where I have to send product information via HTTP POST in XML string to a web server. It turns out that certain product names may have a % sign in their name, such as ".05% Topical Cream". Whenever I attempt to send XML data that contained a % sign in the product name, I get an error apparently because when encoding the XML string data the percent sign caused the data to become malformed.
How can I encode and send the XML string data with % sign in product name safely?
XML Data:
<node>
<product>
<BrandName>amlodipine besylate (bulk) 100 % Powder</BrandName>
</product>
</node>
Web request code:
public string MakeWebServerRequest(string url, string data)
{
var parms = System.Web.HttpUtility.UrlEncode(data);
byte[] bytes = Encoding.UTF8.GetBytes("xml=" + parms);
string webResponse = String.Empty;
try
{
System.Web.HttpUtility.UrlEncode(data);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = bytes.Length;
using (Stream reqStream = req.GetRequestStream())
{
reqStream.WriteTimeout = 3000;
reqStream.Write(bytes, 0, bytes.Length);
reqStream.Close();
}
using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
{
using (StreamReader rdr = new StreamReader(response.GetResponseStream()))
{
webResponse = rdr.ReadToEnd();
rdr.Close();
}
response.Close();
}
}
Should I be creating the web request differently? What can I do to resolve, while maintaining the product name?
Corrected - and working now. Thanks
Thanks
You need to construct request propely. application/x-www-form-urlencoded means that each parameter is Url-encoded. In your case xml parameter must have value correctly encoded, not just blindly concatenated. Below is sample that should give you stared... hopefully you'll be able to avoid string concateneation to construct XML (and insane way of constructing string constant with queotes you have in original code):
var parameterValue = System.Web.HttpUtility.UrlEncode("<xml>" + data);
byte[] bytes = Encoding.UTF8.GetBytes("xml=" + parameterValue);
There are also plenty of samples how to correctly construct requests of this kind. I.e. C# web request with POST encoding question
I'm having issues to send POST data that includes characteres like "+" in the password field,
string postData = String.Format("username={0}&password={1}", "anyname", "+13Gt2");
I'm using HttpWebRequest and a webbrowser to see the results, and when I try to log in from my C# WinForms using HttpWebRequest to POST data to the website, it tells me that password is incorrect. (in the source code[richTexbox1] and the webBrowser1). Trying it with another account of mine, that does not contain '+' character, it lets me log in correctly (using array of bytes and writing it to the stream)
byte[] byteArray = Encoding.ASCII.GetBytes(postData); //get the data
request.Method = "POST";
request.Accept = "text/html";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream newStream = request.GetRequestStream(); //open connection
newStream.Write(byteArray, 0, byteArray.Length); // Send the data.
newStream.Close(); //this works well if user does not includes symbols
From this Question I found that HttpUtility.UrlEncode() is the solution to escape illegal characters, but I can't find out how to use it correctly, my question is, after url-encoding my POST data with urlEncode() how do I send the data to my request correctly?
This is how I've been trying for HOURS to make it work, but no luck,
First method
string urlEncoded = HttpUtility.UrlEncode(postData, ASCIIEncoding.ASCII);
//request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = urlEncoded.Length;
StreamWriter wr = new StreamWriter(request.GetRequestStream(),ASCIIEncoding.ASCII);
wr.Write(urlEncoded); //server returns for wrong password.
wr.Close();
Second method
byte[] urlEncodedArray = HttpUtility.UrlEncodeToBytes(postData,ASCIIEncoding.ASCII);
Stream newStream = request.GetRequestStream(); //open connection
newStream.Write(urlEncodedArray, 0, urlEncodedArray.Length); // Send the data.
newStream.Close(); //The server tells me the same thing..
I think I'm doing wrong on how the url-encoded must be sent to the request, I really ask for some help please, I searched through google and couldn't find more info about how to send encoded url to an HttpWebRequest.. I appreciate your time and attention, hope you can help me. Thank you.
I found my answer using Uri.EscapeDataString it exactly solved my problem, but somehow I couldn't do it with HttpUtility.UrlEncode. Stackoverflowing around, I found this question that is about urlEncode method, in msdn it documentation tells that:
Encodes a URL string.
But I know now that is wrong if used to encode POST data (#Marvin, #Polity, thanks for the correction). After discarding it, I tried the following:
string postData = String.Format("username={0}&password={1}", "anyname", Uri.EscapeDataString("+13Gt2"));
The POST data is converted into:
// **Output
string username = anyname;
string password = %2B13Gt2;
Uri.EscapeDataString in msdn says the following:
Converts a string to its escaped representation.
I think this what I was looking for, when I tried the above, I could POST correctly whenever there's data including the '+' characters in the formdata, but somehow there's much to learn about them.
This link is really helpful.
http://blogs.msdn.com/b/yangxind/archive/2006/11/09/don-t-use-net-system-uri-unescapedatastring-in-url-decoding.aspx
Thanks a lot for the answers and your time, I appreciate it very much. Regards mates.
I'd recommend you a WebClient. Will shorten your code and take care of encoding and stuff:
using (var client = new WebClient())
{
var values = new NameValueCollection
{
{ "username", "anyname" },
{ "password", "+13Gt2" },
};
var url = "http://foo.com";
var result = client.UploadValues(url, values);
}
the postdata you are sending should NOT be URL encoded! it's formdata, not the URL
string url = #"http://localhost/WebApp/AddService.asmx/Add";
string postData = "x=6&y=8";
WebRequest req = WebRequest.Create(url);
HttpWebRequest httpReq = (HttpWebRequest)req;
httpReq.Method = WebRequestMethods.Http.Post;
httpReq.ContentType = "application/x-www-form-urlencoded";
Stream s = httpReq.GetRequestStream();
StreamWriter sw = new StreamWriter(s,Encoding.ASCII);
sw.Write(postData);
sw.Close();
HttpWebResponse httpResp =
(HttpWebResponse)httpReq.GetResponse();
s = httpResp.GetResponseStream();
StreamReader sr = new StreamReader(s, Encoding.ASCII);
Console.WriteLine(sr.ReadToEnd());
This uses the System.Text.Encoding.ASCII to encode the postdata.
Hope this helps,
On the MSDN site there is an example of some C# code that shows how to make a web request with POST'ed data. Here is an excerpt of that code:
WebRequest request = WebRequest.Create ("http://www.contoso.com/PostAccepter.aspx ");
request.Method = "POST";
string postData = "This is a test that posts this string to a Web server.";
byte[] byteArray = Encoding.UTF8.GetBytes (postData); // (*)
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream ();
dataStream.Write (byteArray, 0, byteArray.Length);
dataStream.Close ();
WebResponse response = request.GetResponse ();
...more...
The line marked (*) is the line that puzzles me. Shouldn't the data be encoded using the UrlEncode method rather than UTF8? Isn't that what application/x-www-form-urlencoded implies?
The sample code is misleading, because ContentType is set to application/x-www-form-urlencoded but the actual content is plain text. application/x-www-form-urlencoded is a string like this:
name1=value1&name2=value2
The UrlEncode function is used to escape especial characters like '&' and '=' so a parser doesn't consider them as syntax. It takes a string (media type text/plain) and returns a string (media type application/x-www-form-urlencoded).
Encoding.UTF8.GetBytes is used to convert the string (media type application/x-www-form-urlencoded in our case) into an array of bytes, which is what the WebRequest API expects.
As Max Toro indicated, the examples on the MSDN site are incorrect: a correct form POST requires the data to be URL encoded; since the data in the MSDN example does not contain any characters that would be changed by encoding, they are, in a sense, already encoded.
The correct code would have a System.Web.HttpUtility.UrlEncode call on the names and values of each name/value pair before combining them into the name1=value1&name2=value2 string.
This page was helpful: http://geekswithblogs.net/rakker/archive/2006/04/21/76044.aspx
So I have this c# application that needs to ping my web server thats running linux/php stack.
I am having problems with the c# way of base 64 encoding bytes.
my c# code is like:
byte[] encbuff = System.Text.Encoding.UTF8.GetBytes("the string");
String enc = Convert.ToBase64String(encbuff);
and php side:
$data = $_REQUEST['in'];
$raw = base64_decode($data);
with larger strings 100+ chars it fails.
I think this is due to c# adding '+'s in the encoding but not sure.
any clues
You should probably URL Encode your Base64 string on the C# side before you send it.
And URL Decode it on the php side prior to base64 decoding it.
C# side
byte[] encbuff = System.Text.Encoding.UTF8.GetBytes("the string");
string enc = Convert.ToBase64String(encbuff);
string urlenc = Server.UrlEncode(enc);
and php side:
$data = $_REQUEST['in'];
$decdata = urldecode($data);
$raw = base64_decode($decdata);
Note that + is a valid character in base64 encoding, but when used in URLs it is often translated back to a space. This space may be confusing your PHP base64_decode function.
You have two approaches to solving this problem:
Use %-encoding to encode the + character before it leaves your C# application.
In your PHP application, translate space characters back to + before passing to base64_decode.
The first option is probably your better choice.
This seems to work , replacing + with %2B...
private string HTTPPost(string URL, Dictionary<string, string> FormData)
{
UTF8Encoding UTF8encoding = new UTF8Encoding();
string postData = "";
foreach (KeyValuePair<String, String> entry in FormData)
{
postData += entry.Key + "=" + entry.Value + "&";
}
postData = postData.Remove(postData.Length - 1);
//urlencode replace (+) with (%2B) so it will not be changed to space ( )
postData = postData.Replace("+", "%2B");
byte[] data = UTF8encoding.GetBytes(postData);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
Stream strm = request.GetRequestStream();
// Send the data.
strm.Write(data, 0, data.Length);
strm.Close();
WebResponse rsp = null;
// Send the data to the webserver
rsp = request.GetResponse();
StreamReader rspStream = new StreamReader(rsp.GetResponseStream());
string response = rspStream.ReadToEnd();
return response;
}
Convert.ToBase64String doesn't seem to add anything extra as far as I can see. For instance:
byte[] bytes = new byte[1000];
Console.WriteLine(Convert.ToBase64String(bytes));
The above code prints out a load of AAAAs with == at the end, which is correct.
My guess is that $data on the PHP side doesn't contain what enc did on the C# side - check them against each other.
in c#
this is a <B>long</b>string. and lets make this a3214 ad0-3214 0czcx 909340 zxci 0324#$##$%%13244513123
turns into
dGhpcyBpcyBhIDxCPmxvbmc8L2I+c3RyaW5nLiBhbmQgbGV0cyBtYWtlIHRoaXMgYTMyMTQgYWQwLTMyMTQgMGN6Y3ggOTA5MzQwIHp4Y2kgMDMyNCMkQCMkJSUxMzI0NDUxMzEyMw==
for me. and i think that + is breaking it all.
The PHP side should be:
$data = $_REQUEST['in'];
// $decdata = urldecode($data);
$raw = base64_decode($decdata);
The $_REQUEST should already be URLdecoded.