POST json with Rest APi using webReuest from WP7 - c#

I am updating the db table on force.com using Rest API. And i am posting json data to update db table like this.
// preparing webrequest
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
// adding request headers
request.ContentType = "application/json";
request.Headers["Authorization"] = "OAuth " + token;
request.Headers["X-PrettyPrint"] = "1";
// request method
request.Method = "PATCH";
// start the asynchronous operation
request.BeginGetRequestStream(new AsyncCallback(SaveBeginGetRequestStreamCallBack), request);
private void SaveBeginGetRequestStreamCallBack(IAsyncResult ar)
{
HttpWebRequest webRequest = (HttpWebRequest)ar.AsyncState;
Stream postStream = webRequest.EndGetRequestStream(ar);
(using (StreamWriter sw = new StreamWriter(postStream))
{
sw.Write(postData);
// postData is in json format like: {"Name":"Michel"}
}
postStream.close();
webRequest.BeginGetResponse(new AsyncCallback(SaveBeginGetResponseCallback), webRequest);
}
private void SaveBeginGetResponseCallback(IAsyncResult ar)
{
try
{
HttpWebRequest webRequest = (HttpWebRequest)ar.AsyncState;
HttpWebResponse response;
// End the get response operation
response = (HttpWebResponse)webRequest.EndGetResponse(ar);
Stream streamResponse = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamResponse);
string Response = streamReader.ReadToEnd();
streamResponse.Close();
streamReader.Close();
response.Close();
}
catch (WebException e)
{
MessageBox.Show(e.Message);
// Error treatment
}
But it is showing bad request error. Is it a right way to send json format over http request.

You are not closing/disposing the postStream prior to calling BeginGetResponse ...
Also, call
sw.Write(data);
Since data is a string. Your call (passing an offset and a count) would be appropriate for a byte array. You are actually calling a formatting overload http://msdn.microsoft.com/en-us/library/fd857wct(v=VS.96).aspx

Related

c# How to send HTTP command as this - http://192.168.10.1/api/control?alert=101002

I have this hardware from Patlite,
This hardware has an HTTP command control function, for example, if I copy the url "http://192.168.10.1/api/control?alert=101002" to chrome in my computer, it will activate the hardware as needed.
I want to send the command from my code.
I tried this code with no luck:
System.Net.ServicePointManager.Expect100Continue = false;
WebRequest request = WebRequest.Create("http://10.0.22.222/api/control");
request.Method = "post";
request.ContentType = "application/x-www-form-urlencoded";
string postData = "alert=101002";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
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();
WebResponse response = request.GetResponse();
There is a picture from the manual:
Thanks
You need to create a webrequest instance for this.
WebRequest request = WebRequest.Create("http://192.168.10.1/api/control?alert=101002");
WebResponse response = request.GetResponse();
You may need to set some properties as request method and credentials for this to work.
See this:
https://msdn.microsoft.com/en-us/library/456dfw4f(v=vs.100).aspx
public static string Get(string url, Encoding encoding)
{
try
{
var wc = new WebClient { Encoding = encoding };
var readStream = wc.OpenRead(url);
using (var sr = new StreamReader(readStream, encoding))
{
var result = sr.ReadToEnd();
return result;
}
}
catch (Exception e)
{
//throw e;
return e.Message;
}
}
like this code use the url "http://192.168.10.1/api/control?alert=101002" to send get request.Good luck!

Parsing POST request data with FiddlerCore

I'm tring to capture a local POST requset and parse its data.
For testing only, the FiddlerCore should only response with the data it has parsed.
Here's the code of the FidlerCore encapsulation:
private void FiddlerApplication_BeforeRequest(Session oSession)
{
if (oSession.hostname != "localhost") return;
eventLog.WriteEntry("Handling local request...");
oSession.bBufferResponse = true;
oSession.utilCreateResponseAndBypassServer();
oSession.oResponse.headers.HTTPResponseStatus = "200 Ok";
oSession.oResponse["Content-Type"] = "text/html; charset=UTF-8";
oSession.oResponse["Cache-Control"] = "private, max-age=0";
string body = oSession.GetRequestBodyAsString();
oSession.utilSetResponseBody(body);
}
Here's the code of the request sender:
const string postData = "This is a test that posts this string to a Web server.";
try
{
WebRequest request = WebRequest.Create("http://localhost/?action=print");
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentLength = byteArray.Length;
request.ContentType = "text/html";
request.Method = "POST";
using (Stream stream = request.GetRequestStream())
{
stream.Write(byteArray, 0, byteArray.Length);
}
using (WebResponse response = request.GetResponse())
{
txtResponse.Text = ((HttpWebResponse)response).StatusDescription;
using (Stream stream = response.GetResponseStream())
{
using (StreamReader streamReader = new StreamReader(stream))
{
string responseFromServer = streamReader.ReadToEnd();
streamReader.Close();
txtResponse.Text = responseFromServer;
}
}
}
}
catch (Exception ex)
{
txtResponse.Text = ex.Message;
}
I'm getting the following error:
The server committed a protocol violation. Section=ResponseStatusLine
What am I doing wrong?
Got it to work by changing:
WebRequest request = WebRequest.Create("http://localhost/?action=print");
to
WebRequest request = WebRequest.Create("http://localhost:8877/?action=print");
Calling this URL from a browser is intercepted by FiddlerCore correctly, without having to specify the port number. I did not think I should have inserted the listening port, since FiddlerCore should intercept all traffic, right?

Getting data back from an HttpWebRequest.BeginGetResponse callback

I am writing a Windows Phone 8 app that is supposed to send an GET+POST request to a server and parse the answer.
The code I am using to send the request and to get a response back is the following (it is written in a separate static class):
// server to POST to
string url = "http://myserver.com/?page=hello&param2=val2";
// 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 the post data
string postData = "pseudo=pseudo&titre=test&texte=\"Contenu du message\"";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Write the bytes to the stream
await stream.WriteAsync(byteArray, 0, byteArray.Length);
stream.Close();
IAsyncResult ar = httpWebRequest.BeginGetResponse(new AsyncCallback(GetResponsetStreamCallback), httpWebRequest);
}
}
private static void GetResponsetStreamCallback(IAsyncResult callbackResult)
{
HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
{
string result = httpWebStreamReader.ReadToEnd();
//For debug: show results
System.Diagnostics.Debug.WriteLine(result);
}
My problem is : I have no idea how to get this answer (the string result) back in my behind-code in my app (or any other method in my app to be honest).
How could I do that?
You can try the following code,
string url = "http://myserver.com/?page=hello&param2=val2";
// HTTP web request
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Method = "POST";
httpWebRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), webRequest);
}
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
using (var postStream = webRequest.EndGetRequestStream(asynchronousResult))
{
//send yoour data here
}
webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
}
void GetResponseCallback(IAsyncResult asynchronousResult)
{
try
{
HttpWebRequest myrequest = (HttpWebRequest)asynchronousResult.AsyncState;
using (HttpWebResponse response = (HttpWebResponse)myrequest.EndGetResponse(asynchronousResult))
{
System.IO.Stream responseStream = response.GetResponseStream();
using (var reader = new System.IO.StreamReader(responseStream))
{
data = reader.ReadToEnd();
}
responseStream.Close();
}
}
catch (Exception e)
{
//Handle Exception
}
else
throw;
}
}
public static string GetPageAsString(Uri address)
{
string result = "";
// Create the web request
HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
// Get response
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream(), Constants.EncodingType);
// Read the whole contents and return as a string
result = reader.ReadToEnd();
}
return result;
}
Does it have to be a static class? Because if you have a new webrequest object for each request, then each response will come back into it's own object.v
You need to put the result somewhere that you can access it from the place you want to use it.
e.g. if you put it into another public static variable member then you can read it off where you need to. But you probably need to signal the UI to action it, or bind it to the UI.
If you use a static place to store it, then you will only have one active at a time. Unless you add it to a static list of items or results that you are working with
See also: http://blogs.msdn.com/b/devfish/archive/2011/04/07/httpwebrequest-fundamentals-windows-phone-services-consumption-part-2.aspx
You can: make a global variable in App.xaml.cs:
public string result;
In code use it as
(App.Current as App).result = httpWebStreamReader.ReadToEnd();
If you will need to get notified in your current active page when the result is updated - use delegates after you get the response which will signal to your page.

