I have a web client I'm creating in Silverlight. I am trying to get it to communicate it with my web services on my server through GET and POST requests and JSON. The GET requests work fine and I'm able to parse the JSON on the Silverlight end. The POST requests however dont seem to work. The server reads that there is a POST request, but the POST array is empty.
Ive tried two pieces of code to send the POST requests, but both are resulting in the same response - an empty array.
The first Silverlight code I tried was:
public MainPage()
{
InitializeComponent();
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri("http://www.dipzo.com/game/services.php"));
request.Method = "POST";
request.ContentType = "application/json";
request.BeginGetRequestStream(new AsyncCallback(OnGetRequestStreamCompleted), request);
}
private void OnGetRequestStreamCompleted(IAsyncResult ar)
{
HttpWebRequest request = (HttpWebRequest)ar.AsyncState;
using (StreamWriter writer = new StreamWriter(request.EndGetRequestStream(ar)))
{
writer.Write("name=david");
}
request.BeginGetResponse(new AsyncCallback(OnGetResponseCompleted), request);
}
private void OnGetResponseCompleted(IAsyncResult ar)
{
//this.GetResponseCoimpleted.Visibility = Visibility.Visible;
// Complete the Flickr request and marshal to the UI thread
using (HttpWebResponse response = (HttpWebResponse)((HttpWebRequest)ar.AsyncState).EndGetResponse(ar))
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
string results = reader.ReadToEnd();
}
}
}
The second piece I tried was:
private void WebClient_Click(object sender, RoutedEventArgs e)
{
Test t1 = new Test() { Name = "Civics", Marks = 100 };
DataContractJsonSerializer jsondata = new DataContractJsonSerializer(typeof(Test));
MemoryStream mem = new MemoryStream();
jsondata.WriteObject(mem, t1);
string josnserdata = Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
WebClient cnt = new WebClient();
cnt.UploadStringCompleted += new UploadStringCompletedEventHandler(cnt_UploadStringCompleted);
cnt.Headers["Content-type"] = "application/json";
cnt.Encoding = Encoding.UTF8;
cnt.UploadStringAsync(new Uri("http://www.dipzo.com/game/services.php"), "POST", josnserdata);
}
void cnt_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
var x = e;
}
The code on the server to consume the service is in PHP and is essentially:
var_dump($_POST)
This should output whatever is coming into the post array. I've tested it with a simple PHP client and it works. Just can't get it to work in silverlight. In silverlight I just keep getting an empty array.
You should change the Content-type to application/x-www-form-urlencoded and not application/json which is not a known type yet.
Not that I think anyone is still paying attention tot his old question, but I'm betting that the problem was that it actually WAS getting to the server, but that the server routed the result back to the SL application. This is the behavior I'm seeing with a similar situation from SL5 usingWebClient.UploadStringAsync.
I'm about to implement/test a technique I ran across yesterday which uses a dynamically built, "real" page post from SL; I'll report my findings shortly.
UPDATE -- THIS SOLUTION WORKS:
http://www.codeproject.com/Tips/392435/Using-HTTP-Form-POST-method-to-pass-parameters-fro
I've just tested it in my application (SL5 inside MVC) and it works just fine. Make sure you check the HttpContext.Request.Form["fieldname"] to get the value(s) that you want. I used this technique to submit JSON and was able to return a generated Word document for the user.
Once I implemented this I was able to get rid of the unnecessary WebClient that I was attempting to use before.
Related
I am testing a REST API post, and it works well when I try it on Postman. However, in some scenario (related to the posting XML data) if I post with HttpClient API, I would receive the following error:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
But the same XML content works fine on Postman with status OK and proper response.
What is the differences between using the C# HttpClient API and the postman testing? How can I configure my API call to match with the behavior on postman?
Here I attached the source code, and the Postman screenshot
public void createLoan()
{
string baseCreateLoanUrl = #"https://serverhost/create?key=";
var strUCDExport = XDocument.Load(#"C:\CreateLoan_testcase.xml");
using (var client = new HttpClient())
{
var content = new StringContent(strUCDExport.ToString(), Encoding.UTF8, Mediatype);
string createLoanApi = string.Concat(baseCreateLoanUrl, APIKey);
try
{
var response = client.PostAsync(createLoanApi, content).Result;
}
catch (Exception ex)
{
MessageBox.Show("Error Happened here...");
throw;
}
if (response.IsSuccessStatusCode)
{
// Access variables from the returned JSON object
string responseString = response.Content.ReadAsStringAsync().Result;
JObject jObj = JObject.Parse(responseString);
if (jObj.SelectToken("failure") == null)
{
// First get the authToken
string LoanID = jObj["loanStatus"]["id"].ToString();
MessageBox.Show("Loan ID: " + LoanID);
}
else
{
string getTokenErrorMsg = string.Empty;
JArray errorOjbs = (JArray) jObj["failure"]["errors"];
foreach (var errorObj in errorOjbs)
{
getTokenErrorMsg += errorObj["message"].ToString() + Environment.NewLine;
}
getTokenErrorMsg.Dump();
}
}
}
Thanks for Nard's comment, after comparing the header, I found the issue my client header has this:
Expect: 100-continue
While postman doesn't has.
Once I removed this by using the ServicePointManager:
ServicePointManager.Expect100Continue = false;
Everything seems fine now. Thanks all the input!
My gut tells me it's something simple. First, we know the API works, so I'm thinking it's down to how you are using the HttpClient.
First things first, try as suggested by this SO answer, creating it as a singleton and drop the using statement altogether since the consensus is that HttpClient doesn't need to be disposed:
private static readonly HttpClient HttpClient = new HttpClient();
I would think it would be either there or an issue with your content encoding line that is causing issues with the API. Is there something you are missing that it doesn't like, I bet there is a difference in the requests in Postman vs here. Maybe try sending it as JSON ala:
var json = JsonConvert.SerializeObject(strUCDExport.ToString());
var content = new StringContent(json, Encoding.UTF8, Mediatype);
Maybe the header from Postman vs yours will show something missing, I think the real answer will be there. Have fiddler running in the background, send it via Postman, check it, then run your code and recheck. Pay close attention to all the attribute tags on the header from Postman, the API works so something is missing. Fiddler will tell you.
I was struggling with this for 2 days when I stumbled over Fiddler which lets you record the traffic to the service. After comparing the calls I saw that I had missed a header in my code.
I recently wrote an async HttpWebRequest client for our application and it works fine in .NET 3.5, but on Mono it fails to correctly write the data on to the request before sending it out.
I have confirmed the problem using wireshark to sniff the outgoing packets. The HTTP request is correctly set to POST with a JSON Content Type however the Content-Length and data are 0.
I currently get one exception:
The number of bytes to be written is greater than the specified
ContentLength.
I have tried to resolve this by manually setting the ContentLength of the WebRequest and changing the way I encode the data before giving it to the stream (I have tried both a Steam and StreamWriter).
I have also stepped through the code and debug logged the variables in the async method to ensure the data is really there. It just does not appear to be getting to the WebRequest object.
Here is the relevant code:
private void StartWebRequest(string payload) {
var httpWebRequest = (HttpWebRequest)WebRequest.Create(PortMapSleuthURL);
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
httpWebRequest.Proxy = null; // Setting this to null will save some time.
// start an asynchronous request:
httpWebRequest.BeginGetRequestStream(GetRequestStreamCallback, new object[] {httpWebRequest, payload});
try {
// Send the request and response callback:
httpWebRequest.BeginGetResponse(FinishPortTestWebRequest, httpWebRequest);
} catch (Exception e) {
Console.WriteLine(e.Message);
PortTestException();
}
}
private void GetRequestStreamCallback(IAsyncResult asyncResult) {
try {
object[] args = (object[])asyncResult.AsyncState;
string payload = (string)args[1];
HttpWebRequest request = (HttpWebRequest)args[0];
//StreamWriter streamWriter = new StreamWriter(request.EndGetRequestStream(asyncResult), new UTF8Encoding(false));
StreamWriter streamWriter = new StreamWriter(request.EndGetRequestStream(asyncResult), Encoding.UTF8);
// Write to the request stream.
streamWriter.Write(payload);
streamWriter.Flush();
streamWriter.Close();
} catch (Exception e) {
Console.WriteLine(e.Message);
PortTestException();
}
}
I don't think you are supposed to call BeginGetResponse before EndGetRequestStream. That is, I would move that into the GetRequestStreamCallback. This is how the example on msdn works too.
i'm new to wp8 and i don't have any idea to post and update my data in URL so please can any one help me to post/Update data in the url..
my header and content type...
Header - Accept: application/json
Content-Type application/json
MY Class Register with the variables...
public class Register
{
public string email { get; set; }
public string password { get; set; }
}
My Design..
when i click ADD button it should post the data in my url.. so plz help me to do it..
MY CODE for post method..
WebClient client = new WebClient();
Register res = new Register();
res.email = txt_email.Text;
res.password = txt_password.Text;
String json = JsonConvert.SerializeObject(res);
client.Headers[HttpRequestHeader.Accept] = "application/json";
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.UploadStringCompleted += (object source, UploadStringCompletedEventArgs ex) =>
{
if (ex.Error != null || ex.Cancelled)
{
// Error or cancelled
MessageBox.Show(ex.Result);
}
};
var uri = new Uri(url, UriKind.Absolute);
// client.Encoding = System.Text.Encoding.UTF8;
client.UploadStringAsync(uri,json); // message is the json content in string
ERROR.. on Adding content..
I use RestSharp in my projects for that kind of thing. It simplifies things a bit particularly if you want to access cookies.
There's some examples on their wiki that should show you what to do.
http://restsharp.org/
You can use WebClient
public void PostJSON()
{
client = new WebClient();
client.Headers[HttpRequestHeader.Accept] = "application/json";
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.UploadStringCompleted += (object source, UploadStringCompletedEventArgs e) =>
{
if (e.Error != null || e.Cancelled)
{
// Error or cancelled
}
};
client.UploadStringAsync(url, message); // message is the json content in string
}
Your code seems legit to me. Since you get the error at runtime, I doubt that you might not have a proper Internet connection in your emulator. Or, if you are running your web service from localhost, you must help your emulator reach your local service.
Case #1: No proper Internet connection
Refer the following link and troubleshoot your network problem as stated in the MSDN page.
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj681694(v=vs.105).aspx
Case #2: Help emulator to connect to a local web service
Even when you can connect to external web content, you still need to configure your emulator to access your local web service. Go through the MSDN article given at the link below.
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj684580(v=vs.105).aspx
Feel free to leave a comment if you need further assistance.
I'm working with JSON for a while now, but this is a problem I can't solve.
The program is written in C# and has a method called CreateWebRequest():
public void CreateWebRequest()
{
CurrentTime = DateTime.Now;
target = link;
request = WebRequest.Create(target) as HttpWebRequest;
request.ContentType = "application/json; charset=utf-8";
request.Method = "PUT";
request.ServicePoint.Expect100Continue = false;
string postData = jsonString;
System.Console.WriteLine("POSTDATA: " + postData);
StreamWriter requestWriter;
using (requestWriter = new StreamWriter(request.GetRequestStream()))
{
requestWriter.Write(postData);
}
}
The other function to fetch the result is called: CreateWebResponse():
public void CreateWebResponse()
{
WebResponse response;
string text;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException e)
{
MessageBox.Show(e.Message);
return;
}
using (var sr = new StreamReader(response.GetResponseStream()))
{
text = sr.ReadToEnd();
}
APIresult apiresult = JsonConvert.DeserializeObject<APIresult>(text); //Deserialize the text
}
These functions work all fine, there is only one problem: the code does two requests.
When I put the same JSON in the RESTClient in mozilla FireFox the JSON works fine. It also works great when I'm only using CreateWebRequest(), but when I use both of the methods it seems the code creats a second request?
Is it possible to create only a response? Combine these two functions to one which creates directly an response?
I tried other solutions and put them just together, none of them seems to work. When I call for a response the code doesn't work properly anymore and creates two requests.
Has anyone a solution?
Thanks in advance.
The JSON function I call has several if statements and work fine according to RESTClient in Firefox.
The code below shows the code which is called correct by RESTClient and twice by the C# code:
$sql = 'SELECT...';
$result = $db->sql_query($sql);//search for member id.
if($row = $db->sql_fetchrow($result)){//when found, the user has access.
$member_id = $row['member_id'];
$sql = 'SELECT ...';
$result = $db->sql_query($sql);//search for last login today.
if($row = $db->sql_fetchrow($result)){//if the user has logged in today update the row.
$row_check_in_timestamp = $row['check_in_timestamp'];
$sql = 'UPDATE ...';//update the row with the check out timestamp
$db->sql_query($sql);
break;
}else{//the user hasn't logged in yet today, log in.
$start_session_array = array(
'club_id' => (int)$club_id,
'member_id' => (int)$member_id,
'check_in_timestamp' => (int)time(),
);
$sql = 'INSERT ...';//check user in and add a new row in the database
$db->sql_query($sql);
break;
}
}else{
break;
}
SOLVED: I'm sorry every one and thanks for all the responses, but I've found the problem. I had an older version as service running all the time and made the second JSON call.
I've found it by logging on the server side the calls and blocked code which call the JSON in my own code to figure this out.
I got a Windows Phone project which are getting an list of a object that i call friend from an webservice using REST. The whole connection part works good the first time, the second time it fails. I get the same value from the method even tho i change the value in the database. Here is an example.
Users goes to an page
The right value is fetched from the database using an WCF service
I change the value in the database manually
User goes into the page again and the method for fetching the data is started again but it still gets the same result as the first time it fetched data from the webservice.
Any ideas?
Code:
HttpWebRequest request;
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
UpdateData();
}
public void UpdateData()
{
((App)App.Current).ShowProgressBar();
string uri = App.SERVICE_URI + "/GetFriends?userid=" + App.CurrentUserId;
request = (HttpWebRequest)HttpWebRequest.Create(new Uri(uri));
request.BeginGetResponse(new AsyncCallback(GetFriendsReadCallback), request);
}
private void GetFriendsReadCallback(IAsyncResult asynchronousResult)
{
List<Friend> friends;
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
using (StreamReader streamReader1 = new StreamReader(response.GetResponseStream()))
{
string resultString = streamReader1.ReadToEnd();
var ser = new DataContractJsonSerializer(typeof(List<Friend>));
var stream = new MemoryStream(Encoding.Unicode.GetBytes(resultString));
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(List<Friend>));
friends = (List<Friend>)jsonSerializer.ReadObject(stream);
}
You are running into a caching issue, most likely. Either change your REST service to disable caching:
Response.Cache.SetCacheability(HttpCacheability.NoCache);
If you don't have access to the service code, you can append a changing dummy parameter to the end of your request URL (e.g. a GUID or DateTime.Now.Ticks).
Check out my answer here: WebClient in a WP7.1 app called only once
I'd run this in the emulator with fiddler2 operating - check what id being sent over http to find out if the call is being made second time, and if the correct answer is being sent back. Once you know whether the problem is client or server side then start debugging using breakpoints - where is the wrong value first picked up.