C# Multiple http requests same PHP session - c#

I'm trying to get the picture to load in the same PHP session in which the POST request will be sent.
But because i'm using button1_Click this is not possible.
And the outcome is to get the picture to load before the data is sent.
If you got any questions please ask.
i know i go wrong with the picture loading, but i dont know exactly where..
using visual c# 2010 express winforms
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.ImageLocation = "http://localhost/proj/guess-my-fav/1.jpg";
}
private void button1_Click(object sender, EventArgs e)
{
Uri uri = new Uri("http://localhost/proj/guess-my-fav/level14.php");
var answer = textBox1.Text;
string data = "guess=" + answer + "&level=14&time=opt";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Post;
request.CookieContainer = new CookieContainer();
request.KeepAlive = true;
request.ContentLength = data.Length;
request.ContentType = "application/x-www-form-urlencoded";
StreamWriter writer = new StreamWriter(request.GetRequestStream());
writer.Write(data);
writer.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string tmp = reader.ReadToEnd();
response.Close();
richTextBox1.AppendText(tmp); // log - delete this line
}
How can i put the rendering of image under the second request?

pictureBox1.ImageLocation = "http://localhost/proj/guess-my-fav/1.jpg";
This is going to cause the client's browser to make a request for 1.jpg
Uri uri = new Uri("http://localhost/proj/guess-my-fav/level14.php");
...
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
This is going to cause the webserver running the ASP.NET website to make a request for level14.php
You're not going to get those two requests using the same session since they'll be coming from two different machines!
You might like to look into moving that HttpWebRequest code out of the back end, and reimplementing it on the client side as an AJAX request. Then both requests will be coming from the client's browser.

If you modify your code to match
private CookieContainer cookieContainer;
private void Form1_Load(object sender, EventArgs e)
{
var wr = (HttpWebRequest)WebRequest.Create("http://localhost/proj/guess-my-fav/1.jpg");
cookieContainer = new CookieContainer();
wr.CookieContainer = this.cookieContainer;
var resp = (HttpWebResponse)wr.GetResponse();
wr.CookieContainer = cookieContainer;
using (var s = resp.GetResponseStream())
{
pictureBox1.Image = new Bitmap(s);
}
}
private void button1_Click(object sender, EventArgs e)
{
Uri uri = new Uri("http://localhost/proj/guess-my-fav/level14.php");
var answer = textBox1.Text;
string data = "guess=" + answer + "&level=14&time=opt";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Post;
request.CookieContainer = cookieContainer;
request.KeepAlive = true;
request.ContentLength = data.Length;
request.ContentType = "application/x-www-form-urlencoded";
StreamWriter writer = new StreamWriter(request.GetRequestStream());
writer.Write(data);
writer.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string tmp = reader.ReadToEnd();
response.Close();
richTextBox1.AppendText(tmp); // log - delete this line
}
This should make both requests to the server using the same session.
Hope this helps.

