I've a iOS application written in C# using Monodevelop, and as part of the application I make a call to a web service. The web service call requires that JSON data to be written to the request. However, I receive an error the first time I attempt to write the data; all subsequent calls to the same method with the same parameters work. The following is a snippet of the relavent code:
// Start snippet
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create (_connectionSettings.Uri);
request.Timeout = 15000; // milliseconds
if (_connectionSettings.Username != "") {
request.Credentials = new NetworkCredential (_connectionSettings.Username, _connectionSettings.Password);
}
if (post) {
request.Method = "POST";
request.ContentType = "application/json";
if (jsonData != null) {
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(jsonData);
request.ContentLength = byteArray.Length;
using (Stream ds = request.GetRequestStream()) { //<--- ERROR HERE
ds.Write (byteArray, 0, byteArray.Length);
}
} else {
request.Method = "GET";
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
// end snippet
The error I get is as follows:
System.Net.WebException: Request was cancelled. --->
System.Exception:
Cannot close the stream until all bytes are written
--- End of inner exception stack trace --- at
System.Net.WebConnectionStream.Close ()
[0x00121] in
/Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebConnectionStream.cs:785
at System.IO.Stream.Dispose () [0x00000] in
/Developer/MonoTouch/Source/mono/mcs/class/corlib/System.IO/Stream.cs:93
at
MyCustomMethod (System.String& responseString, System.String jsonData, Boolean post,
Boolean suppressAlert) [0x00101] in /Path/To/My/Class.cs:192
Any ideas what I could be doing wrong?
EDIT
Ok, apparently when stepping through the application, the method works every time. What I've noticed is that when the error is throw, the request.ContentLength is zero despite the fact that the byteArray.Length is non-zero. However when stepping through the application, the request.ContentLength keeps the expected value of the byteArray.Length.
Ok, it looks like we don't need to set the request.ContentLength at all. Removing the line:
request.ContentLength = byteArray.Length;
fixes the issue entirely. I'm still curious if this is a bug in the library as most of the code samples show setting the HttpWebRequest's ContentLength, and it works properly on subsequent tries.
Related
I have a program in C# .NET 3.5 CompactFramework that requests data from a C# WebService:
public SynchronisationResult<J> Get<J>(IEnumerable<DomainProxy> existingObjects, string controller, string parameters) where J : IdJsonObject)
{
string existingObjectsJson = JsonConvert.SerializeObject(existingObjects);
string url = GenerateUrl(controller, parameters);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.ContentType = "text/json";
request.Method = "POST";
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version11;
request.Timeout = 60000;
request.ContentLength = existingObjectsJson.Length;
using (Stream requestStream = request.GetRequestStream())
{
using (var streamWriter = new StreamWriter(requestStream))
{
streamWriter.Write(existingObjectsJson);
streamWriter.Flush();
streamWriter.Close();
}
requestStream.Close();
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
string responseData = "";
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
responseData = streamReader.ReadToEnd();
}
if (response.StatusCode == HttpStatusCode.OK)
{
result = JsonConvert.DeserializeObject<SynchronisationResult<J>>(responseData);
}
else
{
throw new Exception(responseData);
}
response.Close();
}
}
I can call this method several times with different parameters (different controllers on the WebServer) and suddenly everything gets stuck. The application does not react anymore, when i press PAUSE in Visual Studio i see the program pointer at the location
using (Stream requestStream = request.GetRequestStream())
Sometimes a SystemException is thrown in Timer.ring of System.Net.Connection..., although in case, the application does not continue to run, even not by bubbling the exception to the next catch-Block. This means, that i have to reset the device it does never continue to run.
I have tried the following changes to solve the problem:
request.KeepAlive = true / false
request.Pipelines = true / false
ServicePointManager.DefaultConnectionLimit = 1000;
request.AutomaticDecompression = DecompressionMethods.GZip or nothing
Nothing, the request works fine in Postman for example.
Weird thing is, if i implement this in a for loop, asking for about 200 objects to be updated it crashes faster. In case i implement the request method on a button click and click it with a frequency of about 10 seconds it works way longer. I tried with a development IIS backend on port 888, with a production machine on port 80, firewall locally is turned off. There is no certain request that fails it could be a request for type A or B or C,... each run is different.
Would someone explain:
a) why code gets stuck and does not continue?
b) why code gets stuck even when an exception is thrown
c) how to configure ServicePointManager or Request to get things working properly
EDIT: This is the Exception that sometimes occurs when request.GetRequestStream() is executed:
at System.Threading.Timer.startTimer(UInt32 dueTime)
at System.Threading.Timer.Change(UInt32 dueTime, UInt32 period)
at System.Threading.Timer.Change(Int32 dueTime, Int32 period)
at System.Threading.ThreadPool.QueueUserWorkItem(WaitCallback callBack, Object state, Boolean IsHttpRequest)
at System.Net.Connection.actionSending()
at System.Net.Connection.changeState(ConnectionState state)
at System.Net.Connection.transitionRequestSent(Event e)
at System.Net.Connection.processEvent(Event e)
at System.Net.Connection.actionRequestSent()
at System.Net.Connection.changeState(ConnectionState state)
at System.Net.Connection.transitionIdle(Event e)
at System.Net.Connection.processEvent(Event e)
at System.Net.Connection.submitRequest(HttpWebRequest request)
at System.Net.ServicePoint.SubmitRequest(HttpWebRequest request, String connGroupName)
at System.Net.HttpWebRequest.SubmitRequest()
at System.Net.HttpWebRequest.finishGetRequestStream()
at System.Net.HttpWebRequest.GetRequestStream()
I was also stuck on this issue for couple of days. Finally what I found was if I run Fiddler in the background there was no exception thrown in the request.GetRequestStream(). Which means this is something related to the connection pool where fiddler is handling this. So I did some research and found the below link which solved my issue:
https://www.telerik.com/blogs/help!-running-fiddler-fixes-my-app-
Also after the request is completed make sure you abort that as well. What I did is:
if (webrequest != null) webrequest.Abort();
For me everything is working fine now.
After endless research and testing of different combinations, I'm clueless right now.
I receive an WebException: The request timed out only if I my byteArray gets filled by something else than System.Text.Encoding.UTF8.GetBytes(""). (Like "hello")
The server setup is a https-request to a Google Load Balancer, which communicates with the backend via HTTP. The backend is an Apache with PHP.
For testing purposes (self-signed SSL-Cert) I have this:
System.Net.ServicePointManager.ServerCertificateValidationCallback =
delegate (object s,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors){
return true;
};
If I enter the URL in my web-browser (Chrome), I get a response.
If I use the HTTP-requester from Mozilla with or without content to send, I get the correct response data (after adding an SSL-Security exception)
If I run my code below with System.Text.Encoding.UTF8.GetBytes("") everything works (except I cannot send data and therefore receive what I want)
Here's the code I'm using.
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://someurl.com/some.php");
webRequest.Proxy = null;
webRequest.Credentials = CredentialCache.DefaultCredentials;
webRequest.Method = "POST";
webRequest.Timeout = 3000;
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes("someData"); //works if empty
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = byteArray.Length;
Stream postData = webRequest.GetRequestStream();
postData.Write(byteArray, 0, byteArray.Length);
postData.Close();
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse(); //ERROR MESSAGE
Stream dataStream = webResponse.GetResponseStream();
reader = new StreamReader(dataStream);
string data = reader.ReadToEnd(); //output data
reader.Close ();
dataStream.Close ();
webResponse.Close ();
The exact error (btw, all this happens in the Unity3D editor):
WebException: The request timed out
System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult)
System.Net.HttpWebRequest.GetResponse ()
So why on earth is it not working, once there is something the GetRequestStream has to write?
Thanks and all the best,
Kruegbert
..::Addendum
if I increase the timeout, it just takes longer until the same msg appears.
If I write webRequest.ContentLength = byteArray.Length+1 I receive a response, but it's a WebException error: ProtocolError
If I write webRequest.ContentLength = byteArray.Length-1 I get the ProtocolViolationException
I already tried the same with try/catch/using resulting in the same behaviour
I figured out, why it was not working - still I don't know why it behaves like this. (Maybe a UnityEditor thing)
I added
webRequest.ProtocolVersion = HttpVersion.Version10;
and everything worked. No more timeout errors. And yes webRequest.ProtocolVersion = HttpVersion.Version11; results in the timeout error.
However, making a HttpRequest from the web succeeds with either of these: HTTP/1.1, HTTP/1.0 (with Host header), HTTP/1.0 (without Host header)
I am currently developing in Unity (in particular using C#) and I'm stuck with HttpWebRequest - HttpWebResponse random timeouts.
I have some methods that send a POST request to a server I host on my local machine (XAMPP) to use various php scripts which are going to fetch informations from MySQL Database (hosted with XAMPP) and give back those info in JSON format.
Then I handle these JSON informations with my C# scripts.
The problem is that when I run the first test all is good:I can get the JSON data from my Server and show it in the Debug Console.
When I run the second test,a WebException is raised with error:
WebException - The request timed out
After that second test,if I run again and again,the problem keeps presenting in a random way.
I followed all the guidelines I found on the internet on how to setup a webrequest - webresponse properly,in particular I tried to use ServicePoint.DefaultConnectionLimit and ServicePoint.MaxServicePointIdleTime,without any result.
The general structure of my methods (regarding the web request/response part) is something like that:
public void WebMethod(){
string post_url = "http://localhost/service.php?someparam=1&someparam=2";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(post_url);
request.Method = "POST";
request.KeepAlive = false;
request.Timeout = 5000;
request.Proxy = null;
string Response = "";
try
{
using (HttpWebResponse resp = request.GetResponse() as HttpWebResponse)
{
using (Stream objStream = resp.GetResponseStream())
{
using (StreamReader objReader = new StreamReader(objStream, Encoding.UTF8))
{
Response = objReader.ReadToEnd();
objReader.Close();
}
objStream.Flush();
objStream.Close();
}
resp.Close();
}
}catch(WebException e)
{
Debug.Log(e.Message);
}
finally
{
request.Abort();
}
//tried this one after reading some related answers here on StackOverflow,without results
//GC.Collect();
Debug.Log("SERVER RESPONSE:" + Response);
//Response Handling
}
I know that it may be something related to a wrong abort on the HttpWebRequest / Response or maybe related to the HTTP 1.1 connections limit,but I can't figure out any solution at the moment.
Any help is appreciated.
I have a php service that generates XML. How can I parse the XML in C#? I tried using something like this:
WebRequest request = WebRequest.Create("http://devstage.jokeroo.com/rest.php");
request.Method = "GET";
request.ContentType = "text/html";
IAsyncResult result = request.BeginGetResponse(RequestCallback, request);
private void RequestCallback(IAsyncResult ar)
{
var request = ar.AsyncState as WebRequest;
Stream reader = request.EndGetResponse(ar).GetResponseStream();
//use this reader to read the content
}
But it keeps throwing this exception:
An exception of type 'System.Net.ProtocolViolationException' occurred in System.Windows.ni.dll but was not handled in user code
Any suggestions?
Get rid of this line:
request.ContentType = "text/html";
You're making a GET request so there is no request body; therefore, setting the content type (for a non-existent and non-supported HTTP request body) is what's causing your error.
I'm trying to retrieve the oauth access token to make calls to some google apis in asp.net mvc, and I wrote the following code for an action:
public ActionResult GetOAuthToken()
{
String url = "https://accounts.google.com/o/oauth2/token";
// Create a request using a URL that can receive a post.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
// Set the Method property of the request to POST.
request.Method = "POST";
request.Host = "accounts.google.com";
// Create POST data and convert it to a byte array.
string postData = String.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code", Request.QueryString["code"].ToString(), OAuthConfig.client_id, OAuthConfig.client_secret, OAuthConfig.token_redirect_uri);
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byteArray = encoding.GetBytes(postData);
// 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.
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 response.
WebResponse response = request.GetResponse();
// SOME CODE TO PROCESS THE RESPONSE
Response.Redirect("/Home");
return View();
}
OAuthConfig is just a class that contains the client id, client secret etc.
I keep getting 'The remote server returned an error: (400) Bad Request.' at the request.GetResponse() line. Where am I going wrong?
Google does provide a higher level library to work with its services, this handles the formatting of the urls and I find it makes it a lot easier to work with their apis. See http://code.google.com/p/google-api-dotnet-client/