Big files uploading (WebException: The connection was closed unexpectedly) - c#

UPDATED
See post #3 below.
There is a need to upload a file to the web automatically (without browser). Host - Mini File Host v1.2 (if this does matter). Didn't find specific api in documentation, so at first i sniffed browser requests in Firebug as follows :
Params : do
Value : verify
POST /upload.php?do=verify HTTP/1.1
Host: webfile.ukrwest.net
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; ru; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8 (.NET CLR 4.0.20506)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://filehoster.awardspace.com/index.php
Content-Type: multipart/form-data; boundary=---------------------------27368237179714
Content-Length: 445
-----------------------------27368237179714
Content-Disposition: form-data; name="upfile"; filename="Test.file"
Content-Type: application/octet-stream
12345678901011121314151617sample text
-----------------------------27368237179714
Content-Disposition: form-data; name="descr"
-----------------------------27368237179714
Content-Disposition: form-data; name="pprotect"
-----------------------------27368237179714--
Here we can see parameter, headers, content type and chunks of information (1 - file name and type, 2 - file contents, 3 - additional params - description and password, not necessarily applied).
So i've created a class that emulates such a behaviour step by step : HttpWebRequest on the url, apply needed parameters to request, form request strings with StringBuilder and convert them to byte arrays, read a file using FileStream, putting all that stuff to MemoryStream and then writing it to request (took major part of a code from an article at CodeProject where it uploads a file to Rapidshare host).
Neat and tidy, but... It doesn't seem to work :(. As result it returns initial upload page, not a result page with links i could parse and present to a user...
Here are main methods of an Uploader class :
// Step 1 - request creation
private HttpWebRequest GetWebrequest(string boundary)
{
Uri uri = new Uri("http://filehoster.awardspace.com/index.php?do=verify");
System.Net.HttpWebRequest httpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri);
httpWebRequest.CookieContainer = _cookies;
httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
httpWebRequest.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.2; ru; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8 (.NET CLR 4.0.20506)";
httpWebRequest.Referer = "http://filehoster.awardspace.com/index.php";
httpWebRequest.Method = "POST";
httpWebRequest.KeepAlive = true;
httpWebRequest.Timeout = -1;
//httpWebRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
httpWebRequest.Headers.Add("Accept-Charset", "windows-1251,utf-8;q=0.7,*;q=0.7");
httpWebRequest.Headers.Add("Accept-Encoding", "gzip,deflate");
httpWebRequest.Headers.Add("Accept-Language", "ru,en-us;q=0.7,en;q=0.3");
//httpWebRequest.AllowAutoRedirect = true;
//httpWebRequest.ProtocolVersion = new Version(1,1);
//httpWebRequest.SendChunked = true;
//httpWebRequest.Headers.Add("Cache-Control", "no-cache");
//httpWebRequest.ServicePoint.Expect100Continue = false;
return httpWebRequest;
}
// Step 2 - first message part (before file contents)
private string GetRequestMessage(string boundary, string FName, string description, string password)
{
System.Text.StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("--");
stringBuilder.Append(boundary);
stringBuilder.Append("\r\n");
stringBuilder.Append("Content-Disposition: form-data; name=\"");
stringBuilder.Append("upfile");
stringBuilder.Append("\"; filename=\"");
stringBuilder.Append(FName);
stringBuilder.Append("\"");
stringBuilder.Append("\r\n");
stringBuilder.Append("Content-Type: application/octet-stream");
stringBuilder.Append("\r\n");
return stringBuilder.ToString();
}
// Step 4 - additional request parameters. Step 3 - reading file is in method below
private string GetRequestMessageEnd(string boundary)
{
System.Text.StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(boundary);
stringBuilder.Append("\r\n");
stringBuilder.Append("Content-Disposition: form-data; name=\"descr\"");
stringBuilder.Append("\r\n");
stringBuilder.Append("\r\n");
stringBuilder.Append("Default description");
stringBuilder.Append("\r\n");
stringBuilder.Append(boundary);
stringBuilder.Append("\r\n");
stringBuilder.Append("Content-Disposition: form-data; name=\"pprotect\"");
stringBuilder.Append("\r\n");
stringBuilder.Append("\r\n");
stringBuilder.Append("");
stringBuilder.Append("\r\n");
stringBuilder.Append(boundary);
stringBuilder.Append("--");
//stringBuilder.Append("\r\n");
//stringBuilder.Append(boundary);
//stringBuilder.Append("\r\n");
return stringBuilder.ToString();
}
// Main method
public string ProcessUpload(string FilePath, string description, string password)
{
// Chosen file information
FileSystemInfo _file = new FileInfo(FilePath);
// Random boundary generation
DateTime dateTime2 = DateTime.Now;
long l2 = dateTime2.Ticks;
string _generatedBoundary = "----------" + l2.ToString("x");
// Web request creation
System.Net.HttpWebRequest httpWebRequest = GetWebrequest(_generatedBoundary);
// Main app block - form and send request
using (System.IO.FileStream fileStream = new FileStream(_file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] bArr1 = Encoding.ASCII.GetBytes("\r\n--" + _generatedBoundary + "\r\n");
// Generating pre-content post message
string firstPostMessagePart = GetRequestMessage(_generatedBoundary, _file.Name, description, password);
// Writing first part of request
byte[] bArr2 = Encoding.UTF8.GetBytes(firstPostMessagePart);
Stream memStream = new MemoryStream();
memStream.Write(bArr1, 0, bArr1.Length);
memStream.Write(bArr2, 0, bArr2.Length);
// Writing file
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
memStream.Write(buffer, 0, bytesRead);
}
// Generating end of a post message
string secondPostMessagePart = GetRequestMessageEnd(_generatedBoundary);
byte[] bArr3 = Encoding.UTF8.GetBytes(secondPostMessagePart);
memStream.Write(bArr3, 0, bArr3.Length);
// Preparing to send
httpWebRequest.ContentLength = memStream.Length;
fileStream.Close();
Stream requestStream = httpWebRequest.GetRequestStream();
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
// Sending request
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
requestStream.Close();
}
// Delay (?)
System.Threading.Thread.Sleep(5000);
// Getting response
string strResponse = "";
using (Stream stream = httpWebRequest.GetResponse().GetResponseStream())
using (StreamReader streamReader = new StreamReader(stream/*, Encoding.GetEncoding(1251)*/))
{
strResponse = streamReader.ReadToEnd();
}
return strResponse;
}
Plays with ProtocolVersion (1.0, 1.1), AllowAutoRedirect (true/false), even known ServicePoint.Expect100Continue (false) didn't fix an issue. Even a 5sec timeout before getting response (thought in case of a big file it doesn't uploads so quick) didn't help.
Content type "octet-stream" was chosen by purpose to upload any file (could use some switch for most popular jpg/zip/rar/doc etc., but that one seems universal). Boundary is generated randomly from timer ticks, not a big deal. What else? :/
I could give up and forget this, but i feel i'm pretty close to solve and then forget about it :P.
In case you need the whole application to run and debug - here it is (70kb, zipped C# 2.0 VS2k8 solution, no ads, no viruses) :
#Mediafire
#FileQube
#FileDropper

Update : nope, there is no redirect.
screenshot
Read RFC2388 few times, rewrote the code and it finally worked (i guess the trouble was in utf-read trailing boundary instead of correct 7 bit ascii). Hooray? Nope :(. Only small files are transfered, big ones throwing "The connection was closed unexpectedly".
System.Net.WebException was unhandled by user code
Message="The underlying connection was closed: The connection was closed unexpectedly."
Source="Uploader"
StackTrace:
at Uploader.Upload.ProcessUpload(String FilePath, String description, String password) in F:\MyDocuments\Visual Studio 2008\Projects\Uploader\Uploader.cs:line 96
at Uploader.Form1.backgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in F:\MyDocuments\Visual Studio 2008\Projects\Uploader\Form1.cs:line 45
at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
I know that's a bug with .net stack and few solutions exists :
increase both Timeout and ReadWriteTimeout of a request
assign request.KeepAlive = false and System.Net.ServicePointManager.Expect100Continue = false
set ProtocolVersion to 1.0
But neither one of them nor all of them altogether help in my case. Any ideas?
EDIT - Source code:
// .. request created, required params applied
httpWebRequest.ProtocolVersion = HttpVersion.Version10; // fix 1
httpWebRequest.KeepAlive = false; // fix 2
httpWebRequest.Timeout = 1000000000; // fix 3
httpWebRequest.ReadWriteTimeout = 1000000000; // fix 4
// .. request processed, data written to request stream
string strResponse = "";
try
{
using (WebResponse httpResponse = httpWebRequest.GetResponse()) // error here
{
using (Stream responseStream = httpResponse.GetResponseStream())
{
using (StreamReader streamReader = new StreamReader(responseStream))
{
strResponse = streamReader.ReadToEnd();
}
}
}
}
catch (WebException exception)
{
throw exception;
}

"As result it returns initial upload page, not a result page with links i could parse and present to a user..."
Maybe that's just the behaviour of the upload functionality: that after the upload has finished, you can upload another file?
I think you have to call another url for the "browse for file"-page (I suppose that's the one you need).
Edit: Actually, if the server sends a "redirect" (http 3xx), that's something the browser has to handle, so if you're working with your own client application in stead of a browser, you'll have to implement redirection yourself. Here the rfc for more information.

Try setting the maxRequestLength property of the httpRuntime element in the Web.config.

In my case, duplicate filename causing the issue as well. I save the file's settings in an xml file but the name setting is duplicating each other.
<field name="StillImage">
<prefix>isp_main_</prefix>
<suffix>308</suffix>
<width>1080</width>
<height>1080</height>
</field>
<field name="ThumbnailImage">
<prefix>isp_thumb_</prefix> // pay attention to this
<suffix>308</suffix>
<width>506</width>
<height>506</height>
</field>
<field name="Logo">
<prefix>isp_thumb_</prefix> // and this
<suffix>306</suffix>
<width>506</width>
<height>506</height>
</field>
And, in the other case I had, the issue is in the file length. Please do check the allowed file size on your server. In your script just do check this part :
dataStream.Write(filesBytesArray, 0, filesBytesArray.Length);
dataStream.Close();
And if you dont know, just limit the file uploaded size in your frontend section ie. HTML <input type="file"> upload element, this is good reference for limiting file size and other filter.

Related

I get HttpWebResponse with unclear characters when use a class in web application

I created a class in Windows Form application that uses HttpWebResponse.
This class gets the response from some page before login and after login and I analyze this pages.
Everything is good working at all time.
BUT
I used this class in a web application and uploaded project files in server.
I get good response from all page EXCEPT login page. Login page response contains unclear characters like this:
� �Z�N#G�v��CM�'��X؎2�LvV�e�H{��݅����t�
(ڋa���z.��2�͒H��膇
�+�9U�v�n��$pW��S�|��s�)=z����ߗ����0*T��~JuF5y�Ǟ���D��
and it happens often, that means I get sometimes normal response.
For example when extract my zip file again in server, it may work fine.
I am confused, I can't tell regular rule.
URL = "http://www.nonsense-website.com/login";
var request2 = (HttpWebRequest)WebRequest.Create(URL);
string username1 = jandoe;
string password1 = pass1234;
string postData = "hidlogin=1&username=" + username1 + "&password=" + password1;
var data = Encoding.UTF8.GetBytes(postData);
request2.Method = "POST";
request2.ContentType = "application/x-www-form-urlencoded";
request2.ContentLength = data.Length;
request2.UserAgent = "Mozilla/5.0 (Windows NT 10.0; rv:55.0) Gecko/20100101 Firefox/55.0";
request2.Headers.Add("Cookie:" + cookie);
request2.Headers.Add("Accept-Language: en-US,en;q=0.5");
request2.Headers.Add("Accept-Encoding: gzip, deflate");
request2.KeepAlive = true;
request2.Headers.Add("Upgrade-Insecure-Requests: 1");
using (var stream = request2.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
try
{
using (var response2 = (HttpWebResponse)request2.GetResponse())
{
responseString = new StreamReader(response2.GetResponseStream(),Encoding.UTF8).ReadToEnd();
AnalyzeResponse(responseString); // other function that analyze response data
}
}
catch (Exception ex)
{
WriteData("Exception in Login" + Environment.NewLine + ex.Message); // write in file
}
and my exception:
Exception in Login
Error in Parse the HTML
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
You're accepting gzip and deflate compressed responses (via Accept-Encoding), but you aren't checking whether the response is compressed. Turn on automatic decompression to have this done for you:
request2.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

I'm trying to write WebApi code to send an image file to Node.js using a POST request

I'm writing a WebApi program in C# that sends REST requests to a Node.js program written by a third party. I've got the source code for the Node program running on my laptop, but my knowledge of Node is limited. I'm using Fiddler to test sending requests. (Fiddler is similar to Postman and Curl.)
One of the things the WebApi program needs to do is to send an image file using a POST request. (The image file is associated with an order, so the order id is sent in the url.) When I send the request using Fiddler, Node returns OK and the image data is tranmitted successfully. When I send the request using the WebApi program, Node also returns OK, but the image data is not transmitted.
I would like to include some screenshots, but, apparently, I don't have enough credits to do that yet. In the successful Fiddler post, the Node.js console returns a json string containing UploadedFileMetaData data, followed by a Json string containing order_id and filename. In the WebApi case, UploadedFileMetaData is not returned. Instead, a file field containing byte data is added to the returned Json string.
I've listed below the steps that the WebApi program executes to send the request. Can anyone tell me what Fiddler is doing differently that causes the file data to be transmitted correctly? Thanks.
Variables are set with the following values:
string formDataBoundary = string.Format("----------{0:N}", Guid.NewGuid());
string contentType = "multipart/form-data; boundary=" + formDataBoundary;
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
boundary,
param.Key,
fileToUpload.FileName ?? param.Key,
fileToUpload.ContentType ?? "application/octet-stream");
string footer = "\r\n--" + boundary + "--\r\n";
(The header string resolves to the following:
------------d19a2dfc4c734778b0849649617dff78
Content-Disposition: form-data; name="file"; filename="Ducky.jpg";
Content-Type: image/jpeg)
A memory stream is created:
Stream formDataStream = new System.IO.MemoryStream();
The header, file contents, and footer are written to the memory stream:
formDataStream.Write(encoding.GetBytes(header), 0, encoding.GetByteCount(header));
formDataStream.Write(fileToUpload.File, 0, fileToUpload.File.Length);
formDataStream.Write(encoding.GetBytes(footer), 0, encoding.GetByteCount(footer));
The stream is dumped into a byte array:
formDataStream.Position = 0;
byte[] formData = new byte[formDataStream.Length];
formDataStream.Read(formData, 0, formData.Length);
formDataStream.Close();
An http request is created containing the following info:
request.Method = "POST";
request.ContentType = contentType;
request.UserAgent = userAgent; // Value doesn't really matter
request.CookieContainer = new CookieContainer(); // Will not be used
request.ContentLength = formData.Length;
The request is posted:
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(formData, 0, formData.Length);
}
I get the response using request.GetResponse(). It returns OK. The content type returned is "application/json; charset=utf-8". GetResponseStream returns 131,072 bytes.
I think here's another simple solution for you.
//// Upload api written in expressjs.
var apiUpload = "http://localhost:3000/upload";
var filePath =Server.MapPath("~/App_Data/1023.jpg");
using (var client = new WebClient())
{
var responseBytes = client.UploadFile(apiUpload, "POST", filePath);
var result = System.Text.Encoding.UTF8.GetString(responseBytes);
}
I created a simple upload API with expressjs and above sample worked properly with it.

Sending xml to SOAP web service returning error 500

I have a piece of code written in C#.Net which reads from a database, collects records, builds a SOAP envelope around them and sends them to the following URL:
https://nodeD1.production.webservices.amadeus.com/SECRETNUMBER
I am able to copy my SOAP envelope string outputted from my code and paste it into SOAPUI, and it works flawlessly. But when I try to send it to the URL through my code, I always get:
The remote server returned an error: (500) Internal Server Error.
My entire SOAP xml request (including the soap header and everything else) is a single string by the time my code is done building it, and I have tried sending to the URL using the following code:
ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertficate;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
string httpResponseString = "";
webRequest.Proxy = null; //This will result in a quicker post.
byte[] requestBytes = null;
byte[] responseBytes = null;
requestBytes = System.Text.Encoding.UTF8.GetBytes(xmlRequestString);
//Set HttpWebRequest properties
webRequest.Method = "POST";
webRequest.ContentLength = requestBytes.Length;
webRequest.ContentType = "application/soap+xml;charset=UTF-8;";
//webRequest.Headers.Add("SOAPAction: http://webservices.amadeus.com/Profile_PartialUpdateNGProfile_11.1");
//webRequest.ContentType = "text/xml";
using (Stream requestStream = webRequest.GetRequestStream())
{
requestStream.Write(requestBytes, 0, requestBytes.Length);
}
try
{
using (var response = (HttpWebResponse)webRequest.GetResponse())
{
Stream stream = response.GetResponseStream();
using (MemoryStream ms = new MemoryStream())
{
int count = 0;
do
{
byte[] buf = new byte[1024];
count = stream.Read(buf, 0, 1024);
ms.Write(buf, 0, count);
}
while (stream.CanRead && count > 0);
responseBytes = ms.ToArray();
}
}
httpResponseString = System.Text.Encoding.Default.GetString(responseBytes);
}
catch (Exception e)
{
return e.Message;
}
return httpResponseString;
Am I forgetting something obvious? I have been stuck on this problem for a couple days now and I'm not sure what it could be. I have tried commenting and uncommenting the line:
webRequest.Headers.Add("SOAPAction: http://webservices.amadeus.com/Profile_PartialUpdateNGProfile_11.1");
But no dice.
NOTE: My piece of code is an asp.net web service (so I am a web service trying to communicate with another web service), could it be something in my Web.config file that's causing this?
Looks like all I had to do in my case was change my soap action in my soap envelope from:
https://nodeD1.production.webservices.amadeus.com/SECRETNUMBER
to:
https://noded1.production.webservices.amadeus.com/SERCRETNUMBER
Thanks to Fiddler I was able to see the following message:
<faultstring>A header representing a Message Addressing Property is not valid and the message cannot be processed</faultstring>
I Googled the error message and I found a StackOverflow post about it:
Error in Amadeus Service: A header representing a Message Addressing Property is not valid and the message cannot be processed
Apparently .net doesn't like capital letters in URLs in SOAP envelopes. The thing is I thought this might be the case, but I tried with lowercase and it still failed because my SOAP envelope wasn't properly built.

Cannot download iTunes Connect Weekly Opt-In Report from autoingest using c# (The magic number in GZip header is not correct error)

We are successfully getting many of the reports from the iTunes autoingest endpoint:
https://reportingitc.apple.com/autoingestion.tft
However some of the reports, rather than returning the data directly in the body return a ZIP file and whenever we try to read the response we get:
The magic number in GZip header is not correct. Make sure you are passing in a GZip stream.
The response headers look something like the following, indicating the zip file:
{
Content-Encoding:
Content-Disposition: attachment;filename=O_S_W_XXXXXXXX_20120805.zip
filename: O_S_W_XXXXXXXX_20120805.zip
Transfer-Encoding: chunked
Content-Type: application/a-gzip
Date: Wed, 29 Aug 2012 08:54:35 GMT
Set-Cookie: JSESSIONID=XXXXXXXXXXXXXXXX; Path=/
Server: Apache-Coyote/1.1
}
But I do not really see how to access this attachment and I think the error might be something to do with the fact that I am trying to ready both the attachment and other parts of the response in one operation whereas only part of the response is actually zipped.
The code looks something like this:
HttpWebRequest w = (HttpWebRequest)WebRequest.Create(url);
w.Method = "POST";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
w.ContentLength = byteArray.Length;
using (Stream dataStream = w.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
using (WebResponse resp = w.GetResponse())
{
using (System.IO.Compression.GZipStream s = new System.IO.Compression.GZipStream(resp.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress))
{
// Just trying to read one byte causes the error.
s.ReadByte();
}
}
Any ideas greatly appreciated.
Take a look at this question and its accepted answer.
Use Fiddler to intercept the bytes on the wire (see the Inspectors tab).
As it turns out from the API: the stream is not GZipped but Zipped.
Have a look here for a library to unzip a stream in c#
At the start of your app add to overcome http 100 responses:
ServicePointManager.Expect100Continue = true;
Using that you'll implement the unzipping as follows, just after you obtaind the WebResponse:
using (ZipInputStream s = new ZipInputStream(resp.GetResponseStream()) {
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null) {
Console.WriteLine(theEntry.Name);
string directoryName = Path.GetDirectoryName(theEntry.Name);
string fileName = Path.GetFileName(theEntry.Name);
// create directory
if ( directoryName.Length > 0 ) {
Directory.CreateDirectory(directoryName);
}
if (fileName != String.Empty) {
using (FileStream streamWriter = File.Create(theEntry.Name)) {
int size = 2048;
byte[] data = new byte[2048];
while (true) {
size = s.Read(data, 0, data.Length);
if (size > 0) {
streamWriter.Write(data, 0, size);
} else {
break;
}
}
}
}
}
}
Finally figured this out!
I needed to set:
webRequest.AutomaticDecompression = DecompressionMethods.None;
Previously I had it set to try to:
w.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
And .NET was trying and failing to unzip the response before I even had a chance to read it.
I can now read the byte array and decrypt the file after it has been saved to disk.

Screen scrape an ASP.NET Page not working

I am trying to bring back the calendar events on the page at the following site: http://www.wphospital.org/News-Events/Calendar-of-Events.aspx
Notice that this site has a link called "Month" - I need to be able POST data requesting calendar events for a particular month. I cannot get this to work. Here is the code:
private static void GetData(ref string buf)
{
try
{
//First, request the search form to get the viewstate value
HttpWebRequest webRequest = default(HttpWebRequest);
webRequest = (HttpWebRequest)System.Net.WebRequest.Create("http://www.wphospital.org/News-Events/Calendar-of-Events.aspx");
StreamReader responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
string responseData = responseReader.ReadToEnd();
responseReader.Close();
//Extract the viewstate value and build out POST data
string viewState = ExtractViewState(responseData);
string eventValidation = ExtractEventValidation(responseData);
string postData = null;
postData = String.Format("ctl00$manScript={0}&__EVENTTARGET=&__EVENTARGUMENT&__LASTFOCUS=&__VIEWSTATE={1}&lng={2}&__EVENTVALIDATION={3}&ctl00$searchbox1$txtWord={4}&textfield2={5}&ctl00$plcMain$lstbxCategory={6}&ctl00$plcMain$lstbxSubCategory={7}", "ctl00$plcMain$updMonthNav|ctl00$plcMain$btnNextMonth", viewState, "en-US", eventValidation, "Search", "your search here", 0, 0);
var encoding = new ASCIIEncoding();
byte[] data = encoding.GetBytes(postData);
//Now post to the search form
webRequest = (HttpWebRequest)System.Net.WebRequest.Create("http://www.wphospital.org/News-Events/Calendar-of-Events.aspx");
webRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)";
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = data.Length;
var newStream = webRequest.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
//And read the response
responseData = responseReader.ReadToEnd();
responseReader.Close();
buf = responseData;
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
Console.Write("The server returned protocol error ");
// Get HttpWebResponse so that you can check the HTTP status code.
HttpWebResponse httpResponse = (HttpWebResponse)ex.Response;
int sc = (int)httpResponse.StatusCode;
string strsc = httpResponse.StatusCode.ToString();
}
}
}
private static string ExtractViewState(string s)
{
string viewStateNameDelimiter = "__VIEWSTATE";
string valueDelimiter = "value=\"";
int viewStateNamePosition = s.IndexOf(viewStateNameDelimiter);
int viewStateValuePosition = s.IndexOf(valueDelimiter, viewStateNamePosition);
int viewStateStartPosition = viewStateValuePosition + valueDelimiter.Length;
int viewStateEndPosition = s.IndexOf("\"", viewStateStartPosition);
return HttpUtility.UrlEncodeUnicode(s.Substring(viewStateStartPosition, viewStateEndPosition - viewStateStartPosition));
}
Can anyone point me in the right direction?
This may or may not solve your problem because I don't know exactly what the problem is when you say it's not working. But as "Al W" noted - the response from an async postback is not going to look like a straight HTML stream. So if your problem is parsing it afterwards then this might help.
I had the "opportunity" to discover this recently because I needed to rewrite that output. I'm working on a C# jQuery port and found that I was breaking WebForms pages when I tried to re-render the output stream during an async postback. I went through the client script that parses the response and figured out the format of the response.
Each panel that is updated will return a block of data that is formatted like:
"Length|Type|ID|Content"
There could be any number of these strung together. Type is "updatePanel" for UpdatePanels. ID is the UniqueID of the control, and Content is the actual HTML data. Length is equal to the number of bytes in Content, and you need to use that to parse each block, because the separator character may appear inside Content itself. So if you decided you wanted to rewrite this data before sending it back to an ASP.NET page (like I did) you need to update Length to reflect the final length of your content.
The code I used to parse and rewrite it is in Server/CsQueryHttpContext.
For POST operations, you want it to be UTF-8 encoded, so just re-do the one line
//var encoding = new ASCIIEncoding();
//byte[] data = encoding.GetBytes(postData);
//do this instead.....
byte[] data = Encoding.UTF8.GetBytes(postData);
and see if this helps you out
Below is the network trace I get in chrome when clicking the monthly button. Notice the __EVENTTARGET:ctl00$plcMain$monthBtn asp.net has a javascript framework in there that is calling a javascript:postback() method when that link is clicked, which sets the event target. That's basically how ASP.NET webforms knows which event to fire on a postback. One tricky thing here is that the web page is using an update panel so you might not get a true html response. If you can get your request to look something like this, then you should get a successful response. Hope this helps.
Request URL:http://www.wphospital.org/News-Events/Calendar-of-Events.aspx
Request Method:POST
Status Code:200 OK
Request Headers
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Content-Length:9718
Content-Type:application/x-www-form-urlencoded
Cookie:CMSPreferredCulture=en-US; ASP.NET_SessionId=h2nval45vq0q5yb0cp233huc; __utma=101137351.234148951.1312486481.1312486481.1312486481.1; __utmb=101137351.1.10.1312486481; __utmc=101137351; __utmz=101137351.1312486481.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __unam=ef169fe-131964a5f2a-24ec879b-1
Host:www.wphospital.org
Origin:http://www.wphospital.org
Proxy-Connection:keep-alive
Referer:http://www.wphospital.org/News-Events/Calendar-of-Events.aspx
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.124 Safari/534.30
X-MicrosoftAjax:Delta=true
Form Dataview URL encoded
ctl00$manScript:ctl00$plcMain$updTab|ctl00$plcMain$monthBtn
__EVENTTARGET:ctl00$plcMain$monthBtn
__EVENTARGUMENT:
__LASTFOCUS:
__VIEWSTATE:<removed for brevity>
lng:en-US
__EVENTVALIDATION:/wEWEgLbj/nSDgKt983zDgKWlOLbAQKr3LqFAwKL3uqpBwK9kfRnArDHltMCAuTk0eAHAsfniK0DAteIosMPAsiIosMPAsmIosMPAsuIosMPAoD0ookDApCbiOcPAo biOcPAombiOcPAoubiOcPyfqRx8FdqYzlnnkXcJEJZzzopJY=
ctl00$searchbox1$txtWord:Search
textfield2:Enter your search here
ctl00$plcMain$lstbxCategory:0
ctl00$plcMain$lstbxSubCategory:0
ctl00$plcMain$hdnEventCount:2

Categories