WebRequest on windows phone 7

I have the following class (I take it from an example on the net, the only thing I've modified is that I use an IP address and port instead of a domain name):
public class ConnectionManager
{
private static ManualResetEvent allDone = new ManualResetEvent(false);
private string message = "foobar";
public Action MessageSent;
public Action<string> MessageReceived;
public void SendMessage()
{
// Create a new HttpWebRequest object.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://10.1.91.48:3330/");
request.ContentType = "application/json; charset=utf-8";
request.Accept = "application/json";
// Set the Method property to 'POST' to post data to the URI.
request.Method = "POST";
// start the asynchronous operation
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
MessageSent();
// Keep the main thread from continuing while the asynchronous
// operation completes. A real world application
// could do something useful such as updating its user interface.
allDone.WaitOne();
}
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(message);
// Write to the request stream.
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
Console.WriteLine(responseString);
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
allDone.Set();
MessageReceived(responseString);
}
}
The code above fails to send the message. If I step, when I'm inside GetRequestStreamCallback I can see inside IAsyncResult the following error:
AsyncWaitHandle = 'asynchronousResult.AsyncWaitHandle' threw an
exception of type 'System.NotSupportedException'
What am I doing wrong? How can I fix this code?
While it's probably not the solution to your problem, you need to get into the habit of placing your IDisposable objects into using blocks, to ensure they get cleaned up even if exceptions happen:
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
using (Stream postStream = request.EndGetRequestStream(asynchronousResult))
{
byte[] byteArray = Encoding.UTF8.GetBytes(message);
// Write to the request stream.
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
}
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
string responseString;
using (HttpWebResponse response = (HttpWebResponse) request.EndGetResponse(asynchronousResult))
{
using (Stream streamResponse = response.GetResponseStream())
{
using (StreamReader streamRead = new StreamReader(streamResponse))
{
responseString = streamRead.ReadToEnd();
Console.WriteLine(responseString);
}
}
}
allDone.Set();
MessageReceived(responseString);
}
As an alternative you could be using RestSharp.
http://restsharp.org/
It makes this sort of thing a lot more trivial. You have to make some slight changes to get it to work on the Windows Phone though:
http://www.tonicodes.net/blog/async-and-restsharp-for-windows-phone-7/
Nothing too crazy.
I ended up using WebClient:
WebClient wc = new WebClient();
wc.DownloadStringCompleted += ReadServerResponse;
wc.DownloadStringAsync(new Uri(url));

