Malformed string exception while sending "&" in Json to AppEngine - c#

I am trying to send Facebook graph link to the AppEngine server. I receive "Malformed string exception". Here is my method sending json to server:
public async Task<string> SendJSONData(string urlToCall, string JSONData)
{
// server to POST to
string url = urlToCall;
// HTTP web request
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Method = "POST";
// Write the request Asynchronously
using (var stream = await Task.Factory.FromAsync<Stream>(httpWebRequest.BeginGetRequestStream,
httpWebRequest.EndGetRequestStream, null))
{
//create some json string
string json = "action=" + JSONData;
// convert json to byte array
byte[] jsonAsBytes = Encoding.UTF8.GetBytes(json);
// Write the bytes to the stream
await stream.WriteAsync(jsonAsBytes, 0, jsonAsBytes.Length);
}
WebResponse response = await httpWebRequest.GetResponseAsync();
StreamReader requestReader = new StreamReader(response.GetResponseStream());
String webResponse = requestReader.ReadToEnd();
return webResponse; }
Here is what I sniff using Fiddler:
POST http://x.appspot.com/register HTTP/1.1
Accept: */*
Content-Length: 376
Accept-Encoding: identity
Content-Type: application/x-www-form-urlencoded
User-Agent: NativeHost
Host: x.appspot.com
Connection: Keep-Alive
Pragma: no-cache
action={
"mailFb": "mail#gmail.com",
"userName": "Michael",
"userSurname": "w00t",
"nickname": "Michael w00t",
"userSex": "male",
"userAvatar": "https://graph.facebook.com/myperfectid/picture?type=large&access_token=BlahblahblahblahToken"
}
So everything looks fine, but the problem is that i receive the following error in AppEngine log:
2013-03-02 17:52:10.431 /register 500 56ms 0kb NativeHost
W 2013-03-02 17:52:10.427 /register com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Unterminated string at line 7 column 79 at com.google.g
C 2013-03-02 17:52:10.429 Uncaught exception from servlet com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Unterminated string at line 7 colu
I managed to narrow the problem to its source, which is "&" character. So my question is, how to fix the code, so that it works with AppEngine.
Oh, here is how i read the received data on the server:
gson.fromJson(reader, User.class);

The problem is highlighted by the fact you're claiming you are sending "Content-Type: application/x-www-form-urlencoded"
But it isn't. Hence the error.
The correct encoding for & is &.

Related

Empty answer from webclient C#

I'm trying to receive data from compressor, but it's answer is always empty. Here is my code:
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.ContentType]= "application/x-www-form-urlencoded";
string question = "online_pressure";
string URL = "http://10.0.163.51/getVar.cgi";
string answer = client.UploadString(URL, "POST", question);
Console.WriteLine(answer);
When I use this code for another compressor, which different only 2 strings, it works great and I can see answer in console:
string question = "QUESTION=300201";
string URL = "http://10.0.163.50/cgi-bin/mkv.cgi";
Code in VBS works great for both compressors. I can see answer in MsgBox from first and second compressors:
Dim objHTTP
strToSend = "online_pressure"
Set objHTTP = CreateObject("Microsoft.XMLHTTP")
Call objHTTP.Open("POST", "http://10.0.163.51/getVar.cgi", false)
objHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
objHTTP.Send strToSend
MsgBox(objHTTP.ResponseText)
HttpRequest code works just for second compressor too:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
StreamWriter requestWriter = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
requestWriter.Write(data);
requestWriter.Close();
try
{
// get the response
WebResponse webResponse = request.GetResponse();
Stream webStream = webResponse.GetResponseStream();
StreamReader responseReader = new StreamReader(webStream);
string response = responseReader.ReadToEnd();
responseReader.Close();
Console.WriteLine(response);
}
catch (WebException we)
{
string webExceptionMessage = we.Message;
}
What I can try else to get data from first compressor in C#?
I compared the three requests in Fiddler 4 and realized that the only difference (apart from some other headers which won't affect behavior) between vbs script and both WebClient
and HttpWebRequest is that, managed API's send the Expect: 100-continue header and vbs script does not.
This can be the issue if the software running on the compressor device does not support this.
Please try the following, which tells the HttpWebRequest to not send this header:
For the HttpWebRequest, you can simply prevent sending this by:
request.ServicePoint.Expect100Continue = false;
Note: For the WebClient, the assignment requires accessing to the HttpWebRequest object used internally, but this has "protected" access modifier and can be worked around.
Before setting this value:
POST http://oguzozgul.com.tr/getVar.cgi HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: oguzozgul.com.tr
Content-Length: 15
Expect: 100-continue
Connection: Keep-Alive
online_pressure
After setting this value:
POST http://oguzozgul.com.tr/getVar.cgi HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: oguzozgul.com.tr
Content-Length: 15
Connection: Keep-Alive
online_pressure
I also want to put the vb script request here so you can see other differences as well. The Accept-Encoding and some other headers are also not sent by default:
POST http://oguzozgul.com.tr/getVar.cgi HTTP/1.1
Accept: */*
Content-Type: application/x-www-form-urlencoded
Accept-Language: tr,en-US;q=0.8,en-GB;q=0.7,en;q=0.5,zh-Hans-CN;q=0.3,zh-Hans;q=0.2
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Win64; x64; Trident/7.0; .NET4.0E; .NET4.0C; Tablet PC 2.0; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; wbx 1.0.0; Zoom 3.6.0; wbxapp 1.0.0)
Host: oguzozgul.com.tr
Content-Length: 15
Connection: Keep-Alive
Pragma: no-cache
online_pressure
WebClient and HttpWebRequest still do not works with this comressor. I tried to add any headers, but no result.
I tried PowerShell and it returns empty response too:
Invoke-WebRequest -Uri http://10.0.163.51/getVar.cgi -Method POST -Body "package_discharge_pressure" -ContentType "application/x-www-form-urlencoded"
Curl not working too, it hangs without errors
curl -i -X POST -H "Content-Type:application/x-www-form-urlencoded" -d "sump_pressure" http://10.0.163.51/getVar.cgi
Javascript and VBS works good. And today I found c# code wich works too
WinHttpRequest req = new WinHttpRequest();
try {
req.Open("POST", "http://10.0.163.51/getVar.cgi", true);
req.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.Send("sump_pressure");
req.WaitForResponse();
}
catch(Exception ex) {
Console.WriteLine("Error : " + ex.Message.Trim());
}
Console.WriteLine(req.ResponseText);
In visual studio need to make reference to WinHttp