I am assuming here that you want to re-load the image when you click the button.
First of all that ImageLocation property is probably not gonna respect your session cookie, so you might have to download the image manually. You already used a CookieContainer so that's a good start.
What we want to do here is use a new HttpWebRequest to download the image and attach the same CookieContainer to it as this one should hold the session id after your first call.
We can then use the HttpWebResponse to create an Image object and assign this to the pictureBox1.Image property.
All this together might look something like this:
private void button1_Click(object sender, EventArgs e)
{
Uri uri = new Uri("http://localhost/proj/guess-my-fav/level14.php");
var answer = textBox1.Text;
string data = "guess=" + answer + "&level=14&time=opt";
CookieContainer cookies = new CookieContainer(); /* we want to have this for other call also
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Post;
request.CookieContainer = cookies;
request.KeepAlive = true;
request.ContentLength = data.Length;
request.ContentType = "application/x-www-form-urlencoded";
StreamWriter writer = new StreamWriter(request.GetRequestStream());
writer.Write(data);
writer.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string tmp = reader.ReadToEnd();
response.Close();
richTextBox1.AppendText(tmp); // log - delete this line
HttpWebRequest request2 = (HttpWebRequest)HttpWebRequest.Create("http://localhost/proj/guess-my-fav/1.jpg");
request2.CookieContainer = cookies;
HttpWebResponse response2 = (HttpWebResponse)request.GetResponse();
pictureBox1.Image = Image.LoadFromStream(response2.GetResponseStream());
}

Related

"Stream not Writable" error when using StreamWriter in loop

I'm trying to write a tool in C# to help QA some network issues, and am running into a problem. The program is supposed to send a query in JSON format to the server every second.
Currently, it works once, but on the second attempt to send the query, I get an exception because the
"Stream was not writable."
Here's my code:
public partial class Form1 : Form
{
Timer timer1;
String query;
String result;
HttpWebRequest request;
StreamWriter writeData;
StreamReader readData;
HttpWebResponse response;
public Form1()
{
InitializeComponent();
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 1000;
File.Delete(AppDomain.CurrentDomain.BaseDirectory + "log.txt");
logOutput.ReadOnly = true;
request = (HttpWebRequest)WebRequest.Create("a URL goes here");
request.ContentType = "application/json";
request.Method = "POST";
query = "{some json stuff goes here}";
}
private void startButton_Click(object sender, EventArgs e)
{
if (!timer1.Enabled)
{
timer1.Start();
startButton.Text = "Stop";
}
else
{
timer1.Stop();
startButton.Text = "Start";
}
}
private void timer1_Tick(object sender, EventArgs e)
{
writeData = new StreamWriter(request.GetRequestStream());
writeData.Write(query);
writeData.Flush();
writeData.Close();
response = (HttpWebResponse)request.GetResponse();
readData = new StreamReader(response.GetResponseStream());
result = readData.ReadToEnd();
logOutput.Text = result;
File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + "log.txt", result + "\r\n");
}
}
}
Anyone know what I'm doing wrong?
First off, Stop with the global variables. Move the streamwriter, streamreader, httpwebresponse etc into the actual tick method.
Anything that implements IDisposable, which most of that stuff does, should be very local variables that aren't hanging around and are wrapped up in using clauses.
Basically your request object is closed out once your method has finished.
Something like this will work a LOT better:
private void timer1_Tick( object sender, EventArgs e ) {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("a URL goes here");
request.ContentType = "application/json";
request.Method = "POST";
String query = "{some json stuff goes here}";
String result = String.Empty;
using ( StreamWriter writeData = new StreamWriter(request.GetRequestStream()) ) {
writeData.Write(query);
writeData.Flush();
using ( HttpWebResponse response = (HttpWebResponse)request.GetResponse() ) {
using ( StreamReader readData = new StreamReader(response.GetResponseStream()) ) {
result = readData.ReadToEnd();
}
}
}
logOutput.Text = result;
File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + "log.txt", result + "\r\n");
}
}
So I presume it's the writeData.Write(query) that's throwing? request.GetRequestStream() should only be writeable until the request is actually sent, which I believe is done when you call request.GetResponse(). So it works on the first tick, but then sends the request and can't write the second time.
Are you trying to send the request multiple times? You would need to reinitialize the request object.
Similar issue causes if you do not reinitialize the request. As mentioned by ryachza i have pushed request initialization inside loop and it worked for me.
foreach (String item in DATA)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "application/json";
using (Stream webStream = request.GetRequestStream())
using (StreamWriter requestWriter = new StreamWriter(webStream, System.Text.Encoding.ASCII))
{
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
Object routes_list =
json_serializer.DeserializeObject(item);
requestWriter.Write(item);
}
WebResponse webResponse = request.GetResponse();
using (Stream webStream = webResponse.GetResponseStream() ?? Stream.Null)
using (StreamReader responseReader = new StreamReader(webStream))
{
response.Add(responseReader.ReadToEnd());
}
}

C# How can I call multiple POST, GET requests with same cookie via HttpWebRequest?

my question is, how can I call multiple requests via HttpWebRequest with same authenticate cookie in C#? I tried a lot of times but for now I dunno how to do it :/
My code is below:
var postData = "method=loginFormAccount&args[0][email]=###&args[0][pass]=###&args[0][cache]=37317&args[]=1";
var data = Encoding.ASCII.GetBytes(postData);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("###");
request.CookieContainer = new CookieContainer();
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.AllowAutoRedirect = true;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var cookies = new CookieContainer();
cookies.Add(response.Cookies);
System.IO.File.WriteAllText(#desktop + "\\post.html", new StreamReader(response.GetResponseStream()).ReadToEnd());
// =================================== END LOGIN ==================================== \\
System.IO.File.WriteAllText(#desktop + "\\cookie.html","");
foreach (Cookie cook in response.Cookies)
{
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#desktop + "\\cookie.html", true))
{
file.WriteLine(cook.ToString());
}
// Show the string representation of the cookie.
}
HttpWebRequest requestNext = (HttpWebRequest)WebRequest.Create("####");
requestNext.CookieContainer = cookies;
requestNext.Method = "GET";
HttpWebResponse responseNext = (HttpWebResponse)requestNext.GetResponse();
//var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
System.IO.File.WriteAllText(#desktop + "\\get.html", new StreamReader(responseNext.GetResponseStream()).ReadToEnd());
My main problem is that, cookie which I'm getting is the cookie BEFORE authenticate so I must to do something to get cookie AFTER authenticate.
Try this :
HttpWebRequest requestNext = (HttpWebRequest)WebRequest.Create("####");
requestNext.CookieContainer.Add(cookies);

Server Not Found 404 in Application to read data from api But without passing parameters it works

I got one more question related to api I'm working on :p
My problem is that the application i made to read the data works perfectly when the url is all passed, but if i want to pass the general url + parameters it doesn't...
Code with Full URL
private void btn_Api_Click(object sender, EventArgs e)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://MyIP/api/Employee/?FirstName=Jorge");
request.Method = "POST";
string postData = "";
byte[] data = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.Accept = "application/json";
request.ContentLength = data.Length;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(data, 0, data.Length);
}
try
{
using (WebResponse response = request.GetResponse())
{
var responseValue = string.Empty;
// grab the response
using (var responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream))
{
responseValue = reader.ReadToEnd();
}
}
if (responseValue != "")
{
string _txtFileNew = #"C:\Users\Jorge.Leite\Documents\teste\" + txt_First.Text + ".txt"; //+txt_Last.Text + ".txt";
StreamWriter _srEannew = new StreamWriter(_txtFileNew);
_srEannew.WriteLine(responseValue);
_srEannew.Close();
}
}
}
catch (WebException ex)
{
// Handle error
}
Code with Url + parameters later PS: postData is passing the correct string ("?FirstName=Jorge") Jorge is the input Name
private void btn_Api_Click(object sender, EventArgs e)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("MyIP/api/Employee/");
request.Method = "POST";
string postData = string.Format("?FirstName=" + txt_First.Text);
byte[] data = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.Accept = "application/json";
request.ContentLength = data.Length;
When using this code it has an exception server not found 404
I really don't know what going on with this :\
Thank you in advance
Web API with POST methods do not work as smooth as with GET methods.
Check this other link to know a bit more Reading FromUri and FromBody at the same time

How to use Asp.net 1.1 webrequest like java apache httpclient?

I am new in asp.net and I have asp.net 1.1 in my server.
I want to do in background --> login to another site and navigate in it <-- to retrieve some information needed to process in my page.
With Apache httpclient I can maintain the login session at background and navigate how much time I need and get elements by id, class, name (td,tr,etc) with Jsoup (a parser)
Until now I can just retrieve the whole code from the other page with that, but when I try to go to other page using CookieContainer it still doesn't work:
I did this example to show what I trying to do..
protected void Page_Load(object sender, EventArgs e)
{
CookieContainer cookieJar = new CookieContainer();
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://www.4shared.com/web/login/validate");
req.Method = "POST";
req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
req.Headers.Add("Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7");
req.KeepAlive = true;
req.Headers.Add("Keep-Alive: 300");
req.AllowAutoRedirect = false;
req.ContentType = "application/x-www-form-urlencoded";
req.CookieContainer = cookieJar;
String Username = "user%40email.com";
String PassWord = "password";
StreamWriter sw = new StreamWriter(req.GetRequestStream());
sw.Write("login=" + Username + "&password=" + PassWord);
sw.Close();
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(1255));
string tmp = reader.ReadToEnd();
HttpWebRequest req2 = (HttpWebRequest)HttpWebRequest.Create("http://www.4shared.com/account/home.jsp");
req2.Method = "GET";
req2.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
req2.Headers.Add("Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7");
req2.KeepAlive = true;
req2.Headers.Add("Keep-Alive: 300");
req2.CookieContainer = cookieJar;
req2.ContentType = "text/html";
HttpWebResponse response2 = (HttpWebResponse)req2.GetResponse();
StreamReader reader2 = new StreamReader(response2.GetResponseStream(), Encoding.GetEncoding(1255));
string tmp2 = reader2.ReadToEnd();
response2.Close();
Panel2.Text = tmp2;
}
I need to retrieve the page login and show a captcha, and then POST with login info, and after that navigate to get some necessary to process in my page.
What I can't do is navigate to another page. And before that get some elements from response.

How to pass cookies to HtmlAgilityPack or WebClient?

I use this code to login:
CookieCollection cookies = new CookieCollection();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("example.com");
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(cookies);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
cookies = response.Cookies;
string getUrl = "example.com";
string postData = String.Format("my parameters");
HttpWebRequest getRequest = (HttpWebRequest)WebRequest.Create(getUrl);
getRequest.CookieContainer = new CookieContainer();
getRequest.CookieContainer.Add(cookies);
getRequest.Method = WebRequestMethods.Http.Post;
getRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0";
getRequest.AllowWriteStreamBuffering = true;
getRequest.ProtocolVersion = HttpVersion.Version11;
getRequest.AllowAutoRedirect = true;
getRequest.ContentType = "application/x-www-form-urlencoded";
byte[] byteArray = Encoding.ASCII.GetBytes(postData);
getRequest.ContentLength = byteArray.Length;
Stream newStream = getRequest.GetRequestStream();
newStream.Write(byteArray, 0, byteArray.Length);
newStream.Close();
HttpWebResponse getResponse = (HttpWebResponse)getRequest.GetResponse();
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream(), Encoding.GetEncoding("windows-1251")))
{
doc.LoadHtml(sr.ReadToEnd());
webBrowser1.DocumentText = doc.DocumentNode.OuterHtml;
}
then I want to use HtmlWeb (HtmlAgilityPack) or Webclient to parse the HTML to HtmlDocument(HtmlAgilityPack).
My problem is that when I use:
WebClient wc = new WebClient();
webBrowser1.DocumentText = wc.DownloadString(site);
or
doc = web.Load(site);
webBrowser1.DocumentText = doc.DocumentNode.OuterHtml;
The login disappear so i think I must somehow pass the cookies.. Any suggestions?
Check HtmlAgilityPack.HtmlDocument Cookies
Here is an example of what you're looking for (syntax not 100% tested, I just modified some class I usually use):
public class MyWebClient
{
//The cookies will be here.
private CookieContainer _cookies = new CookieContainer();
//In case you need to clear the cookies
public void ClearCookies() {
_cookies = new CookieContainer();
}
public HtmlDocument GetPage(string url) {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
//Set more parameters here...
//...
//This is the important part.
request.CookieContainer = _cookies;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var stream = response.GetResponseStream();
//When you get the response from the website, the cookies will be stored
//automatically in "_cookies".
using (var reader = new StreamReader(stream)) {
string html = reader.ReadToEnd();
var doc = new HtmlDocument();
doc.LoadHtml(html);
return doc;
}
}
}
Here is how you use it:
var client = new MyWebClient();
HtmlDocument doc = client.GetPage("http://somepage.com");
//This request will be sent with the cookies obtained from the page
doc = client.GetPage("http://somepage.com/another-page");
Note: If you also want to use POST method, just create a method similar to GetPage with the POST logic, refactor the class, etc.
There are some recommendations here: Using CookieContainer with WebClient class
However, it's probably just easier to keep using the HttpWebRequest and set the cookie in the CookieContainer:
HTTPWebRequest and CookieContainer
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.cookiecontainer.aspx
The code looks something like this:
// Create a HttpWebRequest
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(getUrl);
// Create the cookie container and add a cookie
request.CookieContainer = new CookieContainer();
// Add all the cookies
foreach (Cookie cookie in response.Cookies)
{
request.CookieContainer.Add(cookie);
}
The second thing is that you don't need to download the site again, since you already have it from your web response and you're saving it here:
HttpWebResponse getResponse = (HttpWebResponse)getRequest.GetResponse();
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream(), Encoding.GetEncoding("windows-1251")))
{
webBrowser1.DocumentText = doc.DocumentNode.OuterHtml;
}
You should be able to just take the HTML and parse it with the HTML Agility Pack:
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(webBrowser1.DocumentText);
And that should do it... :)
Try caching cookies from previous response locally and resend them each web request as follows:
private CookieCollection cookieCollection;
...
parserObject = new HtmlWeb
{
AutoDetectEncoding = true,
PreRequest = request =>
{
if (cookieCollection != null)
cookieCollection.Cast<Cookie>()
.ForEach(cookie => request.CookieContainer.Add(cookie));
return true;
},
PostResponse = (request, response) => { cookieCollection = response.Cookies; }
};

Categories

Resources