UTF8 Encoded post Data causing problems windows phone - c#

I am developing windows phone app. In that i need to send a json string to the server in UTF8 encoded format. I follow the below mentioned method.
private void RequestStreamCallBack(IAsyncResult ar)
{
try
{
HttpWebRequest request = (HttpWebRequest)ar.AsyncState;
Stream postStream = request.EndGetRequestStream(ar);
string postData = "OPERATION_NAME=" + operationName + "&INPUT_DATA=" + inputData ;
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);
}
catch (Exception ex)
{
}
}
The inputData contains the JSON string. So far it worked perfectly. But now the json string has " " character or "+" character. When these characters are present the server is not giving expected response. i don't know what I'm missing.
Please help.
Thank you.

PostData when submitted in application/x-www-urlencoded format must be URL Encoded.
It's in the name.
string postData = "OPERATION_NAME=" + URLEncode(operationName)
+ "&" + "INPUT_DATA=" + URLEncode(inputData);

Related

Send and Receive 'Post' data

Wonder if someone could assist me please, what I'm trying to achieve is to send data from one site to another: So in my 'sending' site I have a page that that runs the following:
string message;
message = "DATA DATA DATA DATA!!!";
System.Net.WebRequest request = WebRequest.Create("http://clt-umbraco.test.clt.co.uk/storereceive/?data-response");
request.ContentType = "application/json";
request.Method = "POST";
request.Headers["X-Parse-Application-Id"] = "aaaaaaaaaaaaaaa";
request.Headers["X-Parse-REST-API-Key"] = "bbbbbbbbbbbbbbb";
byte[] buffer = Encoding.GetEncoding("UTF-8").GetBytes("{\"channels\": [\"\"], \"data\": { \"alert\": \" " + message + "\" } }");
string result = System.Convert.ToBase64String(buffer);
Stream reqstr = request.GetRequestStream();
reqstr.Write(buffer, 0, buffer.Length);
reqstr.Close();
WebResponse response = request.GetResponse();
//jsonString.Text = response;
reqstr = response.GetResponseStream();
StreamReader reader = new StreamReader(reqstr);
jsonString.Text = reader.ReadToEnd();
And on my receiving site/page I have the following on page load:
string[] keys = Request.Form.AllKeys;
for (int i = 0; i < keys.Length; i++)
{
Response.Write(keys[i] + ": " + Request.Form[keys[i]] + "<br>");
}
I can see that this page load event is firing but the Request.Form.Allkeys object is empty where I would hope it would contain the data from the sending page. Obviously I'm going drastically wrong somewhere....could someone help please??
Thanks,
Craig
That is because You are not posting a form, you are uploading raw data.
Set
request.ContentType="application/x-www-form-urlencoded";
And populate your post data as such:
Key1=value1&key2=value2
You should also consider encoding the values with HttpServerUtility.UrlEncode
If you still wan't to send raw data though, then at the server end, you should read the incoming data like: (instead of Request.Form[])
byte[] requestRawData = Request.BinaryRead(Request.ContentLength);

C# HttpWebRequest Content-type not Changing