How to read http response of multi-part stream in c#

I need to receive response from a http server using c#.The response is a multi-part stream; the header would contain
Content-Type: multipart/x-mixed-replace; boundary=userdata
The body of response would be similar to below:
--userdata
Content-type: text/plain
Content-length: <length-of-content>
UserId: <user-Id>
ParentId: <parent-Id>
ParentName: <parent-name>
Time: <time>
--userdata
Content-type: text/plain
Content-length: <length-of-content>
UserId: <user-Id>
ParentId: <parent-Id>
ParentName: <parent-name>
Time: <time>
I need to recieve the response and save these information continuously in
List<UserData>
which contains the list of UserData class having information of user.
Http response url is like
http://username:password#userIp:port-number/transactionStream
I have written following code but no result, Please help:
NetworkCredential networkCredential = new NetworkCredential(this.UserName, this.Password);
string requestingURL = "http://" + this.UserName + ":" + this.Password + "#" +this.UserIp+ ":" + this.PortNo + "/transactionDataStream";
Uri uri = new Uri(requestingURL);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Credentials = networkCredential;
HttpWebResponse Answer = (HttpWebResponse)request.GetResponse();
Stream aStream = Answer.GetResponseStream();
StreamReader aStreamReader = new StreamReader(aStream);
string response = aStreamReader.ReadToEnd();
I've used this before and it works well. StreamingMultipartFormDataParser
The Http Multipart Parser does it exactly what it claims on the tin: parses multipart/form-data. This particular parser is well suited to parsing large data from streams as it doesn't attempt to read the entire stream at once and produces a set of streams for file data.

.NET SOAP request returns "400 Bad Request"