How do I actually get the response of an async web request from outside the method?

I'm a little confused. I'm trying to post to my web service in an async manner, ideally I want to start the request, show a loading spinner on the UI and then when the async request finishes process the response and either show an error if there is one, or do another operation with the result.
Here is my code, I call the request here and pass some data in.
private void SignInExecute()
{
if (Username == null || Password == null)
{
LoginOutput = "Please provide a username or password.";
}
else
{
this.webService.SendLoginRequest("http://localhost:3000/client_sessions", "username=" + Username + "&password=" + Password);
}
}
And here is the actual web request code:
public void SendLoginRequest(string url, string postdata)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Accept = "application/json";
byte[] byteArray = Encoding.UTF8.GetBytes(postdata);
request.CookieContainer = new CookieContainer();
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
((HttpWebRequest)request).KeepAlive = false;
request.BeginGetResponse(new AsyncCallback(GetLoginResponseCallback), request);
}
private static void GetLoginResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
Console.WriteLine(responseString);
// Close the stream object
streamResponse.Close();
streamRead.Close();
response.Close();
}
So to sum up. I want to be able to return the response back to the object which originally gave the call for the web request to start. Any help?
You need to tell the BeginGetResponse to go back to the same context in which it was called via SynchronizationContext.Current. Something like this (the code does not have proper error checking, so you should think about that properly) (Also, Platinum Azure is correct that you should use a using to let your streams close properly (and guaranteed):
In your SendLoginRequest:
//Box your object state with the current thread context
object[] boxedItems = new []{request, SynchronizationContext.Current};
request.BeginGetResponse(new AsyncCallback(GetLoginResponseCallback),
boxedItems);
The getresponse code:
private static void GetLoginResponseCallback(IAsyncResult asynchronousResult)
{
//MY UPDATE
//Unbox your object state with the current thread context
object[] boxedItems = asynchronousResult.AsyncState as object[];
HttpWebRequest request = boxedItems[0] as HttpWebRequest;
SynchronizationContext context = boxedItems[1] as SynchronizationContext;
// End the operation
using(HttpWebResponse response =
(HttpWebResponse)request.EndGetResponse(asynchronousResult))
{
using(Stream streamResponse = response.GetResponseStream())
{
using(StreamReader streamRead = new StreamReader(streamResponse))
{
string responseString = streamRead.ReadToEnd();
Console.WriteLine(responseString);
//MY UPDATE
//Make an asynchronous call back onto the main UI thread
//(context.Send for a synchronous call)
//Pass responseString as your method parameter
//If you have more than one object, you will have to box again
context.Post(UIMethodToCall, responseString);
}
}
}
}
To implement your UI processing
public static void UIMethodCall(object ObjectState)
{
String response = ObjectState as String;
label1.Text = String.Format("Output: {0}", response);
//Or whatever you need to do in the UI...
}
Now, I would test this out first, though. My understanding of Microsoft's implementation of event driven async was that the response was context-aware, and knew which context to return to. So, before jumping to the assumption that you are not on the same context, test it out by trying to update the UI (this will cause a thread context exception if you are not on the calling (UI) thread)

Categories

Resources