Stream and XmlTextwriter.... Request is not received correctly - c#

Im stuck on this httpWebRequest problem. I need to send XML to a website. But I keep getting negative responses on my request. I saw some code examples where the ContentLength was set... And that might be the issue but I don't know....
The XML written in writePaymentRequest(...) is exactly as the website needs it to be, because they got my xml markup and they succeeded, in another programming language though. The result only contains their error instead of the information I'm supposed to be receiving.
I can't set the contentlength because I don't know the length when I create the writer with the requeststream in it.
HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("https://some.website.com");
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
using (writer = new XmlTextWriter(httpWebRequest.GetRequestStream(), System.Text.Encoding.UTF8))
{
writePaymentRequest(writer, registrant, amount, signature, ipaddress);
}
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream());
String stringResult = streamReader.ReadToEnd();
streamReader.Close();

You would know the length if you wrote the XmlTextWriter to something like a MemoryStream first. From there, you could get the bytes, set the httpWebRequest.ContentLength to the length of the byte array, and then write the byte array to your request
edit
The middle of your code would look something like this (I think):
MemoryStream ms = new MemoryStream();
using (writer = new XmlTextWriter(ms, System.Text.Encoding.UTF8))
{
writePaymentRequest(writer, registrant, amount, signature, ipaddress);
}
byte[] bytes = ms.ToArray();
ms.Close();
httpWebRequest.GetRequestStream().Write(bytes, 0, bytes.Length);
httpWebRequest.ContentLength = bytes.Length;
edit #2
Instead of XmlTextWriter(ms, System.Text.Encoding.UTF8), try XmlTextWriter(ms, new UTF8Encoding(false)) to see if that fixes the encoding issue

Related

How to use streamReader(or similar) for a HttpWebResponse stream

I am currently trying to retrieve a xml response and parse the result from a web service, but I have ran into issues when receiving the response as a stream and using stream reader to read the result and convert the xml response to a string so it can be parsed to get a result later.
When testing I receive an error that there is illegal characters in path, as the stream reader only accepts a file path not the actual xml response object itself. After extensive searching most of the similar posts on here, most people point to either textreaders or xmlreaders but as the HttpWebResponse returns a stream I can't use those. Does anyone have a idea's or pointers to help me overcome this?
I have included a snippet of the code to how I am handling the response.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader responseStream = new StreamReader(response.GetResponseStream());
string soapResult = responseStream.ReadToEnd();
Here is the code for the request, just in case it helps.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Location);
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] bytesToWrite = encoding.GetBytes(xml.ToString());
request.Method = "POST";
request.ContentLength = bytesToWrite.Length;
request.ContentType = "application/soap+xml; charset=UTF-8";
Stream newStream = request.GetRequestStream();
newStream.Write(bytesToWrite, 0, bytesToWrite.Length);
newStream.Close();
Thanks

Debugging an HttpWebResponse

