请耐心等待这个稍微冗长的描述但是我在C#屏幕上抓一个ASP.NET网页表单时遇到了一个奇怪的问题.我正在尝试的步骤如下: -
1)通过HTTPS使用基本身份验证来保护站点,因此我需要正确登录.
2)我正在页面上执行GET请求以检索__VIEWSTATE值(如果我没有设置这个东西,darn就什么都不做!)
3)登录后,有几个表单字段要完成,然后是一个提交按钮,POST将表单发送到服务器
4)当按下提交按钮时,表单将POST到服务器,响应是相同的页面和表单,但现在在表单底部有一个额外的小HTML表,我需要获取一些数据.
到目前为止,我已设法使用WebClient类对登录和表单进行排序.我使用fiddler(和firebug)来检查通常使用浏览器填写表单时发送的POST字段值.我可以成功地从POST请求获得响应,并且数据表出现在表单下方,如预期的那样.然而问题是,虽然表中填充了数据,但它填充了我不期望的数据.出现的数据是我在浏览器中正常完成表单,但是将一个特定参数(下拉列表)设置为与我在POST请求中传递给服务器的值不同的值.我已经确认使用fiddler和firebug我正在传递完全相同的POST参数,这些参数是使用Web浏览器人工完成的表单正常发送的.我现在完全不知道为什么这个参数没有被服务器"考虑"了?
一个区别是这个特定的控件是一个选择列表,它在更改时执行页面重新加载或"回发".然而,除了在表单中稍后更改其他一些选择列表内容之外,这似乎没有做任何事情.
我想我问的是,还有什么我错过了会导致这种情况吗?我完全撕掉了我的头发.有人可以帮忙吗?我已经发布了下面的代码(地址和参数被隐瞒了隐私).
// a place to store the html
string responseBody = "";
// create out web client to handle the request
using (WebClient webClient = new WebClient())
{
// space to store responses from the remote site
byte[] responseBytes;
// site uses basic authentication over HTTPS so we'll need to login
CredentialCache credentials = new CredentialCache();
credentials.Add(new Uri(Url), "Basic", new NetworkCredential(Username, Password));
// set the credentials in the web client
webClient.Credentials = credentials;
// a place for __VIEWSTATE
string viewState = "";
// try and get __VIEWSTATE from the web site
try
{
responseBytes = webClient.DownloadData(Url);
viewState = GetHtmlInputValue(Encoding.UTF8.GetString(responseBytes), "__VIEWSTATE");
}
catch (Exception e)
{
bool cancel = false;
ComponentMetaData.FireError(10, "Read web page data", "Error whilst trying to get __VIEWSTATE from web page: " + e.Message, "", 0, out cancel);
}
// add our POST parameters (don't forget the __VIEWSTATE or it won't work as its an ASP.NET web page)
NameValueCollection requestParameters = new NameValueCollection();
// add ASP.NET fields
requestParameters.Add("__EVENTTARGET", __EVENTTARGET);
requestParameters.Add("__EVENTARGUMENT", __EVENTARGUMENT);
requestParameters.Add("__LASTFOCUS", __LASTFOCUS);
// add __VIEWSTATE
requestParameters.Add("__VIEWSTATE", viewState);
// all other form parameters
requestParameters.Add("btnSubmit", btnSubmit);
/* I've hidden the rest of the parameters hidden for privacy just in case */
// see if we can connect and get data
try
{
// set content type
webClient.Headers.Clear();
webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
// 'POST' the form data using web client and hope we get a response
responseBytes = webClient.UploadValues(Url, "POST", requestParameters);
// transform the response to a string
responseBody = Encoding.UTF8.GetString(responseBytes);
}
catch (Exception e)
{
bool cancel = false;
ComponentMetaData.FireError(10, "Read web page data", "Error whilst trying to connect to web page: " + e.Message, "", 0, out cancel);
}
}
Run Code Online (Sandbox Code Playgroud)
请忽略'ComponentMetaData'引用,因为这是SSIS脚本源的一部分.
任何想法或帮助将不胜感激 - 欢呼!
RE:感谢您的快速回复,我只能对这些评论说......
有正常的ASP会话cookie,但cookie中没有值(当然除了会话ID),我认为该网站使用基本身份验证而不是表单身份验证我可以忽略cookie - 当我进入网站和获取数据返回这是好的.我想这值得一试,但我必须改变代码才能使用WebRequest类方法代替......
至于选择列表javascript,没有javascript在页面加载后改变选择列表的值.选择列表中唯一的javascript是onchange事件,用于执行"回发",这似乎只会更改表单上的其他选择列表,无论如何在最终POST中都是空的.注意我在生成POST请求时包含所有POST参数,即使它们是空的,我也包括所有'Web表单'特殊字段,如__VIEWSTATE,__ EVENTTARGET等...
我不是网络表单的专家(自己是MVC人),但网络形式的"引擎"还有什么期待吗?我已经为'application/x-www-form-urlencoded'的'Content-Type'发送了1个标题,但我尝试设置其他标题,例如从原始POST复制'User-Agent'标题但最终结束与我从服务器得到500错误,不知道为什么会发生?
这里的'GetHtmlInputValue'的代码有点简单/基本,可以做得更好但是: -
private string GetHtmlInputValue(string html, string inputID)
{
string valueDelimiter = "value=\"";
int namePosition = html.IndexOf(inputID);
int valuePosition = html.IndexOf(valueDelimiter, namePosition);
int startPosition = valuePosition + valueDelimiter.Length;
int endPosition = html.IndexOf("\"", startPosition);
return html.Substring(startPosition, endPosition - startPosition);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2843 次 |
| 最近记录: |