I am trying to create a simple XML SOAP request to a web service.
The service itself is proven to be OK, I accessed it by using WSDL-generated class without any problems. But if I try to access it using regular WebRequest - it always returns 400 Bad Request.
Here's my code:
class Program
{
static void Main(string[] args)
{
HttpWebRequest request = CreateWebRequest("http://localhost:8000/ExchangeService", "WhoAmI");
XmlDocument SoapEnvelopeXml = new XmlDocument();
SoapEnvelopeXml.LoadXml(
#"<?xml version=""1.0""?>
<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope""
xmlns:tem=""http://tempuri.org"">
<soapenv:Header/>
<soapenv:Body>
<tem:WhoAmI/></soapenv:Body></soapenv:Envelope>");
using (Stream stream = request.GetRequestStream())
{
SoapEnvelopeXml.Save(stream);
}
using (WebResponse response = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
string soapResult = rd.ReadToEnd();
Console.WriteLine(soapResult);
}
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
public static HttpWebRequest CreateWebRequest(string url, string soapAction)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.ContentType = "text/xml;charset=UTF-8;action=\"" + soapAction + "\"";
webRequest.Method = "POST";
return webRequest;
}
}
The XML is generated by SoapUI and works there perfectly. Here is the SoapUI's HTTP header:
POST http://localhost:8000/ExchangeService HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "http://tempuri.org/IExchangeFunctions/WhoAmI"
Content-Length: 211
Host: localhost:8000
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
What am I doing wrong?
UPD: changed the service from my to some third-party:
http://wsf.cdyne.com/WeatherWS/Weather.asmx
Through WSDL - it works. SoapUI returns data. From my code - Internal Error 500.
Try remove carriage return from soap message
.Replace("\r\n", "");
If not work verify the http request sended with fiddler, to me it was very helpful.

.NET C# using HTTPrequest similar to Curl script

I´m using .NET C# and want to use HTTPrequest to make a POST in the same way as it is written in Curl:
curl
--header ’Accept: text/html’
--user ’test1:password’
--Form ’wait=0’
--Form ’data=#data.csv;type=text/csv’
some URL address here
I´m getting Error 500 Internal error from the Internet server.
The data to be send is a CSV file.
My source code in C#:
string data = "Time, A, B\n20120101, 100, 24\n20120102\n, 101, 27";
// Create a request using a URL that can receive a post.
request = WebRequest.Create(url);
//Set authorization
request.Credentials = new NetworkCredential(username, password);
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(data);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the original response.
WebResponse response = request.GetResponse();
this.Status = ((HttpWebResponse)response).StatusDescription;
// Get the stream containing all content returned by the requested server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content fully up to the end.
string responseFromServer = reader.ReadToEnd();
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
What am I doing wrong?
cURL uses the multipart/form-data content type to create its requests. I think this is required in your case as you are passing both a text parameter and a file. Sadly the .Net framework does not appear to have built in support for creating this content type.
There is a question on SO that gives example code for how to do it yourself here: Multipart forms from C# client
For reference the HTTP request generated by that cURL command looks something like this:
POST http://www.example.com/example HTTP/1.1
Authorization: Basic J3Rlc3Q6cGFzc3dvcmQn
User-Agent: curl/7.33.0
Host: www.example.com
Accept: text/html
Connection: Keep-Alive
Content-Length: 335
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------99aa46d554951aa6
--------------------------99aa46d554951aa6
Content-Disposition: form-data; name="'wait"
0'
--------------------------99aa46d554951aa6
Content-Disposition: form-data; name="'data"; filename="data.csv"
Content-Type: text/csv'
Time, A, B\n20120101, 100, 24\n20120102\n, 101, 27
--------------------------99aa46d554951aa6--
Doesn't data need to be URL encoded for a form post? http://en.wikipedia.org/wiki/POST_%28HTTP%29#Use_for_submitting_web_forms

Web Service always return empty plain/text

Has been using Service Reference without any success:
Web service return only XML
Now I am using the raw SOAP message to do it:
XmlDocument doc = new XmlDocument();
doc.Load("Service.xml");
// create the request to your URL
Uri wsHost = new Uri("http://www.rrr.net/services/Connect");
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(wsHost);
// add the headers
// the SOAPACtion determines what action the web service should use
request.Headers.Add("SOAPAction", "act");
// set the request type
request.ContentType = "text/xml;charset=\"utf-8\"";
request.Accept = "text/xml";
request.Method = "POST";
// add our body to the request
Stream stream = request.GetRequestStream();
doc.Save(stream);
stream.Close();
// get the response back
using( HttpWebResponse response = (HttpWebResponse)request.GetResponse() )
{
Stream dataStream = response.GetResponseStream();
StreamReader dataReader = new StreamReader(dataStream);
// Use Linq to read the xml response
using (XmlReader reader = XmlReader.Create(dataStream))
{
The post is correct, but response always give me text/plain empty result, the reponse header:
Headers = {Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/plain
Date: Thu, 06 Sep 2012 15:59:28 GMT
}
The SOAP message is, act is the function:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webService">
<soapenv:Header/>
<soapenv:Body>
<web:act>
<web:d1>1</web:d1>
<web:d2>14</web:d2>
</web:act>
</soapenv:Body>
</soapenv:Envelope>
I use SoapUI, below is the raw request from SoapUI, it return a xml result:
POST http://www.rrr.net/services/Connect HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: ""
Content-Length: 516
Host: www.rrr.net
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
Thank you.
SOAP webservices require action/method to be specified (and NOT empty). If you don't know which action you want you can look at webservice WSDL by invoking the webservice with queryString "?WSDL". I.e. www.yourSite.com/your/Web/Service/URL?WSDL
You must specify an action in both the request and also the service interface. You can set the action value on the interface member using the attributes shown below and then in the request using the method you have used but by specifying the action name you used in the contract:
The attributes on the interface member
[OperationContract Name="YourActionName"]
[WebInvoke (Method = "POST", UriTemplate = "YourActionName")]
Message YourServiceFunction();
One method of specifying the action on the message
Message inputMessage = Message.CreateMessage (MessageVersion.Soap, "YourActionName", reader);

Categories