This is being done on a Windows Forms App. I've spent a ton of time stepping through this code with the debugger. What I've found are the following things and they all seem to be at this line:
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
1. If I include
request.SendChunked = true;
I get this error at the response line previously stated:
'System.Net.WebException: The remote server returned an error: (415) Unsupported Media Type.
2. If I comment out the code in #1, I receive this error at that main response line that I mentioned in the beginning:
'System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly.
3. If I go with route #1, the "Connection" of the request remains as "KeepAlive" all the way through. But if I go with route #2, the "Connection" of the request changes to "null" at the response line that I mentioned in the beginning.
private void HttpPost()
{
HttpWebRequest request = null;
Uri uri = new Uri("https://post.craigslist.org/bulk-rss/post");
request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
XmlDocument doc = new XmlDocument();
doc.Load("XMLFile1.xml");
//request.ContentLength = doc.InnerXml.Length;
request.SendChunked = true;
using (Stream writeStream = request.GetRequestStream())
{
UTF8Encoding encoding = new UTF8Encoding();
byte[] bytes = encoding.GetBytes(doc.InnerXml);
//request.ContentLength = bytes.Length;
writeStream.Write(bytes, 0, bytes.Length);
}
string result = string.Empty;
request.ProtocolVersion = System.Net.HttpVersion.Version11;
request.KeepAlive = false;
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
using (System.IO.StreamReader readStream = new System.IO.StreamReader(responseStream, Encoding.UTF8))
{
result = readStream.ReadToEnd();
}
}
}
}
catch (Exception e)
{
string innerException = String.Format("Inner exception: '{0}'", e.Data);
string exceptionCause = String.Format("An error occurred: '{0}'", e);
System.IO.File.WriteAllText(#"C:\Users\Nathan\Documents\DebugOutputFile\exception.txt", exceptionCause);
System.IO.File.WriteAllText(#"C:\Users\Nathan\Documents\DebugOutputFile\innerException.txt", innerException);
}
}
I feel like these things are adding up towards a solution, but I could really use some guidance.
Option 1: Change your content type to match the body encoding
request.ContentType = "application/xml";
Option 2: Change your body encoding to match the specified content-type
If your server expects only "application/x-www-form-urlencoded", then you need to change your body encoding to suit it, for example, like this:
using (Stream writeStream = request.GetRequestStream())
{
UTF8Encoding encoding = new UTF8Encoding();
string response = String.Concat("arg=", HttpUtility.UrlEncode(doc.InnerXml))
byte[] bytes = encoding.GetBytes(doc.InnerXml);
//request.ContentLength = bytes.Length;
writeStream.Write(bytes, 0, bytes.Length);
}
You need to know the parameter name (above was set to "arg") and add a reference to System.Web, if you haven't.
See following XML...
<?xml version="1.0" encoding="UTF-8"?><test></test>
and encoded string for reference (your request body should look similar to this):
arg=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Ctest%3E%3C%2Ftest%3E
Explanation
If you look at the response you are getting with the first approach: 415 - Unsupported Media Type, you can notice that the content type you are specifying ("application/x-www-form-urlencoded") doesn't match what you are sending in the body (an XML document). Chunk encoding should be enabled when sending files.
Note
When you are having trouble with a request done in source code, try to test the request alone with a web debugging tool, like Fiddler. There you would compose and issue the request until you get the response you want. Then you can compare that with what you are sending from source code (again you should use the same tool for inspecting your request).

posting data to PHP from C#

HI I have been trying to post data to PHP webservice(3rd party) from my C# code.
The PHP webservice says it expects a parameter c (missing parameter c is the error I get).
I am using JSON to send the data, but i do not understand how do give the parameter. Would be great if some one could throw light on this.The following is my code:
DropYa d = new DropYa();
List<DropYaUser> d1 = new List<DropYaUser>();
DropYaUser ds = new DropYaUser();
ds.action = "create";
ds.groupid = 10;
ds.name = "Test";
ds.manager_key = "test";
d1.Add(ds);
WebRequest request = WebRequest.Create(" http://dev.dropya.net/api/Group.php");
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
JavaScriptSerializer ser = new JavaScriptSerializer();//typeof(DropYaUser));
string postData = ser.Serialize(ds);
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/json";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
Console.Write("Wrote");
Console.Read();
// Get the response.
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
Console.Read();
dataStream = response.GetResponseStream();
Console.Read();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
Console.Read();
response.Close();
Any post request is going to be read as a data stream. The field names and values for a posted form will appear in the stream in a form like "c=ABC&d=123", where 'c' and 'd' are form fields. Of course you can post without any form field names but in this case it is expecting 'c'. What you'll want to do is prepend "c=" to the data you're posting. Perhaps modify your GetBytes line like so:
byte[] byteArray = Encoding.UTF8.GetBytes("c=" + postData);

http response returning webpage

Excuse any ignorance on my part with this methodology as it is somewhat new to me. I've been reading up on it as much as I can, but haven't been able to solve this yet.
I'm trying to accomplish a SSO with a vendor through an http post. Simple enough. I've done this in the past, but it usually returns a url that I can then redirect the user to. Unfortunately, with this vendor they are returning the entire page, html and all. Is this typical? If so, is my only solution to post this to a new window?
For reference, here's my code so far:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(link);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
byte[] postBytes = Encoding.UTF8.GetBytes(postString);
request.ContentLength = postBytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseStream = response.GetResponseStream();
var responseReader = new StreamReader(responseStream);
var responseString = responseReader.ReadToEnd();
responseReader.Close();
responseStream.Close();
response.Close();
Does everything look normal and ok so far?
It is normal for a POST request to return a new web page. I would think the redirect would be the abnormal case.
You're pretty vague about your app, so I'm not sure how you'll want to get the returned html shown to the user.
You might want to check out the WebClient class which could simplify your code considerably.
using (var client = new WebClient())
{
var resultBytes = client.UploadData(new Uri("http://example.com"), "POST", data);
}

Translating COM objects (or possibly XMLHTTP) in Coldfusion to C#

I've been converting a bunch of files from Coldfusion to C#, and all has been going swimmingly until now. I'm pretty much learning ColdFusion as I go, and I barely ever write in C# so I'm stuck here. Can anybody help explain how I would go about translating this chunk of code into C#?
<cfobject type="COM" action="Create" name="objServerXMLHttp" class="msxml2.ServerXMLHTTP.3.0">
<cfset objServerXMLHttp.open("POST", "http://URL", True , "Me.User", "Me.Password")>
<cfset objServerXMLHttp.setRequestHeader("Content-Type", "text/xml")>
<cfset objServerXMLHttp.setRequestHeader("charset", "utf-8")>
<cfset objServerXMLHttp.send("#XMLRequest#")>
<cfset thread = CreateObject("java", "java.lang.Thread")>
For some background, I'm basically just taking info from a database, surrounding it with XML tags in a string, creating an XML file out of the string, and now here I am.
The direct translation is easy in C# 4.0 (VS2010) with the dynamic keyword:
dynamic objServerXMLHttp = Activator.CreateInstance(Type.GetTypeFromProgID("msxml2.ServerXMLHTTP.3.0"));
objServerXMLHttp.open("POST", "http://chrdevweb:8080/mellibase/webservice/rest", true, "Me.User", "Me.Password");
objServerXMLHttp.setRequestHeader("Content-Type", "text/xml");
objServerXMLHttp.setRequestHeader("charset", "utf-8");
objServerXMLHttp.send("#XMLRequest#");
So just to break it down as to what this coldfusion code is doing (which you probably know anyway):
It is instantiating an object type msxml2.ServerXMLHTTP in memory.
It is then using that object to construct an XML document.
It is then sending that (via HTTP POST) to the URL: http://chrdevweb:8080/mellibase/webservice/rest
And lastly, it seems to instantiate a java object (not sure its related).
So in asp.net using c#, the post code would like so:
HttpWebRequest request=null;
Uri uri = new Uri(url);
request = (HttpWebRequest) WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postData.Length;
using(Stream writeStream = request.GetRequestStream())
{
UTF8Encoding encoding = new UTF8Encoding();
byte[] bytes = encoding.GetBytes(postData);
writeStream.Write(bytes, 0, bytes.Length);
}
string result=string.Empty;
using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader readStream = new StreamReader (responseStream, Encoding.UTF8))
{
result = readStream.ReadToEnd();
}
}
}
The result variable in the end would hold your response. The 'url' is the url you are posting to, and 'postData' is your xml string.
To construct the XML doc, you can use XMLdocument in c#, or you can just put a string together.
PS: this is untested, so there may be a syntax error somewhere :)

Categories