In C# i need to POST some data to a web server using HTTP. I keep getting errors returned by the web server and after sniffing throught the data I dound that the problem is that thew Content-type header is still set to "text/html" and isn't getting changed to "application/json; Charset=UTF-8" as in my program. I've tried everything I can think of that might stop it getting changed, but am out of ideas.
Here is the function that is causing problems:
private string post(string uri, Dictionary<string, dynamic> parameters)
{
//Put parameters into long JSON string
string data = "{";
foreach (KeyValuePair<string, dynamic> item in parameters)
{
if (item.Value.GetType() == typeof(string))
{
data += "\r\n" + item.Key + ": " + "\"" + item.Value + "\"" + ",";
}
else if (item.Value.GetType() == typeof(int))
{
data += "\r\n" + item.Key + ": " + item.Value + ",";
}
}
data = data.TrimEnd(',');
data += "\r\n}";
//Setup web request
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(Url + uri);
wr.KeepAlive = true;
wr.ContentType = "application/json; charset=UTF-8";
wr.Method = "POST";
wr.ContentLength = data.Length;
//Ignore false certificates for testing/sniffing
wr.ServerCertificateValidationCallback = delegate { return true; };
try
{
using (Stream dataStream = wr.GetRequestStream())
{
//Send request to server
dataStream.Write(Encoding.UTF8.GetBytes(data), 0, data.Length);
}
//Get response from server
WebResponse response = wr.GetResponse();
response.Close();
}
catch (WebException e)
{
MessageBox.Show(e.Message);
}
return "";
}
The reason i'm getting problems is because the content-type stays as "text/html" regardless of what I set it as.
Thanks in advence.
As odd as this might sound, but this worked for me:
((WebRequest)httpWebRequest).ContentType = "application/json";
this changes the internal ContentType which updates the inherited one.
I am not sure why this works but I would guess it has something to do with the ContentType being an abstract property in WebRequest and there is some bug or issue in the overridden one in HttpWebRequest
A potential problem is that you're setting the content length based on the length of the string, but that's not necessarily the correct length to send. That is, you have in essence:
string data = "whatever goes here."
request.ContentLength = data.Length;
using (var s = request.GetRequestStream())
{
byte[] byteData = Encoding.UTF8.GetBytes(data);
s.Write(byteData, 0, data.Length);
}
This is going to cause a problem if encoding your string to UTF-8 results in more than data.Length bytes. That can happen if you have non-ASCII characters (i.e. accented characters, symbols from non-English languages, etc.). So what happens is your entire string isn't sent.
You need to write:
string data = "whatever goes here."
byte[] byteData = Encoding.UTF8.GetBytes(data);
request.ContentLength = byteData.Length; // this is the number of bytes you want to send
using (var s = request.GetRequestStream())
{
s.Write(byteData, 0, byteData.Length);
}
That said, I don't understand why your ContentType property isn't being set correctly. I can't say that I've ever seen that happen.

Twitch TV OAuth Login In C#

I am trying to connect a twitch TV account to a user profile on my website and I am getting a 403 Forbidden error. I am trying to use the Authorization Code Flow specified here: https://github.com/justintv/Twitch-API/blob/master/authentication.md#auth-code but the 2nd part where I have to Post back to Twitch TV is where I am getting the error. I am doing this with ASP.net MVC3 and C#.
Here is my method to get the code and ask the user to give my application access to twitch TV (This works as expected):
[Authorize]
public ActionResult TwitchTvLogOn(string returnUrl)
{
string redirectUrl = "";
// This is special code used to determine the URL that will be used when working in UGDB since the URL is different in
// development than it is in production.
#if (DEBUG)
redirectUrl = "http://localhost:58386/Account/AuthorizeTwitchTv";
#else
redirectUrl = "http://www.mywebsite.com/Account/AuthorizeTwitchTv";
#endif
var loginUri = "https://api.twitch.tv/kraken/oauth2/authorize?response_type=code&client_id=" +
System.Configuration.ConfigurationManager.AppSettings["TwitchClientId"] +
"&redirect_uri=" + redirectUrl + "&state=" + returnUrl;
return Redirect(loginUri);
}
This is the part that is not working correctly and is giving the 403:
public ActionResult AuthorizeTwitchTv(string code, string state)
{
string currentUrl = Request.Url.AbsoluteUri;
string redirectUrl = "";
#if (DEBUG)
redirectUrl = "http://localhost:58386/Account/AuthorizeTwitchTv";
#else
redirectUrl = "http://www.mywebsite.com/Account/AuthorizeTwitchTv";
#endif
var twitchTvPost = "https://api.twitch.tv/kraken/oauth2/token?client_id=" +
System.Configuration.ConfigurationManager.AppSettings["TwitchClientId"] + "&client_secret=" +
System.Configuration.ConfigurationManager.AppSettings["TwitchAppSecret"] + "&grant_type=authorization_code&redirect_uri=" +
redirectUrl + "&code=" + code;
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "client_id=" + System.Configuration.ConfigurationManager.AppSettings["TwitchClientId"];
postData += ("&client_secret=" + System.Configuration.ConfigurationManager.AppSettings["TwitchAppSecret"]);
postData += ("&grant_type=authorization_code");
postData += ("&redirect_uri=" + redirectUrl);
postData += ("&code=" + code);
byte[] data = encoding.GetBytes(postData);
// Prepare POST web request...
HttpWebRequest myRequest =
(HttpWebRequest)WebRequest.Create(new Uri("https://api.twitch.tv/kraken/oauth2/token"));
myRequest.Method = "POST";
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.ContentLength = data.Length;
Stream newStream = myRequest.GetRequestStream();
// Send the data.
newStream.Write(data, 0, data.Length);
newStream.Close();
// Get response
HttpWebResponse response = (HttpWebResponse)myRequest.GetResponse();
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
// Read the whole contents and return as a string
string result = reader.ReadToEnd();
return View();
}
Any help would be greatly appreciated. The overall end goal is to get the "access_token" so I can use it to get the current user's twitch username and be able to grab that user's channels and feeds.
I am not very good with this, but i think the problem is that you are trying to connect to localhost wich is your own computer trough a server port. if this is not the problem and this is what you want. did you think about port forwarding?

