ASP.NET Authorization from Console Application & Timeout
For what its worth, I managed to get a console application to authenticate itself with an existing ASP.NET web application. It just mimics the login page by making a post request to the login page containing the viewstate information (just as if a browser had made the request).
It then catches the cookie sent back in response in a CookieContainer.
The application then goes on to make multiple requests to the same page (which requires authorization). The page does some work and writes out a file on the server.
The problem I'm encountering is that after the phony login, the first two requests go through okay. The third request never even receives a response. Below is the code I'm using to make the requests:
To login:
private static CookieContainer PerformLoginRequest()
{
string loginURL = "http://www.myDomain.com/mySite/login.aspx";
//Set up the request and give it a cookie container.
CookieContainer cookieJar = new CookieContainer();
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(loginURL);
request.CookieContainer = cookieJar;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
//Grab the request body so we can put important information in it.
Stream requestBody = request.GetRequestStream();
string postData = "__VIEWSTATE=GIBBERISH&UserName=USERNAME&Password=PASSWORD%21&LoginButton.x=0&LoginButton.y=0";
//Throw the string into the body.
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byte1 = encoding.GetBytes(postData);
requestBody.Write(byte1, 0, byte1.Length);
requestBody.Close();
//Get the response to the login request.
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string result = reader.ReadToEnd();
reader.Close();
return cookieJar;
}
To request a page:
private static long RequestPage(string url)
{
//If we've already got a CookieContainer, then we've logged in already. Otherwise, log in.
if (cookieJar == null)
{
try
{
cookieJar = PerformLoginRequest();
}
catch
{
throw;
}
}
//Set up the request.
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.CookieContainer = cookieJar;
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = timeout; //5 minutes.
WebResponse response = request.GetResponse();
return response.ContentLength;
}
The cookieJar and timeout variables are global to the application.
Any idea what would cause this?
Update (2010-01-17, 3:30 PM EST)
When I launch the application with Fiddler running, everything goes through fine. All the requests function, just as I would expect.
I inspected the IIS log files. In them I can see the intial login request, the redirect after login, and the requests for the first two pages. But after that...nothing. It's like the requests don't even make it to the web server.
Update (2010-01-18, 11:29 AM EST)
I updated the code up top to reflect the changes suggested by Chris B. Behrens. But to no avail. In case it matters, the loop that calls the above functions looks like this:
private static void RegenerateNecessaryForms(MyEntities context)
{
var items = context.Items.Where(i => i.NeedsProcessing == true);
var area = context.Areas;
foreach (Item i in items)
{
bool success = true;
foreach (Area area in areas)
{
try
{
string url = string.Format("http://{0}/mySite/process.aspx?item={1}&area={2}", targetDomain, i.ItemName, area.AreaName);
long result = RequestPage(url, m);
}
catch
{
success = false;
}
}
if (success)
{
i.NeedsProcessing = false;
}
}
}
Update (2010-01-18, 1:03 PM EST) This is probably the most useful information I've been able to provide so far.
I was looking at the IIS logs again. When the login request is sent, I can flush the logs and it shows up immediately. However, none of the page开发者_如何学JAVA requests show up until I close the console application. Here's the relevant bit of the log:
2011-01-18 17:44:54 X.X.X.X POST /MySite/login.aspx - 80 - X.X.X.X - 302 0 0 148
2011-01-18 17:44:54 X.X.X.X GET /MySite/default.aspx - 80 AutomatedUser X.X.X.X - 200 0 0 48
2011-01-18 17:54:33 X.X.X.X GET /MySite/process.aspx model=ITEM_ONE&area=US 80 AutomatedUser X.X.X.X - 200 0 995 579100
2011-01-18 17:54:33 X.X.X.X GET /MySite/process.aspx model=ITEM_ONE&area=CANADA 80 AutomatedUser X.X.X.X - 200 0 995 553247
2011-01-18 17:54:33 X.X.X.X GET /MySite/process.aspx model=ITEM_TWO&area=US 80 AutomatedUser X.X.X.X - 200 0 995 532824
Each of the GET requests to process.aspx corresponds to a call to the RequestPage method above. The line "request.GetResponse();" only takes about 10 seconds or so, but it looks like somehow that request never gets completed (at least according to IIS) until I close the application. (If you look at the last number on each line, that's the amount of time it took to serve the page in milliseconds, but I got the response back in the application in much less time than that.) So it's possible (probably even likely) that IIS is restricting the amount of connections it will accept from one IP.
Which brings me to the question: What is it about the requests that I'm making that causes them to stay "open" like that?
The requests don't return an HTML page (if that matters) they return a PDF.
You're not explicitly closing your request:
//Get the response to the login request.
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string result = reader.ReadToEnd();
reader.Close();
return cookieJar;
See if that does the trick.
精彩评论