I am using thread pool to call some asynchronous web request call for posting the data
I am calling RunWebAccess function in a for loop
public void RunWebAccess (string strdara, int inttype)
{
HttpWebRequest req =
(HttpWebRequest)WebRequest.Create("http://www.test.com");
byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(xmlvar);
req.Method = "POST";
req.ContentType = "text/xml";
req.ContentLength = requestBytes.Length;
IAsyncResult result =
req.BeginGetRequestStream(new AsyncCallback(ProcessResults), req);
}
private void ProcessResults(IAsyncResult result)
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
Stream postStream = request.EndGetRequestStream(result);
postStream.Write(result., 0, postData.Length ;
postStream.Close();
}
ProcessResults function is not working because it can not access the parameters.
The problem is I want to pass the parameters in ProcessResults function and write to stream.
As per code, I can not use global variable or read input in ProcessResults function.
(I want to pass the strdara,inttype in ProcessResults function)
You could use lambda-notation for the callback, something like this:
public void RunWebAccess (string strdara, int inttype)
{
HttpWebRequest req =
(HttpWebRequest)WebRequest.Create("http://www.test.com");
byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(xmlvar);
req.Method = "POST";
req.ContentType = "text/xml";
req.ContentLength = requestBytes.Length;
IAsyncResult result = null;
result =
req.BeginGetRequestStream(ar =>
{
Stream postStream = request.EndGetRequestStream(result);
postStream.Write(result., 0, postData.Length ;
postStream.Close();
}
, req);
}
You could send a new object, containing all the parameters that you want to pass to the callback. Like:
IAsyncResult result = req.BeginGetRequestStream(
new AsyncCallback(ProcessResults),
new Tuple<HttpWebRequest,byte[]>(req, postData));
Related
I have an http POST being actioned via a .NET System.Net.WebRequest as follows:
...
XXXUtilities.Log.WriteLog(string.Format("XXXHTTPPost PostToUri has uri={0}, body={1}", uri, messageBodyAsString));
System.Net.WebRequest req = System.Net.WebRequest.Create(uri);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(messageBodyAsString);
req.ContentLength = bytes.Length;
System.IO.Stream os = req.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
os.Close();
try
{
using (System.Net.WebResponse resp = req.GetResponse())
{
if (resp == null) return null;
System.IO.StreamReader sr =
new System.IO.StreamReader(resp.GetResponseStream());
string rs = sr.ReadToEnd().Trim();
sr.Close();
resp.Close();
XXXUtilities.Log.WriteLog(string.Format("XXXHTTPPost PostToUri has string response = {0}", rs));
MongoDB.Bson.BsonDocument doc2 = new BsonDocument();
doc2.Add("Response", rs);
return doc2;
}
}
catch (System.Net.WebException e)
{...
This all works fine most of the time. However, looking at the log files that this creates I spotted something strange. The suspect log entries look like this:
18:59:17.0608 HPSHTTPPost PostToUri has uri=https://salesforce.ringlead.com/cgi-bin/2848/3/dedup.pl, body=LastName=Doe&FirstName=Jon
18:59:17.5608 HPSHTTPPost PostToUri has string response = Success
18:59:18.0295 HPSHTTPPost PostToUri has string response = Success
It seems that the Http Response is being received twice. Is this even technically possible? i.e. is it possible for an Http POST to receive two Responses, one after the other? If so, is my code below then liable to be called twice, thus resulting in the observed log file entries? Many thanks.
Edit:
In response to the comment that the logging code may be broken, here is the logging code:
public class Log
{
public static void WriteLog(string commandText)
{
string clientDBName = "test";
string username = "test";
try
{
string filePath = "c:\\Data\\XXXLogs\\" + clientDBName + "logs\\";
string filename = System.DateTime.Now.ToString("yyyyMMdd_") + username + ".log";
DirectoryInfo dir = new DirectoryInfo(filePath);
if (!dir.Exists)
{
dir.Create();
}
System.IO.FileStream stream = new System.IO.FileStream(
filePath + filename
, System.IO.FileMode.Append); // Will create if not already exists
StreamWriter writer = new StreamWriter(stream);
writer.WriteLine(); // Writes a line terminator, thus separating entries by 1 blank line
writer.WriteLine(System.DateTime.Now.ToString("HH:mm:ss.ffff") + " " + commandText);
writer.Flush();
stream.Close();
}
catch { }
}
}
I am using Lymbix client library for sentiment analysis.
When I run the code I am getting an error in (WebResponse)httpRequest.GetResponse(): 401-Unauthorized
(available at https://github.com/lymbix/.NET-Wrapper)
The function containing 401 error is given below:
private static string Post(string url, string data, List<string> headers)
{
HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create(url);
httpRequest.Method = "POST";
httpRequest.Accept = "application/json";
httpRequest.ContentType = "application/x-www-form-urlencoded";
if (headers != null)
{
foreach (string header in headers)
{
httpRequest.Headers.Add(header);
}
}
// write request?
byte[] postData = Encoding.UTF8.GetBytes(data.ToString());
httpRequest.ContentLength = postData.Length;
httpRequest.GetRequestStream().Write(postData, 0, postData.Length);
// read response
WebResponse webResponse = (WebResponse)httpRequest.GetResponse();
StreamReader webResponseStream = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8);
return webResponseStream.ReadToEnd();
}
It's saying you're not authorized, so you need to provide credentials.
HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create(url);
httpRequest.Method = "POST";
httpRequest.Accept = "application/json";
httpRequest.ContentType = "application/x-www-form-urlencoded";
httpRequest.Credentials = new NetworkCredential("username","password");
httpRequest.UseDefaultCredentials = false; //the default is false, but I included it here just to illustrate that it needs to be false in order to use the specified credentials
There are currently 1205 resources (citations) in the SciTS Mendeley group. However, no matter how we call the “getDocuments” method of the API, we only get the first 1000 resources. Is there a specific parameter we need to pass to get the full list of resources? Or is there a way to make a subsequent call that gets data pages not returned by the first call?
string grantType = "client_credentials";
string applicationID = "id";
string clientsecret = "XXXXXXX";
string redirecturi = "*******";
string url = "https://api-oauth2.mendeley.com/oauth/token";
string view = "all";
string group_id = "f7c0e437-f68b-34df-83c7-2877147ba8f9";
HttpWebResponse response = null;
try
{
// Create the data to send
StringBuilder data = new StringBuilder();
data.Append("client_id=" + Uri.EscapeDataString(applicationID));
data.Append("&client_secret=" + Uri.EscapeDataString(clientsecret));
data.Append("&redirect_uri=" + Uri.EscapeDataString(redirecturi));
data.Append("&grant_type=" + Uri.EscapeDataString(grantType));
data.Append("&response_type=" + Uri.EscapeDataString("code"));
data.Append("&scope=" + Uri.EscapeDataString("all"));
byte[] byteArray = Encoding.UTF8.GetBytes(data.ToString());
// Setup the Request
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
// Write data
Stream postStream = request.GetRequestStream();
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Send Request & Get Response
response = (HttpWebResponse)request.GetResponse();
string accessToken;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
// Get the Response Stream
string json = reader.ReadLine();
Console.WriteLine(json);
// Retrieve and Return the Access Token
JavaScriptSerializer ser = new JavaScriptSerializer();
Dictionary<string, object> x = (Dictionary<string, object>)ser.DeserializeObject(json);
accessToken = x["access_token"].ToString();
}
// Console.WriteLine("Access TOken"+ accessToken);
var apiUrl = "https://api-oauth2.mendeley.com/oapi/documents/groups/3556001/docs/?details=true&items=1250";
try
{
request = (HttpWebRequest)WebRequest.Create(apiUrl);
request.Method = "GET";
request.Headers.Add("Authorization", "Bearer " + accessToken);
request.Host = "api-oauth2.mendeley.com";
response = (HttpWebResponse)request.GetResponse();
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
// Get the Response Stream
string json = reader.ReadLine();
Console.WriteLine(json);
//need this to import documents
}
}
catch (WebException ex1)
{
Console.WriteLine("Access TOken exception" + ex1.Message);
}
}
catch (WebException e)
{
if (e.Response != null)
{
using (HttpWebResponse err = (HttpWebResponse)e.Response)
{
Console.WriteLine("The server returned '{0}' with the status code '{1} ({2:d})'.",
err.StatusDescription, err.StatusCode, err.StatusCode);
}
}
}
The default number of items returned is limited to 1000 per page. For a paginated response you should get some additional fields in the response; notably 'items_per_page','total_pages','total_results'.
I suspect you have will two pages and to get the next result you need to append 'page=1'.
Im trying to get the string response from this request:
void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
string postData = "{\"email\":\"yudelsuarez#gmail.com\", \"password\":\"1234\"}";
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Write to the request stream.
postStream.Write(byteArray, 0, postData.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();
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.tremendamuela.com/beta/index.php/api/Account");
request.ContentType = "application/json";
// Set the Method property to 'POST' to post data to the URI.
request.Method = "PUT";
// start the asynchronous operation
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
}
the problem is that I dont know how to save the string....cos thats an async method it doesnt' let me modify a textBlock in the pag or save it with a StreamWriter.
cos thats an async method it doesnt' let me modify a textBlock in the
pag or save it with a StreamWriter.
Try:
Dispatcher.BeginInvoke(() =>
{
textBlock.Text = responseString;
});
I have a xml string that return from Post method:
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
HttpStatusCode rcode = response.StatusCode;
var stream = new GZipInputStream(response.GetResponseStream());
using (StreamReader reader = new StreamReader(stream))
{
responseString = reader.ReadToEnd();
}
response.Close();
}
The responseString is the string I want to parse, using parseXmlString class below. However I can't call the method parseXmlString directly because of the static. How can I pass the responseString to the parseXmlString method to have them parse out and bind to the listBox. Or anyway to have the same result would be great.
void parseXmlString()
{
byte[] byteArray = Encoding.UTF8.GetBytes(responseString);
MemoryStream str = new MemoryStream(byteArray);
str.Position = 0;
XDocument xdoc = XDocument.Load(str);
var data = from query in xdoc.Descendants("tracks").Elements("item")
select new searchResult
{
artist = (string)query.Element("artist"),
album = (string)query.Element("album"),
track = (string)query.Element("track"),
// artistA = (string)query.Element("artists").Element("artist"),
};
// ListBox lb = new ListBox();
listBox1.ItemsSource = data;
var data1 = from query in xdoc.Descendants("artists").Elements("item")
select new searchResult
{
artistA = (string)query.Element("artist"),
};
listBox2.ItemsSource = data1;
}
Your approach is inversed logic. You know that you can have return values on methods, right?-)
What you need to do is let your ParseXmlString method take the responseString as a parameter, and let it return the created IEnumerable, like this:
private IEnumerable<SearchResult> ParseXmlString(responseString)
{
XDocument xdoc = XDocument.Load(responseString);
var data =
from query in xdoc.Descendants("tracks").Elements("item")
select new SearchResult
{
Artist = (string)query.Element("artist"),
Album = (string)query.Element("album"),
Track = (string)query.Element("track"),
};
return
from query in xdoc.Descendants("artists").Elements("item")
select new SearchResult
{
ArtistA = (string)query.Element("artist"),
};
}
And change your async code handling, to perform a callback to your UI thread, when it's done reading out the responseString.
Then, on your UI thread, you would do:
// This being your method to get the async response
GetResponseAsync(..., responseString =>
{
var searchResults = ParseXmlString(responseString);
listBox2.ItemsSource = searchResults;
})
You can see this answer, if you need some basic understanding of callbacks: Callbacks in C#