Write JSON to Solr via HTTP/Post

I am writing to Solr using JSON via HTTP/POST from a C#/Winforms/.NET4.0 app to speed up indexing and using the code below. I write a document to solr (based on these instructions) but keep getting a '400 bad request'. The JSON appears to be clean and no issues.
It seems to be a syntax issue but I have been wrestling with this for last many hours to no avail. Any ideas on what is awry? All help appreciated.
Here is the URI string being posted
"http://localhost:8080/solr/update/json -H 'Content-type:application/json' -d ' [ {\"UUID\":\"d2a174e4-81d6-487f-b68d-392be5d3d47a\",\"Extension\":\".AVI\",\"VideoFileName\":\"Clip 1.avi\"} ' ]"
string uri = http://localhost:8080/solr/update/json;
public bool WriteJSONToSolr(string uri, string json)
{
WebRequest request = WebRequest.Create(uri + " -H 'Content-type:application/json' -d ' [ " + json + " ' ]" );
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(json);
Stream stream = null;
try
{ // send the Post
request.ContentLength = bytes.Length; //Count bytes to send
stream = request.GetRequestStream();
stream.Write(bytes, 0, bytes.Length); //Send it
}
catch
{
return false;
}
finally
{
if (stream != null)
{
stream.Close();
}
}
System.Net.WebResponse response = request.GetResponse();
if (response == null) return false;
return true;
}
If you are inserting then you will need to use add and doc in your json element. You'll also want to add a commit so that the index is updated. You can also remove the parameters from your uri as you can add them in the web request object. Lastly, you should have your collection name in the uri.
string json = "{\"add\":{\"doc\":{"
+ "\"UUID\":\"d2a174e4-81d6-487f-b68d-392be5d3d47a\","
+ "\"Extension\":\".AVI\","
+ "\"VideoFileName\":\"Clip 1.avi\"}},";
+ "\"commit\":{}}";
string uri = "http://localhost:8080/solr/collection/update";
WebRequest request = WebRequest.Create(uri);
request.ContentType = "application/json";
request.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(json);
Stream stream = null;
try {
request.ContentLength = bytes.Length;
stream = request.GetRequestStream();
stream.Write(bytes, 0, bytes.Length);
}
catch {
return;
}
finally {
if (stream != null) {
stream.Close();
}
}
System.Net.WebResponse response = request.GetResponse();
if (response == null) {
return;
}
If you are inserting multiple objects to solr you can add multiple add objects or doc objects to the json. For example...
json = "{add:{doc:{keys:values}}, add:{doc:{keys:values}}, commit:{}}"
or
json = "{add:{doc:{keys:values}, doc:{keys:values}}, commit:{}}"
While your debugging this watch the log for solr. It will alert you to any problems with that may be happening on the solr side.
First of all, I don't think you are passing a correct json data with -d option.. Look at the following formatting code in your code.
" -H 'Content-type:application/json' -d ' [ " + json + " ' ]"
Assume, your json data is {"name":"sam"} Then, the above formatting results to
-H 'Content-type:application/json' -d ' [{"name":"sam"} ' ]
You are passing a json data with missing ].
Apart from that, your approach for updating a document in solr index is wrong. Take a look at the following simple code.
[BTW: You may pass the 'commit' argument in the url].
public async Task PostAsync()
{
string json = "{\"add\": {\"doc\": {"
+ "\"id\":\"12345\","
+ "\"firstname\":\"Sam\","
+ "\"lastname\":\"Wills\","
+ "\"dob\":\"2016-12-14T00:00:00Z\""
+ "}}}";
using (var client = new HttpClient())
{
string uri = "http://localhost:8983/solr/people/update/json?wt=json&commit=true";
var jsonContent = new StringContent(json);
await client.PostAsync(new Uri(uri), jsonContent);
}
}
If you want to update a specific field instead of whole document [partial update], use the following code snippet.
public async Task PartialPostAsync()
{
string json = "{\"add\": {\"doc\": {"
+ "\"id\":\"12345\","
+ "\"lastname\":{\"set\":\"George\"}"
+ "}}}";
using (var client = new HttpClient())
{
string uri = "http://localhost:8983/solr/people/update/json?wt=json&commit=true";
var jsonContent = new StringContent(json);
await client.PostAsync(new Uri(uri), jsonContent);
}
}
'id' field is an unique field.
did you forget putting a space char before -H?
The reasong that your code isn't working, is because you are using cURL syntax in .Net.
cURL is an executable that sends and receives HTTP requests and .Net is a framework for programming applications.
They are not the same.
To make it work with .Net you first should post to the correct uri, and you need to set the correct ContentType property like such:
var uri = "http://localhost:8080/solr/update/json";
using (var r = WebRequest.Create(uri))
{
r.ContentType = "application/json";
r.Method = "POST";
using (var rs = r.GetRequestStream())
rs.Write // your data
// get response
// return response data
}
That said, why inflict pain upon yourself? Just use a SolR connector that already has a typed API for SolR operations!
https://code.google.com/p/solrnet/ for example!
But if you don't want to use that, then at least use a modern HTTP API like https://nuget.org/packages/RestSharp
I ran into this same problem today.
Try these two things
1) Keep in mind that you can NOT send a json string like
[{"A":"1","B":"0","C":"","D":"Washington"}]
instead you may have to massage the json to be more like
[{"A":"1","B":"0","D":"Washington"}]
Solr does not like empty values.
2) This second trick that helps (when sending data to solr via 'curl') : Try replacing all Double Quotes in your json string with two Double Quotes before you send the request to solr.
json = json.Replace(#"""", #"""""");
Please try below code after convert json to stream bytes
protected override void Append(LoggingEvent loggingEvent)
{
byte[] bodyBytes;
try
{
string body = BodyFormatter.CreateBody(loggingEvent, _parameters);
bodyBytes = Encoding.UTF8.GetBytes(body);
}
catch (Exception e)
{
ErrorHandler.Error("Failed to create body", e);
return;
}
HttpWebRequest request = BuildRequest();
request.BeginGetRequestStream(r =>
{
try
{
using (Stream stream = request.EndGetRequestStream(r))
{
stream.BeginWrite(bodyBytes, 0, bodyBytes.Length, c =>
{
try
{
stream.EndWrite(c);
request.BeginGetResponse(a =>
{
try
{
var response = request.EndGetResponse(a);
if (((HttpWebResponse)response).StatusCode != HttpStatusCode.OK)
ErrorHandler.Error("Got failed response: " + ((HttpWebResponse)response).StatusDescription);
response.Close();
}
catch (Exception e)
{
ErrorHandler.Error("Failed to get response", e);
}
}, null);
}
catch (Exception e)
{
ErrorHandler.Error("Failed to write", e);
}
}, null);
}
}
catch (Exception e)
{
ErrorHandler.Error("Failed to connect", e);
}
}, null);
}

super tiny web server in c#

I am writing a super tiny web server for educational purposes.
For the following code, if I request a html page containing an image, I cannot see the image in the browser. What am I doing wrong?
static void Main(string[] args)
{
TcpListener listener = new TcpListener(9999);
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
string request = GetRequest(client.GetStream(),
client.ReceiveBufferSize);
WriteOutput(request, client.GetStream());
client.Close();
}
}
static void WriteOutput(string request, NetworkStream output)
{
try
{
string[] reqs = request.Split(' ');
WriteOutputHelper(output, reqs[1].Substring(1));
}
catch (Exception)
{
WriteOutputHelper(output, "404.html");
}
}
private static void WriteOutputHelper(NetworkStream output, string file)
{
byte[] statusLine = (new System.Text.ASCIIEncoding()).
GetBytes(GetStatusLine(file) + "\r\n\r\n");
output.Write(statusLine, 0, statusLine.Length);
byte[] ContentType =
(new System.Text.ASCIIEncoding()).GetBytes(GetContentType(file) +
"\r\n\r\n");
output.Write(ContentType, 0, ContentType.Length);
byte[] response = System.IO.File.ReadAllBytes("C:\\" + file);
output.Write(response, 0, response.Length);
output.Flush();
}
static string GetContentType(string fileName)
{
string i = "<META http-equiv=\"Content-Type\" content=\"";
if ((fileName.IndexOf(".htm") > -1) || (fileName.IndexOf(".html") > -1))
i = i + "text/html";
else if (fileName.IndexOf(".jpg") > -1)
i = i + "image/jpeg";
i = i + ";\">";
return i;
}
static string GetStatusLine(string fileName)
{
string i = "HTTP/1.0 ";
if (fileName.IndexOf("404") > -1)
return i + "404 Not Found";
else if (fileName.IndexOf("jpg") > -1)
return i + "302 Found";
return i + "200 OK";
}
static string GetRequest(NetworkStream reqStream,int bufSize)
{
byte[] bytesFrom = new byte[10025];
reqStream.Read(bytesFrom, 0, bufSize);
string request = System.Text.Encoding.ASCII.GetString(bytesFrom);
return request;
}
Edited:
static void imageTest(NetworkStream output)
{
byte[] fileContent = System.IO.File.ReadAllBytes("C:\\sachin.jpg");
string statusLine = "HTTP/1.0 200 OK" + System.Environment.NewLine;
string contentType = "Content-type: image/jpeg" + System.Environment.NewLine;
string contentLength = "Content-length: " + fileContent.Length + System.Environment.NewLine;
System.Text.UnicodeEncoding coding = new UnicodeEncoding();
byte[] headers = coding.GetBytes(statusLine + contentType + contentLength);
output.Write(headers, 0, headers.Length);
output.Write(fileContent, 0, fileContent.Length);
output.Flush();
}
For the code above, I am getting this error in fiddler.
The Server did not return properly formatted HTTP Headers. HTTP headers
should be terminated with CRLFCRLF. These were terminated with LFLF.
I am using Unicode encoding because I want to convert string to bytes and I only know to use encoding.
The response for a JPG must be just the HTTP header and then the contents of the JPEG, not any HTML around it.
Something like
HTTP/1.0 200 OK
Content-type: image/jpeg
Content-length: XXXXX
RAWJPEGDATA
Fill in XXXXX with the number of bytes in the Jpeg, and just output the raw JPEG data directly, without any encoding.
Use Fiddler or Firebug to help debug -- they show the exact requests/responses being sent.
It looks like you are sending a 302 Found status for jpeg files, which is meant for redirects. You need to send 200 OK like you do for the HTML file.
I think the problem is in the WriteOutputHelper and the GetContentTypeHelper methods.
The headers should not have \r\n\r\n, one should suffice, also, the GetContentTypeHelper method should return a header like:
Content-type: image/jpeg
Not a html <meta> element which is meant for (X)HTML content, not a HTTP header.
Have you thought about using cassini, It is open source under the project title of utildev. You can definately write your own but you can never cover all your bases. An off the hip guess of what the issue is that all the mime types are not supported by your lite web server.

Categories