C# 表单上的InvokeMember(“提交”)不会重定向浏览器
我使用WebBrowser控件来测试表单提交,在这个特定的例子中,该操作是一个MVC操作,它重定向到另一个结果页 代码非常简单C# 表单上的InvokeMember(“提交”)不会重定向浏览器,c#,winforms,webbrowser-control,C#,Winforms,Webbrowser Control,我使用WebBrowser控件来测试表单提交,在这个特定的例子中,该操作是一个MVC操作,它重定向到另一个结果页 代码非常简单 void _browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { var parentForm = _my_find_form_function(); parentForm.SetAttribute("action", "http:/
void _browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var parentForm = _my_find_form_function();
parentForm.SetAttribute("action", "http://localhost/tests/TestSubmission");
parentForm.InvokeMember("submit");
}
在提交(如预期的那样工作)之后,我原以为下一个documentcompleted事件将在加载重定向页面后触发。相反,将加载相同的页面(带有表单)
有什么我遗漏的吗
谢谢好的,很抱歉耽搁了,我接着讲别的 不管怎样,这真的很粗糙,但你应该能够挑选你需要的东西 最初的想法是从发现 raisedynamicevent方法的工作方式与async nav类似,它在事件发生后监视文档的状态。当再次确定时,返回。应该处理ajax的东西。需要重新考虑一点,问题很多,但希望能帮助一些人
/// the _profileQueue was a queue of URLs i wanted to nav through and find an
/// form elem and "click" the submit button on
private async void Next()
{
Submission res = null;
if (_profileQueue.TryDequeue(out res))
{
// dirty, but hold the details of the url i'm navigating to in the Tag
_browser.Tag = res;
var cts = new CancellationTokenSource(Properties.Settings.Default.BrowserNavigationTimeout); // cancel in 10s
var html = await LoadDynamicPage(res.SiteProfile.URL, cts.Token);
// this parses the dom once loaded (awaits for the page)
ProcessSiteProfile();
Next();
}
}
// navigate and download
async Task<string> LoadDynamicPage(string url, CancellationToken token)
{
// navigate and await DocumentCompleted
var tcs = new TaskCompletionSource<bool>();
WebBrowserDocumentCompletedEventHandler handler = (s, arg) =>
tcs.TrySetResult(true);
// i'm keeping the tcs in a concurrentdictionary against the browser object
// again, this is pretty dirty but obviously felt like i needed it.
_browserTasks[_browser] = tcs;
using (token.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: true))
{
// nav to page async
this._browser.DocumentCompleted += handler;
try
{
if (!string.IsNullOrWhiteSpace(url))
{
this._browser.Navigate(url);
await tcs.Task; // wait for DocumentCompleted
}
}
finally
{
this._browser.DocumentCompleted -= handler;
}
}
// get the root element
var documentElement = this._browser.Document.GetElementsByTagName("html")[0];
// poll the current HTML for changes asynchronosly
var html = documentElement.OuterHtml;
while (true)
{
// wait asynchronously, this will throw if cancellation requested
await Task.Delay(Properties.Settings.Default.BrowserNavigationWait, token);
// continue polling if the WebBrowser is still busy
if (this._browser.IsBusy)
continue;
var htmlNow = documentElement.OuterHtml;
if (html == htmlNow)
break; // no changes detected, end the poll loop
html = htmlNow;
}
// consider the page fully rendered
token.ThrowIfCancellationRequested();
// remove from task dictionary
_browserTasks[this._browser] = null;
return html;
}
async void ProcessSiteProfile()
{
// now process submission
HtmlElement parentForm = null;
/////////////////
// parse dom to find the form you're looking for
// couple of helpers below
///////////////////////
parentForm = HtmlElementQuery(_browser.Document, "myTextFieldInput");
var sub = (_browser.Tag as Submission);
HtmlDocument doc = _browser.Document;
if (parentForm != null)
{
var elements = parentForm.GetElementsByTagName("input");
foreach (HtmlElement el in elements)
{
// If there's more than one button, you can check the
// element.InnerHTML to see if it's the one you want
if (el.GetAttribute("type").ToLower() == "submit")
{
var cts = new CancellationTokenSource(Properties.Settings.Default.BrowserNavigationTimeout); // cancel in 10s
var html = await RaiseDynamicEvent(el, "click", cts.Token);
}
}
}
}
// used to raise an event with a dom element that would cause the document to change
async Task<string> RaiseDynamicEvent(HtmlElement element, string evt, CancellationToken token)
{
// navigate and await DocumentCompleted
var tcs = new TaskCompletionSource<bool>();
WebBrowserDocumentCompletedEventHandler handler = (s, arg) =>
tcs.TrySetResult(true);
_browserTasks[_browser] = tcs;
using (token.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: true))
{
this._browser.DocumentCompleted += handler;
try
{
element.InvokeMember(evt);
try
{
await tcs.Task; // wait for DocumentCompleted
}
catch (TaskCanceledException)
{
// no the end of the world
}
}
finally
{
this._browser.DocumentCompleted -= handler;
}
}
// get the root element
var documentElement = this._browser.Document.GetElementsByTagName("html")[0];
// poll the current HTML for changes asynchronosly
var html = documentElement.OuterHtml;
while (true)
{
// wait asynchronously, this will throw if cancellation requested
await Task.Delay(500, token);
// continue polling if the WebBrowser is still busy
if (this._browser.IsBusy)
continue;
var htmlNow = documentElement.OuterHtml;
if (html == htmlNow)
break; // no changes detected, end the poll loop
html = htmlNow;
}
// consider the page fully rendered
token.ThrowIfCancellationRequested();
// remove from task dictionary
_browserTasks[this._browser] = null;
return html;
}
// couple of useful helpers
HtmlElement FindParentByElement(string elementName, HtmlElement element)
{
if (element.Parent != null)
{
if (element.Parent.TagName.ToLower() == elementName.ToLower())
{
return element.Parent;
}
else
{
return FindParentByElement(elementName, element.Parent);
}
}
else
{
return null;
}
}
HtmlElement HtmlElementQuery(HtmlDocument container, string query)
{
HtmlElement el = null;
if (query.StartsWith("#"))
{
el = container.GetElementById(query.TrimStart('#'));
}
else
{
el = container.All[query];
}
return el;
}
//_profileQueue是我想要导航并查找
///表单元素并“单击”上的提交按钮
私有异步void Next()
{
提交res=null;
if(_profileQueue.TryDequeue(out res))
{
//脏,但在标记中保留我导航到的url的详细信息
_Tag=res;
var cts=new CancellationTokenSource(Properties.Settings.Default.BrowserNavigationTimeout);//10秒后取消
var html=await LoadDynamicPage(res.SiteProfile.URL,cts.Token);
//这将在加载后解析dom(等待页面)
ProcessSiteProfile();
Next();
}
}
//导航和下载
异步任务LoadDynamicPage(字符串url、CancellationToken令牌)
{
//导航并等待文档完成
var tcs=new TaskCompletionSource();
WebBrowserDocumentCompletedEventHandler=(s,arg)=>
tcs.TrySetResult(真);
//我将tcs保存在针对浏览器对象的concurrentdictionary中
//同样,这是相当肮脏,但显然感觉我需要它。
_浏览器任务[_browser]=tcs;
使用(token.Register(()=>tcs.trysetconceled(),useSynchronizationContext:true))
{
//导航到页面异步
此._browser.DocumentCompleted+=处理程序;
尝试
{
如果(!string.IsNullOrWhiteSpace(url))
{
此._浏览器.导航(url);
wait tcs.Task;//等待文档完成
}
}
最后
{
此._browser.DocumentCompleted-=处理程序;
}
}
//获取根元素
var documentElement=this.\u browser.Document.GetElementsByTagName(“html”)[0];
//异步轮询当前HTML的更改
var html=documentElement.OuterHtml;
while(true)
{
//异步等待,如果请求取消,则将抛出
等待任务。延迟(Properties.Settings.Default.BrowserNavigationWait,令牌);
//如果WebBrowser仍然忙,请继续轮询
如果(此.\u browser.IsBusy)
继续;
var htmlNow=documentElement.OuterHtml;
如果(html==htmlNow)
break;//未检测到任何更改,结束轮询循环
html=htmlNow;
}
//考虑页面完全呈现
token.ThrowIfCancellationRequested();
//从任务字典中删除
_browserTasks[此浏览器]=空;
返回html;
}
异步void ProcessSiteProfile()
{
//现在处理提交
HtmlElement parentForm=null;
/////////////////
//解析dom以查找要查找的表单
//下面有几个助手
///////////////////////
parentForm=HtmlElementQuery(_browser.Document,“myTextFieldInput”);
var sub=(_browser.Tag作为提交);
HtmlDocument doc=\u browser.Document;
if(parentForm!=null)
{
var elements=parentForm.GetElementsByTagName(“输入”);
foreach(元素中的HtmlElement el)
{
//如果有多个按钮,您可以检查
//element.InnerHTML查看它是否是您想要的
if(el.GetAttribute(“type”).ToLower()=“提交”)
{
var cts=new CancellationTokenSource(Properties.Settings.Default.BrowserNavigationTimeout);//10秒后取消
var html=await RaiseDynamicEvent(el,“click”,cts.Token);
}
}
}
}
//用于引发具有dom元素的事件,该事件将导致文档更改
异步任务RaiseDynamicEvent(HtmleElement元素、字符串evt、CancellationToken标记)
{
//导航并等待文档完成
var tcs=new TaskCompletionSource();
WebBrowserDocumentCompletedEventHandler=(s,arg)=>
tcs.TrySetResult(真);
_浏览器任务[_browser]=tcs;
使用(token.Register(()=>tcs.trysetconceled(),useSynchronizationContext:true))
{
此._browser.DocumentCompleted+=处理程序;
尝试
{
元素调用成员(evt);
尝试
{
wait tcs.Task;//等待文档完成
}
捕获(TaskCanceledException)
{
//不,世界末日
}
}
最后
{
此._browser.DocumentCompleted-=处理程序;
}
}
//获取根元素
var documentElement=this.\u browser.Document.GetElementsByTagName(“html”)[0];
//轮询当前HTML f